Make an MTH5 from NIMS data

This notebook provides an example of how to read in NIMS (.BIN) files into an MTH5. NIMS files represent a single run.

There are two ways to do this. First, we will demonstrate how to use the automated from_nims() method in MakeMTH5. This should satisfy most users’ needs. If a more precise read is required, or if more metadata needs to be appended to the MTH5 file before archiving, then we will provide the routines needed for the older, more granular read as well afterward.

[1]:
from mth5.mth5 import MTH5
from mth5.io.nims import NIMSCollection
from mth5 import read_file
from mth5.clients import MakeMTH5

from mth5_test_data import get_test_data_path

nims_data_path = get_test_data_path("nims")

The New from_nims() Method

As of MTH5 v0.3.5, you can call from_nims() with a path to the folder containing a .BIN file and load it automatically. By default, it will then be saved in the working directory under the name from_nims.h5

NIMS Collection

We will use the NIMSCollection to assemble the .bin files into a logical order by run. The output NIMS files include all data for each channel for a single run. Therefore the collection is relatively simple.

Metadata: we need to input the survey_id to provide minimal metadata when making an MTH5 file.

The NIMSCollection.get_runs() will return a two level ordered dictionary (OrderedDict). The first level is keyed by station ID. These objects are in turn ordered dictionaries by run ID. Therefore you can loop over stations and runs.

Note: n_samples and end are estimates based on file size not the data. To get an accurate number you should read in the full file.

[2]:
nc = NIMSCollection(nims_data_path)
nc.survey_id = "test_survey"
runs = nc.get_runs(sample_rates=[1])
print(f"Found {len(runs)} station with {len(runs[list(runs.keys())[0]])} runs")
list(runs.keys())
2026-01-15T11:14:16.030467-0800 | WARNING | mth5.io.nims.nims | end_time | line: 364 | Estimating end time from n_samples
2026-01-15T11:14:16.033323-0800 | WARNING | mth5.io.nims.nims | end_time | line: 364 | Estimating end time from n_samples
Found 2 station with 1 runs
[2]:
['300', 'Mnp300']
[3]:
for run_id, run_df in runs["Mnp300"].items():
    display(run_df)
survey station run start end channel_id component fn sample_rate file_size n_samples sequence_number dipole coil_number latitude longitude elevation instrument_id calibration_fn
1 test_survey Mnp300 Mnp300a 2019-09-26 18:29:29+00:00 2019-10-01 15:03:23+00:00 1 hx,hy,hz,ex,ey,temperature C:\Users\peaco\OneDrive\Documents\GitHub\mth5_... 8 54972155 3357078 1 [109.0, 101.0] None None None None NIMS None

Build MTH5

Now that we have a logical collection of files, lets load them into an MTH5. As mentioned above, this can be handily accomplished using the from_nims() method. If you would prefer to load the metadata file by hand, you can simply loop of the stations, runs, and channels in the ordered dictionary.

There are a few things that to keep in mind if you opt for the latter method:

  • The NIMS raw files come with very little metadata, so as a user you will have to manually input most of it.

  • The resultant NIMS .bin file(s) are already calibrated into units of nT and mV/km (I think), therefore there are no filters to apply to calibrate the data.

  • Since this is a MTH5 file version 0.2.0 the filters are in the survey_group so add them there.

The process for doing this is very similar to the make_mth5_from_lemi424 example notebook. Please reference the routines there for an idea on how to accomplish a manual read.

[4]:
mth5_path = MakeMTH5.from_nims(nims_data_path, survey_id="test_survey")
2026-01-15T11:14:16.076083-0800 | WARNING | mth5.io.nims.nims | end_time | line: 364 | Estimating end time from n_samples
2026-01-15T11:14:16.080857-0800 | WARNING | mth5.io.nims.nims | end_time | line: 364 | Estimating end time from n_samples
2026-01-15T11:14:16.485519-0800 | INFO | mth5.mth5 | _initialize_file | line: 773 | Initialized MTH5 0.2.0 file C:\Users\peaco\OneDrive\Documents\GitHub\mth5_test_data\mth5_test_data\nims\from_nims.h5 in mode w
2026-01-15T11:14:22.093892-0800 | WARNING | mth5.io.nims.nims | read_nims | line: 1240 | odd number of bytes 54971209, not even blocks cutting down the data by 72 bits
2026-01-15T11:14:28.631106-0800 | INFO | mth5.mth5 | close_mth5 | line: 896 | Flushing and closing C:\Users\peaco\OneDrive\Documents\GitHub\mth5_test_data\mth5_test_data\nims\from_nims.h5
MTH5 Structure

Have a look at the MTH5 structure and make sure it looks correct.

[5]:
with MTH5() as m:
    m = m.open_mth5(mth5_path)
    print(m)
    ch_summary = m.channel_summary.to_dataframe()
    run_df = m.run_summary
/:
====================
    |- Group: Experiment
    --------------------
        |- Group: Reports
        -----------------
        |- Group: Standards
        -------------------
            --> Dataset: summary
            ......................
        |- Group: Surveys
        -----------------
            |- Group: test_survey
            ---------------------
                |- Group: Filters
                -----------------
                    |- Group: coefficient
                    ---------------------
                        |- Group: dipole_101.00
                        -----------------------
                        |- Group: dipole_106.00
                        -----------------------
                        |- Group: dipole_109.00
                        -----------------------
                        |- Group: e_analog_to_digital
                        -----------------------------
                        |- Group: h_analog_to_digital
                        -----------------------------
                        |- Group: to_mt_units
                        ---------------------
                    |- Group: fap
                    -------------
                    |- Group: fir
                    -------------
                    |- Group: time_delay
                    --------------------
                        |- Group: ex_time_offset
                        ------------------------
                        |- Group: ey_time_offset
                        ------------------------
                        |- Group: hx_time_offset
                        ------------------------
                        |- Group: hy_time_offset
                        ------------------------
                        |- Group: hz_time_offset
                        ------------------------
                    |- Group: zpk
                    -------------
                        |- Group: nims_1_pole_butterworth
                        ---------------------------------
                            --> Dataset: poles
                            ....................
                            --> Dataset: zeros
                            ....................
                        |- Group: nims_3_pole_butterworth
                        ---------------------------------
                            --> Dataset: poles
                            ....................
                            --> Dataset: zeros
                            ....................
                        |- Group: nims_5_pole_butterworth
                        ---------------------------------
                            --> Dataset: poles
                            ....................
                            --> Dataset: zeros
                            ....................
                |- Group: Reports
                -----------------
                |- Group: Standards
                -------------------
                    --> Dataset: summary
                    ......................
                |- Group: Stations
                ------------------
                    |- Group: 300
                    -------------
                        |- Group: 300b
                        --------------
                            --> Dataset: ex
                            .................
                            --> Dataset: ey
                            .................
                            --> Dataset: hx
                            .................
                            --> Dataset: hy
                            .................
                            --> Dataset: hz
                            .................
                            --> Dataset: temperature
                            ..........................
                        |- Group: Features
                        ------------------
                        |- Group: Fourier_Coefficients
                        ------------------------------
                        |- Group: Transfer_Functions
                        ----------------------------
                    |- Group: Mnp300
                    ----------------
                        |- Group: Features
                        ------------------
                        |- Group: Fourier_Coefficients
                        ------------------------------
                        |- Group: Mnp300a
                        -----------------
                            --> Dataset: ex
                            .................
                            --> Dataset: ey
                            .................
                            --> Dataset: hx
                            .................
                            --> Dataset: hy
                            .................
                            --> Dataset: hz
                            .................
                            --> Dataset: temperature
                            ..........................
                        |- Group: Transfer_Functions
                        ----------------------------
        --> Dataset: channel_summary
        ..............................
        --> Dataset: fc_summary
        .........................
        --> Dataset: tf_summary
        .........................
2026-01-15T11:14:29.013087-0800 | INFO | mth5.mth5 | close_mth5 | line: 896 | Flushing and closing C:\Users\peaco\OneDrive\Documents\GitHub\mth5_test_data\mth5_test_data\nims\from_nims.h5

Channel Summary

Have a look at the channel summary and make sure everything looks good.

[6]:
ch_summary
[6]:
survey station run latitude longitude elevation component start end n_samples sample_rate measurement_type azimuth tilt units has_data hdf5_reference run_hdf5_reference station_hdf5_reference
0 test_survey 300 300b 34.726823 -115.735015 940.0 ex 2019-10-01 16:22:01+00:00 2019-10-03 23:01:03.875000+00:00 1573944 8.0 electric 0.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
1 test_survey 300 300b 34.726823 -115.735015 940.0 ey 2019-10-01 16:22:01+00:00 2019-10-03 23:01:03.875000+00:00 1573944 8.0 electric 90.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
2 test_survey 300 300b 34.726823 -115.735015 940.0 hx 2019-10-01 16:22:01+00:00 2019-10-03 23:01:03.875000+00:00 1573944 8.0 magnetic 0.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
3 test_survey 300 300b 34.726823 -115.735015 940.0 hy 2019-10-01 16:22:01+00:00 2019-10-03 23:01:03.875000+00:00 1573944 8.0 magnetic 90.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
4 test_survey 300 300b 34.726823 -115.735015 940.0 hz 2019-10-01 16:22:01+00:00 2019-10-03 23:01:03.875000+00:00 1573944 8.0 magnetic 0.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
5 test_survey 300 300b 34.726823 -115.735015 940.0 temperature 2019-10-01 16:22:01+00:00 2019-10-03 23:01:03.875000+00:00 1573944 8.0 auxiliary 0.0 0.0 celsius True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
6 test_survey Mnp300 Mnp300a 34.726827 -115.735012 940.4 ex 2019-09-26 18:33:21+00:00 2019-10-01 15:07:07.875000+00:00 3357016 8.0 electric 0.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
7 test_survey Mnp300 Mnp300a 34.726827 -115.735012 940.4 ey 2019-09-26 18:33:21+00:00 2019-10-01 15:07:07.875000+00:00 3357016 8.0 electric 90.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
8 test_survey Mnp300 Mnp300a 34.726827 -115.735012 940.4 hx 2019-09-26 18:33:21+00:00 2019-10-01 15:07:07.875000+00:00 3357016 8.0 magnetic 0.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
9 test_survey Mnp300 Mnp300a 34.726827 -115.735012 940.4 hy 2019-09-26 18:33:21+00:00 2019-10-01 15:07:07.875000+00:00 3357016 8.0 magnetic 90.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
10 test_survey Mnp300 Mnp300a 34.726827 -115.735012 940.4 hz 2019-09-26 18:33:21+00:00 2019-10-01 15:07:07.875000+00:00 3357016 8.0 magnetic 0.0 0.0 digital counts True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>
11 test_survey Mnp300 Mnp300a 34.726827 -115.735012 940.4 temperature 2019-09-26 18:33:21+00:00 2019-10-01 15:07:07.875000+00:00 3357016 8.0 auxiliary 0.0 0.0 celsius True <HDF5 object reference> <HDF5 object reference> <HDF5 object reference>

Run Summary

[7]:
run_df
[7]:
channel_scale_factors duration end has_data input_channels mth5_path n_samples output_channels run sample_rate start station survey run_hdf5_reference station_hdf5_reference
0 {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... 196742.875 2019-10-03 23:01:03.875000+00:00 True [hx, hy] C:/Users/peaco/OneDrive/Documents/GitHub/mth5_... 1573944 [ex, ey, hz] 300b 8.0 2019-10-01 16:22:01+00:00 300 test_survey <HDF5 object reference> <HDF5 object reference>
1 {'ex': 1.0, 'ey': 1.0, 'hx': 1.0, 'hy': 1.0, '... 419626.875 2019-10-01 15:07:07.875000+00:00 True [hx, hy] C:/Users/peaco/OneDrive/Documents/GitHub/mth5_... 3357016 [ex, ey, hz] Mnp300a 8.0 2019-09-26 18:33:21+00:00 Mnp300 test_survey <HDF5 object reference> <HDF5 object reference>