Pydantic Demo

Before starting, ensure you have installed the python packages as described in the Getting Started section.

We will start with the necessary imports

from datetime import datetime, timedelta
from gmpacket.provenance import SoftwareAgent, PersonAgent, OrganizationAgent, Website, Provenance
from gmpacket.feature import (
    Feature,
    FeatureGeometry,
    FeatureProperties,
    Metric,
    MetricDimensions,
    MetricProperties,
    Stream,
    StreamHousing,
    StreamProperties,
    Trace,
    TraceProperties,
)
from gmpacket.packet import Event, GroundMotionPacket

Dealing with Provenance

person = PersonAgent.from_params("Alex Processor", 
                                 "aprocessor@datagenerator.org", 
                                 "Data Processor")
print(person)

website = Website(url="https://code.usgs.gov/ghsc/esi/groundmotion-processing/#introduction")
software = SoftwareAgent.from_params("gmprocess", "1.2.0", website)
print(software)

org_website = Website(url="https://www.datagenerator.org")
organization = OrganizationAgent.from_params("Data Generator", "Data Provider", org_website)
print(organization)

# the names of the keys are not important, but the values must be valid Person,Software, or 
# OrganizationAgent objects.
agents = {"person": person, "software": software, "organization":organization}
provenance = Provenance(agent=agents)
print(provenance)
label='Alex Processor' type={'$': 'prov:Person', 'type': 'prov:QUALIFIED_NAME'} name='Alex Processor' email='aprocessor@datagenerator.org' role='Data Processor'
label='gmprocess' type={'$': 'prov:SoftwareAgent', 'type': 'prov:QUALIFIED_NAME'} name='gmprocess' version='1.2.0' website=Website(url='https://code.usgs.gov/ghsc/esi/groundmotion-processing/#introduction', site_type='xsd:anyURI')
label='Data Generator' type={'$': 'prov:Organization', 'type': 'prov:QUALIFIED_NAME'} name='Data Generator' role='Data Provider' website=Website(url='https://www.datagenerator.org', site_type='xsd:anyURI')
prefix={'seis_prov': 'http://seisprov.org/seis_prov/0.1/#'} agent={'person': PersonAgent(label='Alex Processor', type={'$': 'prov:Person', 'type': 'prov:QUALIFIED_NAME'}, name='Alex Processor', email='aprocessor@datagenerator.org', role='Data Processor'), 'software': SoftwareAgent(label='gmprocess', type={'$': 'prov:SoftwareAgent', 'type': 'prov:QUALIFIED_NAME'}, name='gmprocess', version='1.2.0', website=Website(url='https://code.usgs.gov/ghsc/esi/groundmotion-processing/#introduction', site_type='xsd:anyURI')), 'organization': OrganizationAgent(label='Data Generator', type={'$': 'prov:Organization', 'type': 'prov:QUALIFIED_NAME'}, name='Data Generator', role='Data Provider', website=Website(url='https://www.datagenerator.org', site_type='xsd:anyURI'))}

Creating Simple Metrics

pga_props = MetricProperties(description="Peak Ground Accleration",
                           name="PGA",
                           units= "g",
                           provenance_ids= provenance.getAgents())
print(pga_props)

# for scalar values like PGA, MetricDimensions are not necessary
pga_metric = Metric(properties=pga_props, values=1.5)
print(pga_metric)
description='Peak Ground Accleration' name='PGA' units='g' provenance_ids=['person', 'software', 'organization'] time_of_peak=None
properties=MetricProperties(description='Peak Ground Accleration', name='PGA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None) dimensions=None values=1.5 std_deviations=None

Creating Complex Metrics

sa_props = MetricProperties(description="Spectral Accleration",
                             name="SA",
                             units= "g",
                             provenance_ids= provenance.getAgents())
print(sa_props)

sa_dims = MetricDimensions(number=2,
                           names=["critical damping", "period"],
                           units=["%","s"],
                           axis_values=[[5.0],[0.3, 1.0, 3.0]])
print(sa_dims)

sa_metric = Metric(properties=sa_props, dimensions=sa_dims, values=[[1.2, 1.4, 1.6]])
print(sa_metric)
description='Spectral Accleration' name='SA' units='g' provenance_ids=['person', 'software', 'organization'] time_of_peak=None
number=2 names=['critical damping', 'period'] units=['%', 's'] axis_values=[[5.0], [0.3, 1.0, 3.0]]
properties=MetricProperties(description='Spectral Accleration', name='SA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None) dimensions=MetricDimensions(number=2, names=['critical damping', 'period'], units=['%', 's'], axis_values=[[5.0], [0.3, 1.0, 3.0]]) values=[[1.2, 1.4, 1.6]] std_deviations=None

Creating Traces

end_time = datetime.utcnow()
start_time = end_time - timedelta(seconds=30)
sa_trace_props = TraceProperties(channel_code="HNE", 
                                 location_code="10", 
                                 as_recorded=True, 
                                 azimuth=90, 
                                 dip=0,
                                 start_time=start_time, 
                                 end_time=end_time)
print(sa_trace_props)

metrics = [pga_metric, sa_metric]
hne_trace = Trace(properties=sa_trace_props, metrics=metrics)
print(hne_trace)
channel_code='HNE' location_code='10' as_recorded=True azimuth=90.0 dip=0.0 start_time=datetime.datetime(2026, 1, 9, 18, 30, 46, 419654) end_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 419654)
properties=TraceProperties(channel_code='HNE', location_code='10', as_recorded=True, azimuth=90.0, dip=0.0, start_time=datetime.datetime(2026, 1, 9, 18, 30, 46, 419654), end_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 419654)) metrics=[Metric(properties=MetricProperties(description='Peak Ground Accleration', name='PGA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=None, values=1.5, std_deviations=None), Metric(properties=MetricProperties(description='Spectral Accleration', name='SA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=MetricDimensions(number=2, names=['critical damping', 'period'], units=['%', 's'], axis_values=[[5.0], [0.3, 1.0, 3.0]]), values=[[1.2, 1.4, 1.6]], std_deviations=None)]
/tmp/ipykernel_494/45128388.py:1: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
  end_time = datetime.utcnow()

Creating a Stream

stream_housing = StreamHousing(cosmos_code=10, description="A building", stream_depth=0.0)
print(stream_housing)

stream_props = StreamProperties(band_code="H", 
                                instrument_code="N", 
                                samples_per_second=100.0, 
                                stream_housing=stream_housing)
print(stream_props)

stream = Stream(properties=stream_props, traces=[hne_trace])
print(stream)
cosmos_code=10 description='A building' stream_depth=0.0 stream_location=None
band_code='H' instrument_code='N' samples_per_second=100.0 stream_housing=StreamHousing(cosmos_code=10, description='A building', stream_depth=0.0, stream_location=None)
properties=StreamProperties(band_code='H', instrument_code='N', samples_per_second=100.0, stream_housing=StreamHousing(cosmos_code=10, description='A building', stream_depth=0.0, stream_location=None)) traces=[Trace(properties=TraceProperties(channel_code='HNE', location_code='10', as_recorded=True, azimuth=90.0, dip=0.0, start_time=datetime.datetime(2026, 1, 9, 18, 30, 46, 419654), end_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 419654)), metrics=[Metric(properties=MetricProperties(description='Peak Ground Accleration', name='PGA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=None, values=1.5, std_deviations=None), Metric(properties=MetricProperties(description='Spectral Accleration', name='SA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=MetricDimensions(number=2, names=['critical damping', 'period'], units=['%', 's'], axis_values=[[5.0], [0.3, 1.0, 3.0]]), values=[[1.2, 1.4, 1.6]], std_deviations=None)])]

Creating a Feature (station)

feature_geom = FeatureGeometry(coordinates=[-124.1, 32.0, 1.1])
print(feature_geom)

feature_props = FeatureProperties(network_code="NC", 
                                  station_code="ABCD", 
                                  name="A nice place for picnics", 
                                  streams=[stream])
print(feature_props)

feature = Feature(geometry=feature_geom, properties=feature_props)
print(feature)
type='Point' coordinates=[-124.1, 32.0, 1.1]
network_code='NC' station_code='ABCD' name='A nice place for picnics' streams=[Stream(properties=StreamProperties(band_code='H', instrument_code='N', samples_per_second=100.0, stream_housing=StreamHousing(cosmos_code=10, description='A building', stream_depth=0.0, stream_location=None)), traces=[Trace(properties=TraceProperties(channel_code='HNE', location_code='10', as_recorded=True, azimuth=90.0, dip=0.0, start_time=datetime.datetime(2026, 1, 9, 18, 30, 46, 419654), end_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 419654)), metrics=[Metric(properties=MetricProperties(description='Peak Ground Accleration', name='PGA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=None, values=1.5, std_deviations=None), Metric(properties=MetricProperties(description='Spectral Accleration', name='SA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=MetricDimensions(number=2, names=['critical damping', 'period'], units=['%', 's'], axis_values=[[5.0], [0.3, 1.0, 3.0]]), values=[[1.2, 1.4, 1.6]], std_deviations=None)])])] structure_reference_orientation=None
type='Feature' geometry=FeatureGeometry(type='Point', coordinates=[-124.1, 32.0, 1.1]) properties=FeatureProperties(network_code='NC', station_code='ABCD', name='A nice place for picnics', streams=[Stream(properties=StreamProperties(band_code='H', instrument_code='N', samples_per_second=100.0, stream_housing=StreamHousing(cosmos_code=10, description='A building', stream_depth=0.0, stream_location=None)), traces=[Trace(properties=TraceProperties(channel_code='HNE', location_code='10', as_recorded=True, azimuth=90.0, dip=0.0, start_time=datetime.datetime(2026, 1, 9, 18, 30, 46, 419654), end_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 419654)), metrics=[Metric(properties=MetricProperties(description='Peak Ground Accleration', name='PGA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=None, values=1.5, std_deviations=None), Metric(properties=MetricProperties(description='Spectral Accleration', name='SA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=MetricDimensions(number=2, names=['critical damping', 'period'], units=['%', 's'], axis_values=[[5.0], [0.3, 1.0, 3.0]]), values=[[1.2, 1.4, 1.6]], std_deviations=None)])])], structure_reference_orientation=None)

Creating a Ground Motion Packet

event = Event.from_params("us2023abcd", datetime.utcnow(), 7.3, 32.1, -120.0, 35.3)
print(event)

gm_packet = GroundMotionPacket(version="0.1dev", 
                               event=event, 
                               provenance=provenance, 
                               features=[feature]
                              )
print(gm_packet)
type='Feature' properties={'id': 'us2023abcd', 'time': datetime.datetime(2026, 1, 9, 18, 31, 16, 443069), 'magnitude': 7.3} geometry={'type': 'Point', 'coordinates': [-120.0, 32.1, 35300.0]}
type='FeatureCollection' version='0.1dev' creation_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 383025) event=Event(type='Feature', properties={'id': 'us2023abcd', 'time': datetime.datetime(2026, 1, 9, 18, 31, 16, 443069), 'magnitude': 7.3}, geometry={'type': 'Point', 'coordinates': [-120.0, 32.1, 35300.0]}) provenance=Provenance(prefix={'seis_prov': 'http://seisprov.org/seis_prov/0.1/#'}, agent={'person': PersonAgent(label='Alex Processor', type={'$': 'prov:Person', 'type': 'prov:QUALIFIED_NAME'}, name='Alex Processor', email='aprocessor@datagenerator.org', role='Data Processor'), 'software': SoftwareAgent(label='gmprocess', type={'$': 'prov:SoftwareAgent', 'type': 'prov:QUALIFIED_NAME'}, name='gmprocess', version='1.2.0', website=Website(url='https://code.usgs.gov/ghsc/esi/groundmotion-processing/#introduction', site_type='xsd:anyURI')), 'organization': OrganizationAgent(label='Data Generator', type={'$': 'prov:Organization', 'type': 'prov:QUALIFIED_NAME'}, name='Data Generator', role='Data Provider', website=Website(url='https://www.datagenerator.org', site_type='xsd:anyURI'))}) features=[Feature(type='Feature', geometry=FeatureGeometry(type='Point', coordinates=[-124.1, 32.0, 1.1]), properties=FeatureProperties(network_code='NC', station_code='ABCD', name='A nice place for picnics', streams=[Stream(properties=StreamProperties(band_code='H', instrument_code='N', samples_per_second=100.0, stream_housing=StreamHousing(cosmos_code=10, description='A building', stream_depth=0.0, stream_location=None)), traces=[Trace(properties=TraceProperties(channel_code='HNE', location_code='10', as_recorded=True, azimuth=90.0, dip=0.0, start_time=datetime.datetime(2026, 1, 9, 18, 30, 46, 419654), end_time=datetime.datetime(2026, 1, 9, 18, 31, 16, 419654)), metrics=[Metric(properties=MetricProperties(description='Peak Ground Accleration', name='PGA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=None, values=1.5, std_deviations=None), Metric(properties=MetricProperties(description='Spectral Accleration', name='SA', units='g', provenance_ids=['person', 'software', 'organization'], time_of_peak=None), dimensions=MetricDimensions(number=2, names=['critical damping', 'period'], units=['%', 's'], axis_values=[[5.0], [0.3, 1.0, 3.0]]), values=[[1.2, 1.4, 1.6]], std_deviations=None)])])], structure_reference_orientation=None))]
/tmp/ipykernel_494/1597145296.py:1: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
  event = Event.from_params("us2023abcd", datetime.utcnow(), 7.3, 32.1, -120.0, 35.3)

Exporting GroundMotion Packets

print(gm_packet.as_json())

df = gm_packet.to_dataframe()
df
{"type":"FeatureCollection","version":"0.1dev","creation_time":"2026-01-09T18:31:16.383025","event":{"type":"Feature","properties":{"id":"us2023abcd","time":"2026-01-09T18:31:16.443069","magnitude":7.3},"geometry":{"type":"Point","coordinates":[-120,32.1,35300]}},"provenance":{"prefix":{"seis_prov":"http://seisprov.org/seis_prov/0.1/#"},"agent":{"person":{"prov:label":"Alex Processor","prov:type":{"$":"prov:Person","type":"prov:QUALIFIED_NAME"},"seis_prov:name":"Alex Processor","seis_prov:email":"aprocessor@datagenerator.org","seis_prov:role":"Data Processor"},"software":{"prov:label":"gmprocess","prov:type":{"$":"prov:SoftwareAgent","type":"prov:QUALIFIED_NAME"},"seis_prov:software_name":"gmprocess","seis_prov:software_version":"1.2.0","seis_prov:website":{"$":"https://code.usgs.gov/ghsc/esi/groundmotion-processing/#introduction","type":"xsd:anyURI"}},"organization":{"prov:label":"Data Generator","prov:type":{"$":"prov:Organization","type":"prov:QUALIFIED_NAME"},"seis_prov:name":"Data Generator","seis_prov:role":"Data Provider","seis_prov:website":{"$":"https://www.datagenerator.org","type":"xsd:anyURI"}}}},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-124.1,32,1.1]},"properties":{"network_code":"NC","station_code":"ABCD","name":"A nice place for picnics","streams":[{"properties":{"band_code":"H","instrument_code":"N","samples_per_second":100,"stream_housing":{"cosmos_code":10,"description":"A building","stream_depth":0,"stream_location":null}},"traces":[{"properties":{"channel_code":"HNE","location_code":"10","as_recorded":true,"azimuth":90,"dip":0,"start_time":"2026-01-09T18:30:46.419654","end_time":"2026-01-09T18:31:16.419654"},"metrics":[{"properties":{"description":"Peak Ground Accleration","name":"PGA","units":"g","provenance_ids":["person","software","organization"],"time_of_peak":null},"dimensions":null,"values":1.5,"std_deviations":null},{"properties":{"description":"Spectral Accleration","name":"SA","units":"g","provenance_ids":["person","software","organization"],"time_of_peak":null},"dimensions":{"number":2,"names":["critical damping","period"],"units":["%","s"],"axis_values":[[5],[0.3,1,3]]},"values":[[1.2,1.4,1.6]],"std_deviations":null}]}]}],"structure_reference_orientation":null}}]}
id time magnitude event_longitude event_latitude event_depth network station station_name station_longitude station_latitude station_elevation epicentral_distance_km component location PGA(g) SA(g)_critical_damping_5.0%_period_0.3s SA(g)_critical_damping_5.0%_period_1.0s SA(g)_critical_damping_5.0%_period_3.0s
0 us2023abcd 2026-01-09 18:31:16.443069 7.3 -120.0 32.1 35300.0 NC ABCD A nice place for picnics -124.1 32.0 1.1 387.346866 HNE 10 1.5 1.2 1.4 1.6