Build MTH5 from USGS Geomagnetic data

Its common to look at observatory data for geomagnetic storms or to use as a remote reference. The USGS provides geomagnetic observatory data for observatories in North America. In the future this will be expanded to the various other observatories using well developed packages like geomagpy.

You will need to know ahead of time what observatories you would like to download data from, dates, and type of data. There are no wildcards. See USGS Geomagnetic webservices for more information on allowed options.

Here we will download 2 days of data from 2 different observatories for the x and y components of calibrated data (‘adjusted’).

[1]:
import pandas as pd

from mth5.clients import MakeMTH5

Create a request DataFrame

The request input is in the form of a pandas.DataFrame with the following columns

Column

Description

Options

observatory

Observatory code

BDT, BOU, TST, BRW, BRT, BSL, CMO, CMT, DED, DHT, FRD, FRN, GUA, HON, NEW, SHU, SIT, SJG, TUC, USGS, BLC, BRD, CBB, EUA, FCC, IQA, MEA, OTT, RES, SNK, STJ, VIC, YKC, HAD, HER, KAK

type

The type of data to download

variation, adjusted, quasi-definitive, definitivevariation, adjusted (default), quasi-definitive, definitive

elements

Components or elements of the geomagnetic data to download, should be a list

D, DIST, DST, E, E-E, E-N, F, G, H, SQ, SV, UK1, UK2, UK3, UK4, X, Y, ZD, DIST, DST, E, E-E, E-N, F, G, H, SQ, SV, UK1, UK2, UK3, UK4, X, Y, Z

sampling_period

Sampling period of data to download in seconds

1, 60, 3600

start

Start time (YYYY-MM-DDThh:mm:ss) in UTC time

end

End time (YYYY-MM-DDThh:mm:ss) in UTC time

[2]:
request_df = pd.DataFrame(
    {
        "observatory": ["frn", "frn", "ott", "ott"],
        "type": ["adjusted"] * 4,
        "elements": [["x", "y"]] * 4,
        "sampling_period": [1] * 4,
        "start": [
            "2022-01-01T00:00:00",
            "2022-01-03T00:00:00",
            "2022-01-01T00:00:00",
            "2022-01-03T00:00:00",
        ],
        "end": [
            "2022-01-02T00:00:00",
            "2022-01-04T00:00:00",
            "2022-01-02T00:00:00",
            "2022-01-04T00:00:00",
        ],
    }
)
[3]:
request_df
[3]:
observatory type elements sampling_period start end
0 frn adjusted [x, y] 1 2022-01-01T00:00:00 2022-01-02T00:00:00
1 frn adjusted [x, y] 1 2022-01-03T00:00:00 2022-01-04T00:00:00
2 ott adjusted [x, y] 1 2022-01-01T00:00:00 2022-01-02T00:00:00
3 ott adjusted [x, y] 1 2022-01-03T00:00:00 2022-01-04T00:00:00

Adding Run ID

When the request is input automatically run names will be assigned to different windows of time by f"sp{sampling_period}_{count:03}". So the first run is sp1_001, alternatively you can add a run column and name them as you like.

Create MTH5

Once the request is complete get the data. The file name will be created automatically as usgs_geomag_{list of observatories}_{list of elements}.h5.

Note: If the key word interact is set to True then the MTH5 stays open and the returned object is the opened MTH5 file object. If interact is set to False then the MTH5 is closed and the returned object is the path to the created file.

[4]:
mth5_object = MakeMTH5.from_usgs_geomag(request_df, mth5_version="0.2.0", interact=True)
2026-05-07T15:34:36.400006-0600 | WARNING | mth5.mth5 | open_mth5 | line: 795 | usgs_geomag_frn_ott_xy.h5 will be overwritten in 'w' mode
2026-05-07T15:34:37.440363-0600 | INFO | mth5.mth5 | _initialize_file | line: 900 | Initialized MTH5 0.2.0 file C:\Users\jpopelar\OneDrive - DOI\Documents\mtproject\mth5\docs\examples\notebooks\usgs_geomag_frn_ott_xy.h5 in mode w
                               data
2022-01-01T00:00:00.000Z  22558.020
2022-01-01T00:00:01.000Z  22558.010
2022-01-01T00:00:02.000Z  22558.039
2022-01-01T00:00:03.000Z  22558.045
2022-01-01T00:00:04.000Z  22558.071
...                             ...
2022-01-01T23:59:56.000Z  22540.641
2022-01-01T23:59:57.000Z  22540.625
2022-01-01T23:59:58.000Z  22540.638
2022-01-01T23:59:59.000Z  22540.666
2022-01-02T00:00:00.000Z  22540.685

[86402 rows x 1 columns]
                              data
2022-01-01T00:00:00.000Z  5029.007
2022-01-01T00:00:01.000Z  5029.028
2022-01-01T00:00:02.000Z  5029.061
2022-01-01T00:00:03.000Z  5029.055
2022-01-01T00:00:04.000Z  5029.054
...                            ...
2022-01-01T23:59:56.000Z  5028.165
2022-01-01T23:59:57.000Z  5028.167
2022-01-01T23:59:58.000Z  5028.152
2022-01-01T23:59:59.000Z  5028.183
2022-01-02T00:00:00.000Z  5028.166

[86402 rows x 1 columns]
2026-05-07T15:35:35.491394-0600 | WARNING | mt_timeseries.run_ts | validate_metadata | line: 1102 | sample rate of dataset 1.0 is different than metadata sample rate 0.0 updating metatdata value to 1.0
RunTS Summary:
        Survey:      USGS-GEOMAG
        Station:     Fresno
        Run:         sp1_001
        Start:       2022-01-01T00:00:00+00:00
        End:         2022-01-02T00:00:01+00:00
        Sample Rate: 1.0
        Components:  ['hx', 'hy']
                               data
2022-01-03T00:00:00.000Z  22548.540
2022-01-03T00:00:01.000Z  22548.555
2022-01-03T00:00:02.000Z  22548.555
2022-01-03T00:00:03.000Z  22548.581
2022-01-03T00:00:04.000Z  22548.594
...                             ...
2022-01-03T23:59:56.000Z  22539.686
2022-01-03T23:59:57.000Z  22539.678
2022-01-03T23:59:58.000Z  22539.665
2022-01-03T23:59:59.000Z  22539.671
2022-01-04T00:00:00.000Z  22539.629

[86402 rows x 1 columns]
                              data
2022-01-03T00:00:00.000Z  5024.867
2022-01-03T00:00:01.000Z  5024.871
2022-01-03T00:00:02.000Z  5024.885
2022-01-03T00:00:03.000Z  5024.890
2022-01-03T00:00:04.000Z  5024.887
...                            ...
2022-01-03T23:59:56.000Z  5031.129
2022-01-03T23:59:57.000Z  5031.122
2022-01-03T23:59:58.000Z  5031.133
2022-01-03T23:59:59.000Z  5031.142
2022-01-04T00:00:00.000Z  5031.138

[86402 rows x 1 columns]
2026-05-07T15:36:32.699859-0600 | WARNING | mt_timeseries.run_ts | validate_metadata | line: 1102 | sample rate of dataset 1.0 is different than metadata sample rate 0.0 updating metatdata value to 1.0
RunTS Summary:
        Survey:      USGS-GEOMAG
        Station:     Fresno
        Run:         sp1_002
        Start:       2022-01-03T00:00:00+00:00
        End:         2022-01-04T00:00:01+00:00
        Sample Rate: 1.0
        Components:  ['hx', 'hy']
2026-05-07T15:36:32.740998-0600 | INFO | mth5.groups.base | _add_group | line: 631 | StationGroup Fresno already exists, returning existing group.
2026-05-07T15:36:54.686945-0600 | INFO | mth5.mth5 | close_mth5 | line: 1035 | Flushing and closing C:\Users\jpopelar\OneDrive - DOI\Documents\mtproject\mth5\docs\examples\notebooks\usgs_geomag_frn_ott_xy.h5
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
Cell In[4], line 1
----> 1 mth5_object = MakeMTH5.from_usgs_geomag(request_df, mth5_version="0.2.0", interact=True)

File ~\AppData\Local\miniforge3\envs\mtenv\Lib\site-packages\mth5\clients\make_mth5.py:465, in MakeMTH5.from_usgs_geomag(cls, request_df, **kwargs)
    457 kw_dict = maker.get_h5_kwargs()
    459 geomag_client = USGSGeomag(
    460     save_path=maker.save_path,
    461     interact=maker.interact,
    462     **kw_dict,
    463 )
--> 465 return geomag_client.make_mth5_from_geomag(request_df)

File ~\AppData\Local\miniforge3\envs\mtenv\Lib\site-packages\mth5\clients\geomag.py:655, in USGSGeomag.make_mth5_from_geomag(self, request_df)
    644 for row in request_df.itertuples():
    645     geomag_client = GeomagClient(
    646         observatory=row.observatory,
    647         type=row.type,
   (...)    652         **{"_ch_map": {"x": "hx", "y": "hy", "z": "hz"}},
    653     )
--> 655     run = geomag_client.get_data(run_id=row.run)
    656     print(run)
    657     station_group = survey_group.stations_group.add_station(
    658         run.station_metadata.id,
    659         station_metadata=run.station_metadata,
    660     )

File ~\AppData\Local\miniforge3\envs\mtenv\Lib\site-packages\mth5\clients\geomag.py:415, in GeomagClient.get_data(self, run_id)
    406             ch[element["metadata"]["element"].lower()].append(
    407                 pd.DataFrame(
    408                     {
   (...)    412                 )
    413             )
    414     else:
--> 415         raise IOError(
    416             "Could not connect to server. Error code: "
    417             f"{request_obj.status_code}"
    418         )
    420 survey_metadata = Survey(id="USGS-GEOMAG")
    421 station_metadata = self._to_station_metadata(request_json["metadata"])

OSError: Could not connect to server. Error code: 422

Check to make sure everything was downloaded properly

[ ]:
mth5_object.channel_summary.summarize()
mth5_object.channel_summary.to_dataframe()

Have a look at a run

[ ]:
run = mth5_object.get_run("Fresno", "sp1_001", "USGS-GEOMAG")
[ ]:
run_ts = run.to_runts()
run_ts.plot()

Close the MTH5 file

IMPORTANT: Be sure to close the file, otherwise bad things can happen.

[ ]:
mth5_object.close_mth5()
[ ]: