Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mth5 \ mth5 \ clients \ make_mth5.py: 92%

98 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-27 20:09 -0800

1# -*- coding: utf-8 -*- 

2""" 

3Make MTH5 

4============ 

5 

6This module provides helper functions to make MTH5 file from various clients 

7 

8Supported Clients include: 

9 

10 * FDSN (through Obspy) 

11 * Science Base (TODO) 

12 * NCI - Australia (TODO) 

13 * Phoenix MTU-5C 

14 * Zen 

15 * LEMI 424 

16 

17 

18Updated on Wed Aug 25 19:57:00 2021 

19 

20@author: jpeacock + tronan 

21""" 

22# ============================================================================= 

23# Imports 

24# ============================================================================= 

25from pathlib import Path 

26 

27import pandas as pd 

28 

29from . import ( 

30 FDSN, 

31 LEMI424Client, 

32 MetronixClient, 

33 NIMSClient, 

34 PhoenixClient, 

35 USGSGeomag, 

36 ZenClient, 

37) 

38 

39 

40# ============================================================================= 

41 

42 

43class MakeMTH5: 

44 """ 

45 Factory class for creating MTH5 files from various data sources. 

46 

47 This class provides class methods to create MTH5 files from different 

48 magnetotelluric data acquisition systems and data repositories. 

49 

50 Parameters 

51 ---------- 

52 mth5_version : str, default "0.2.0" 

53 MTH5 file format version 

54 interact : bool, default False 

55 If True, keep file open for interactive use. If False, close file after creation. 

56 save_path : str or Path, optional 

57 Directory path to save MTH5 file. If None, uses current working directory. 

58 **kwargs : dict 

59 Additional keyword arguments for HDF5 file parameters. Any parameter 

60 starting with 'h5' will be used for HDF5 configuration. 

61 

62 Attributes 

63 ---------- 

64 h5_compression : str, default "gzip" 

65 HDF5 compression algorithm 

66 h5_compression_opts : int, default 4 

67 Compression level (0-9 for gzip) 

68 h5_shuffle : bool, default True 

69 Enable byte shuffle filter for better compression 

70 h5_fletcher32 : bool, default True 

71 Enable Fletcher32 checksum for data integrity 

72 h5_data_level : int, default 1 

73 Data processing level indicator 

74 

75 Examples 

76 -------- 

77 Create a basic MakeMTH5 instance: 

78 

79 >>> from mth5.clients import MakeMTH5 

80 >>> maker = MakeMTH5(save_path="/path/to/save") 

81 >>> print(maker) 

82 MakeMTH5 Attibutes: 

83 mth5_version: 0.2.0 

84 h5_compression: gzip 

85 ... 

86 

87 Create with custom compression: 

88 

89 >>> maker = MakeMTH5( 

90 ... save_path="/data/mt", 

91 ... h5_compression="lzf", 

92 ... h5_shuffle=False 

93 ... ) 

94 

95 See Also 

96 -------- 

97 mth5.mth5.MTH5 : Main MTH5 file interface 

98 """ 

99 

100 def __init__( 

101 self, 

102 mth5_version: str = "0.2.0", 

103 interact: bool = False, 

104 save_path: str | Path | None = None, 

105 **kwargs, 

106 ): 

107 self.mth5_version = mth5_version 

108 self.interact = interact 

109 self.save_path = save_path 

110 self.h5_compression = "gzip" 

111 self.h5_compression_opts = 4 

112 self.h5_shuffle = True 

113 self.h5_fletcher32 = True 

114 self.h5_data_level = 1 

115 self.mth5_file_mode = "w" 

116 self.mth5_filename = "make_mth5.h5" 

117 

118 for key, value in kwargs.items(): 

119 setattr(self, key, value) 

120 

121 if self.save_path is None: 

122 self.save_path = Path().cwd() 

123 

124 def __str__(self): 

125 lines = ["MakeMTH5 Attibutes:"] 

126 for key, value in self.get_h5_kwargs().items(): 

127 lines.append(f"\t{key}: {value}") 

128 

129 return "\n".join(lines) 

130 

131 def __repr__(self): 

132 return self.__str__() 

133 

134 @property 

135 def save_path(self) -> Path: 

136 """Get the save path as a Path object.""" 

137 return Path(self._save_path) 

138 

139 @save_path.setter 

140 def save_path(self, value: str | Path | None): 

141 """Set the save path, converting to Path if necessary.""" 

142 if value is None: 

143 self._save_path = Path().cwd() 

144 else: 

145 self._save_path = Path(value) 

146 if "." in self._save_path.name: 

147 self.mth5_filename = self._save_path.name 

148 self._save_path = self._save_path.parent 

149 else: 

150 if not self._save_path.exists(): 

151 self._save_path.mkdir(parents=True, exist_ok=True) 

152 

153 def get_h5_kwargs(self) -> dict: 

154 """ 

155 Extract HDF5-related keyword arguments from instance attributes. 

156 

157 Returns 

158 ------- 

159 dict 

160 Dictionary of HDF5 configuration parameters including version, 

161 compression settings, shuffle, fletcher32, and data level. 

162 

163 Examples 

164 -------- 

165 >>> maker = MakeMTH5(h5_compression="lzf", h5_data_level=2) 

166 >>> kwargs = maker.get_h5_kwargs() 

167 >>> print(kwargs["h5_compression"]) 

168 lzf 

169 """ 

170 h5_params = dict( 

171 mth5_version=self.mth5_version, 

172 h5_compression=self.h5_compression, 

173 h5_compression_opts=self.h5_compression_opts, 

174 h5_shuffle=self.h5_shuffle, 

175 h5_fletcher32=self.h5_fletcher32, 

176 h5_data_level=self.h5_data_level, 

177 mth5_file_mode=self.mth5_file_mode, 

178 ) 

179 

180 for key, value in self.__dict__.items(): 

181 if key.startswith("h5"): 

182 h5_params[key] = value 

183 

184 return h5_params 

185 

186 @classmethod 

187 def from_fdsn_client(cls, request_df: pd.DataFrame, client: str = "IRIS", **kwargs): 

188 """ 

189 Create MTH5 file from FDSN data service. 

190 

191 Pull data from an FDSN archive like IRIS using ObsPy clients. 

192 The request DataFrame specifies which data to download. 

193 

194 Parameters 

195 ---------- 

196 request_df : pd.DataFrame 

197 DataFrame with columns: 

198 

199 - 'network' : str 

200 FDSN Network code (e.g., 'IU', 'TA') 

201 - 'station' : str 

202 FDSN Station code (e.g., 'ANMO', 'CAS04') 

203 - 'location' : str 

204 FDSN Location code (e.g., '00', '') 

205 - 'channel' : str 

206 FDSN Channel code (e.g., 'LFE', 'BHZ') 

207 - 'start' : str 

208 Start time in format 'YYYY-MM-DDThh:mm:ss' 

209 - 'end' : str 

210 End time in format 'YYYY-MM-DDThh:mm:ss' 

211 

212 client : str, default "IRIS" 

213 FDSN client name (e.g., 'IRIS', 'USGS', 'NCEDC') 

214 **kwargs : dict 

215 Additional keyword arguments. HDF5 parameters should be prefixed 

216 with 'h5_' (e.g., h5_compression='gzip', h5_compression_opts=4). 

217 

218 Returns 

219 ------- 

220 mth5.mth5.MTH5 or Path 

221 MTH5 object if interact=True, otherwise Path to created file 

222 

223 Raises 

224 ------ 

225 AttributeError 

226 If the input DataFrame is not properly formatted 

227 ValueError 

228 If the DataFrame column values are invalid 

229 

230 Notes 

231 ----- 

232 If any column value is blank, any matching value will be searched. 

233 For example, leaving 'station' blank will return all stations within 

234 the specified time range. 

235 

236 Examples 

237 -------- 

238 Create a request DataFrame and download data: 

239 

240 >>> import pandas as pd 

241 >>> from mth5.clients import MakeMTH5 

242 >>> 

243 >>> # Define request 

244 >>> request_df = pd.DataFrame({ 

245 ... 'network': ['IU'], 

246 ... 'station': ['ANMO'], 

247 ... 'location': ['00'], 

248 ... 'channel': ['LF*'], 

249 ... 'start': ['2020-01-01T00:00:00'], 

250 ... 'end': ['2020-01-02T00:00:00'] 

251 ... }) 

252 >>> 

253 >>> # Create MTH5 with custom compression 

254 >>> mth5_obj = MakeMTH5.from_fdsn_client( 

255 ... request_df, 

256 ... client='IRIS', 

257 ... h5_compression_opts=1 

258 ... ) 

259 

260 See Also 

261 -------- 

262 from_fdsn_miniseed_and_stationxml : Create from existing files 

263 obspy.clients.fdsn : ObsPy FDSN client documentation 

264 """ 

265 maker = cls(**kwargs) 

266 kw_dict = maker.get_h5_kwargs() 

267 kw_dict["mth5_filename"] = maker.mth5_filename 

268 

269 fdsn_client = FDSN(client=client, **kw_dict) 

270 

271 mth5_object = fdsn_client.make_mth5_from_fdsn_client( 

272 request_df, path=maker.save_path, interact=maker.interact 

273 ) 

274 

275 return mth5_object 

276 

277 @classmethod 

278 def from_fdsn_miniseed_and_stationxml( 

279 cls, 

280 station_xml_path: str | Path, 

281 miniseed_files: str | Path | list[str | Path], 

282 save_path: str | Path | None = None, 

283 **kwargs, 

284 ): 

285 """ 

286 Create MTH5 from existing StationXML and miniSEED files. 

287 

288 Use this method when you already have StationXML and miniSEED files 

289 downloaded from an FDSN client or created locally. 

290 

291 Parameters 

292 ---------- 

293 station_xml_path : str, Path, or obspy.Inventory 

294 Full path to StationXML file or an ObsPy Inventory object 

295 miniseed_files : str, Path, list, or obspy.Stream 

296 List of miniSEED file paths or ObsPy Stream objects. Can also 

297 be a single file path or Stream object. 

298 save_path : str or Path, optional 

299 Directory to save new MTH5 file. If None, saves to current 

300 working directory. 

301 **kwargs : dict 

302 Additional keyword arguments. HDF5 parameters should be prefixed 

303 with 'h5_' (e.g., h5_compression='gzip'). 

304 

305 Returns 

306 ------- 

307 Path 

308 Path to created MTH5 file. Filename format is 

309 {network}_{station}.h5 based on unique network and station codes. 

310 

311 Raises 

312 ------ 

313 TypeError 

314 If inputs are not of correct type 

315 

316 Examples 

317 -------- 

318 Create MTH5 from existing files: 

319 

320 >>> from mth5.clients import MakeMTH5 

321 >>> from pathlib import Path 

322 >>> 

323 >>> # Define file paths 

324 >>> station_xml = Path("data/station.xml") 

325 >>> miniseed = [ 

326 ... Path("data/IU.ANMO.00.LFE.mseed"), 

327 ... Path("data/IU.ANMO.00.LFN.mseed") 

328 ... ] 

329 >>> 

330 >>> # Create MTH5 

331 >>> mth5_path = MakeMTH5.from_fdsn_miniseed_and_stationxml( 

332 ... station_xml, 

333 ... miniseed, 

334 ... save_path="output", 

335 ... h5_compression="lzf" 

336 ... ) 

337 >>> print(mth5_path) 

338 output/IU_ANMO.h5 

339 

340 Using ObsPy objects directly: 

341 

342 >>> from obspy import read, read_inventory 

343 >>> 

344 >>> inventory = read_inventory("station.xml") 

345 >>> stream = read("data/*.mseed") 

346 >>> 

347 >>> mth5_path = MakeMTH5.from_fdsn_miniseed_and_stationxml( 

348 ... inventory, 

349 ... stream, 

350 ... save_path="output" 

351 ... ) 

352 

353 See Also 

354 -------- 

355 from_fdsn_client : Download and create in one step 

356 """ 

357 maker = cls(**kwargs) 

358 kw_dict = maker.get_h5_kwargs() 

359 kw_dict["mth5_filename"] = maker.mth5_filename 

360 

361 fdsn_client = FDSN(**kw_dict) 

362 

363 return fdsn_client.make_mth5_from_inventory_and_streams( 

364 station_xml_path, miniseed_files, save_path=save_path 

365 ) 

366 

367 @classmethod 

368 def from_usgs_geomag(cls, request_df: pd.DataFrame | str | Path, **kwargs): 

369 """ 

370 Create MTH5 from USGS geomagnetic observatory data. 

371 

372 Downloads geomagnetic observatory data from USGS webservices into an 

373 MTH5 file using a request DataFrame or CSV file. 

374 

375 Parameters 

376 ---------- 

377 request_df : pd.DataFrame, str, or Path 

378 Request definition as DataFrame or path to CSV file. Required columns: 

379 

380 * **observatory** : str - Observatory code (e.g., 'BOU', 'FRN') 

381 * **type** : str - Data type: 'variation', 'adjusted', 

382 'quasi-definitive', or 'definitive' 

383 * **elements** : str - Geomagnetic elements to retrieve: 

384 D, DIST, DST, E, E-E, E-N, F, G, H, SQ, SV, UK1, UK2, UK3, UK4, 

385 X, Y, Z 

386 * **sampling_period** : int - Sample period in seconds: 1, 60, or 3600 

387 * **start** : str - Start time in YYYY-MM-DDThh:mm:ss format (UTC) 

388 * **end** : str - End time in YYYY-MM-DDThh:mm:ss format (UTC) 

389 

390 **kwargs : dict 

391 Additional keyword arguments. HDF5 parameters should be prefixed 

392 with 'h5_' (e.g., h5_compression='gzip', h5_compression_opts=1). 

393 

394 Returns 

395 ------- 

396 Path or MTH5 

397 If interact=False (default), returns Path to created MTH5 file. 

398 If interact=True, returns MTH5 object with file open. 

399 

400 Notes 

401 ----- 

402 See USGS Geomagnetism Data web service for more information: 

403 https://www.usgs.gov/tools/web-service-geomagnetism-data 

404 

405 Examples 

406 -------- 

407 Create MTH5 from USGS Boulder observatory using DataFrame: 

408 

409 >>> import pandas as pd 

410 >>> from mth5.clients import MakeMTH5 

411 >>> 

412 >>> request = pd.DataFrame([{ 

413 ... 'observatory': 'BOU', 

414 ... 'type': 'variation', 

415 ... 'elements': 'XYZF', 

416 ... 'sampling_period': 1, 

417 ... 'start': '2020-01-01T00:00:00', 

418 ... 'end': '2020-01-02T00:00:00' 

419 ... }]) 

420 >>> 

421 >>> mth5_path = MakeMTH5.from_usgs_geomag( 

422 ... request, 

423 ... h5_compression='gzip', 

424 ... h5_compression_opts=1 

425 ... ) 

426 

427 Using CSV file: 

428 

429 >>> mth5_path = MakeMTH5.from_usgs_geomag('requests.csv') 

430 

431 Multiple observatories and periods: 

432 

433 >>> request = pd.DataFrame([ 

434 ... {'observatory': 'BOU', 'type': 'variation', 

435 ... 'elements': 'XYZF', 'sampling_period': 1, 

436 ... 'start': '2020-01-01T00:00:00', 'end': '2020-01-02T00:00:00'}, 

437 ... {'observatory': 'FRN', 'type': 'variation', 

438 ... 'elements': 'XYZF', 'sampling_period': 60, 

439 ... 'start': '2020-01-01T00:00:00', 'end': '2020-01-02T00:00:00'} 

440 ... ]) 

441 >>> mth5_path = MakeMTH5.from_usgs_geomag(request) 

442 

443 See Also 

444 -------- 

445 mth5.io.usgs_geomag.USGSGeomag : USGS geomagnetic data client 

446 """ 

447 maker = cls(**kwargs) 

448 kw_dict = maker.get_h5_kwargs() 

449 

450 geomag_client = USGSGeomag( 

451 save_path=maker.save_path, 

452 interact=maker.interact, 

453 **kw_dict, 

454 ) 

455 

456 return geomag_client.make_mth5_from_geomag(request_df) 

457 

458 @classmethod 

459 def from_zen( 

460 cls, 

461 data_path: str | Path, 

462 sample_rates: list[int] = [4096, 1024, 256], 

463 calibration_path: str | Path | None = None, 

464 survey_id: str | None = None, 

465 combine: bool = True, 

466 **kwargs, 

467 ): 

468 """ 

469 Create MTH5 from Zonge ZEN data files. 

470 

471 Processes ZEN data files from a directory structure and creates an 

472 MTH5 file with organized time series data. 

473 

474 Parameters 

475 ---------- 

476 data_path : str or Path 

477 Directory where ZEN data files are stored 

478 sample_rates : list of int, default [4096, 1024, 256] 

479 Sample rates to include in Hz 

480 calibration_path : str or Path, optional 

481 Path to calibration file (amtant.cal). If None, looks for 

482 calibration file in data_path. 

483 survey_id : str, optional 

484 Survey ID to apply to all stations found under data_path. If None, 

485 attempts to extract from directory structure. 

486 combine : bool, default True 

487 If True, combine multiple runs into single run sampled at 1s 

488 **kwargs : dict 

489 Additional keyword arguments. HDF5 parameters should be prefixed 

490 with 'h5_' (e.g., h5_compression='gzip', h5_compression_opts=1). 

491 Use save_path to specify output directory. 

492 

493 Returns 

494 ------- 

495 Path 

496 Path to created MTH5 file 

497 

498 Notes 

499 ----- 

500 ZEN data is typically organized with multiple .Z3D files per station. 

501 The reader processes these files and organizes them into runs based on 

502 sampling rate and timing. 

503 

504 When combine=True, all runs are merged into a single continuous run 

505 sampled at 1 second intervals, which is useful for long-term datasets. 

506 

507 Examples 

508 -------- 

509 Create MTH5 from ZEN data directory: 

510 

511 >>> from mth5.clients import MakeMTH5 

512 >>> from pathlib import Path 

513 >>> 

514 >>> data_dir = Path("data/zen_survey") 

515 >>> mth5_path = MakeMTH5.from_zen( 

516 ... data_dir, 

517 ... sample_rates=[4096, 256], 

518 ... survey_id="MT001", 

519 ... save_path="output" 

520 ... ) 

521 

522 With calibration file and HDF5 compression: 

523 

524 >>> mth5_path = MakeMTH5.from_zen( 

525 ... "data/zen_survey", 

526 ... calibration_path="data/amtant.cal", 

527 ... survey_id="MT001", 

528 ... combine=False, 

529 ... h5_compression="gzip", 

530 ... h5_compression_opts=4 

531 ... ) 

532 

533 Process all sample rates without combining: 

534 

535 >>> mth5_path = MakeMTH5.from_zen( 

536 ... "data/zen_survey", 

537 ... sample_rates=[4096, 1024, 256, 64, 4], 

538 ... combine=False 

539 ... ) 

540 

541 See Also 

542 -------- 

543 mth5.io.zen.ZenCollection : ZEN data reader 

544 """ 

545 

546 maker = cls(**kwargs) 

547 kw_dict = maker.get_h5_kwargs() 

548 

549 zc = ZenClient( 

550 data_path, 

551 sample_rates=sample_rates, 

552 save_path=maker.save_path, 

553 calibration_path=calibration_path, 

554 **kw_dict, 

555 ) 

556 

557 return zc.make_mth5_from_zen(survey_id=survey_id, combine=combine, **kwargs) 

558 

559 @classmethod 

560 def from_phoenix( 

561 cls, 

562 data_path: str | Path, 

563 mth5_filename: str | None = None, 

564 save_path: str | Path | None = None, 

565 sample_rates: list[int] = [150, 24000], 

566 receiver_calibration_dict: str | Path | dict | None = None, 

567 sensor_calibration_dict: str | Path | dict | None = None, 

568 **kwargs, 

569 ): 

570 """ 

571 Create MTH5 from Phoenix MTU-5C data files. 

572 

573 Builds an MTH5 file from Phoenix MTU-5C data with calibration support. 

574 Requires receiver and sensor calibration files exported from EMPower 

575 software. 

576 

577 Parameters 

578 ---------- 

579 data_path : str or Path 

580 Directory where Phoenix data files are stored. Can be single station 

581 or multiple stations. 

582 mth5_filename : str, optional 

583 Filename for the MTH5 file. If None, defaults to 'from_phoenix.h5' 

584 save_path : str or Path, optional 

585 Directory to save MTH5 file. If None, saves to data_path. 

586 sample_rates : list of int, default [150, 24000] 

587 Sample rates to include in Hz 

588 receiver_calibration_dict : str, Path, or dict, optional 

589 Receiver calibration specification: 

590 

591 * str/Path: Directory containing rxcal.json files 

592 * dict: Keys are receiver IDs, values are paths to rxcal.json files 

593 

594 sensor_calibration_dict : str, Path, or dict, optional 

595 Sensor calibration specification: 

596 

597 * str/Path: Directory containing scal.json files 

598 * dict: Keys are sensor IDs, values are PhoenixCalibration objects 

599 or paths to scal.json files 

600 

601 **kwargs : dict 

602 Additional keyword arguments. HDF5 parameters should be prefixed 

603 with 'h5_' (e.g., h5_compression='gzip'). 

604 

605 Returns 

606 ------- 

607 Path 

608 Path to created MTH5 file 

609 

610 Notes 

611 ----- 

612 Phoenix data requires calibration files exported from EMPower software: 

613 

614 1. Export rxcal files (receiver calibration) to JSON 

615 2. Export scal files (sensor calibration) to JSON 

616 3. Place files in accessible directory 

617 4. Provide directory path or dict mapping to from_phoenix() 

618 

619 The method automatically matches calibration files with data based on 

620 receiver and sensor IDs. 

621 

622 Examples 

623 -------- 

624 Basic usage with calibration directories: 

625 

626 >>> from mth5.clients import MakeMTH5 

627 >>> from pathlib import Path 

628 >>> 

629 >>> data_dir = Path("data/phoenix_survey") 

630 >>> cal_dir = Path("calibrations") 

631 >>> 

632 >>> mth5_path = MakeMTH5.from_phoenix( 

633 ... data_dir, 

634 ... receiver_calibration_dict=cal_dir / "receivers", 

635 ... sensor_calibration_dict=cal_dir / "sensors", 

636 ... save_path="output" 

637 ... ) 

638 

639 With explicit filename and HDF5 compression: 

640 

641 >>> mth5_path = MakeMTH5.from_phoenix( 

642 ... "data/phoenix_survey", 

643 ... mth5_filename="MT_survey_2020.h5", 

644 ... sample_rates=[150, 24000], 

645 ... receiver_calibration_dict="calibrations/receivers", 

646 ... sensor_calibration_dict="calibrations/sensors", 

647 ... save_path="output", 

648 ... h5_compression="gzip", 

649 ... h5_compression_opts=4 

650 ... ) 

651 

652 Using explicit calibration dictionaries: 

653 

654 >>> receiver_cal = { 

655 ... 'RX001': Path('cal/rx001_cal.json'), 

656 ... 'RX002': Path('cal/rx002_cal.json') 

657 ... } 

658 >>> sensor_cal = { 

659 ... 'SN123': phoenix_cal_obj_1, 

660 ... 'SN124': phoenix_cal_obj_2 

661 ... } 

662 >>> mth5_path = MakeMTH5.from_phoenix( 

663 ... "data/phoenix_survey", 

664 ... receiver_calibration_dict=receiver_cal, 

665 ... sensor_calibration_dict=sensor_cal 

666 ... ) 

667 

668 See Also 

669 -------- 

670 mth5.io.phoenix.PhoenixClient : Phoenix data reader 

671 mth5.io.phoenix.PhoenixCalibration : Calibration file handler 

672 """ 

673 

674 maker = cls(**kwargs) 

675 kw_dict = maker.get_h5_kwargs() 

676 

677 phx_client = PhoenixClient( 

678 data_path, 

679 mth5_filename=mth5_filename, 

680 sample_rates=sample_rates, 

681 receiver_calibration_dict=receiver_calibration_dict, 

682 sensor_calibration_dict=sensor_calibration_dict, 

683 save_path=save_path, 

684 **kw_dict, 

685 ) 

686 

687 return phx_client.make_mth5_from_phoenix() 

688 

689 @classmethod 

690 def from_lemi424( 

691 cls, 

692 data_path: str | Path, 

693 survey_id: str, 

694 station_id: str, 

695 mth5_filename: str = "from_lemi424.h5", 

696 save_path: str | Path = Path().cwd(), 

697 **kwargs, 

698 ): 

699 """ 

700 Create MTH5 from LEMI-424 long period data. 

701 

702 Builds an MTH5 file from LEMI-424 instrument data on a station-by-station 

703 basis. LEMI data has limited metadata, so survey and station IDs must 

704 be provided. 

705 

706 Parameters 

707 ---------- 

708 data_path : str or Path 

709 Directory where LEMI-424 data files are stored. Can be single 

710 station or full directory. 

711 survey_id : str 

712 Survey ID to apply to all stations 

713 station_id : str 

714 Station ID for this station's data 

715 mth5_filename : str, default 'from_lemi424.h5' 

716 Filename for the MTH5 output file 

717 save_path : str or Path, default current directory 

718 Directory to save MTH5 file 

719 **kwargs : dict 

720 Additional keyword arguments. HDF5 parameters should be prefixed 

721 with 'h5_' (e.g., h5_compression='gzip'). 

722 

723 Returns 

724 ------- 

725 Path 

726 Path to created MTH5 file 

727 

728 Notes 

729 ----- 

730 LEMI-424 is a long-period magnetotelluric instrument. Data files have 

731 limited embedded metadata, requiring manual specification of survey 

732 and station information. 

733 

734 Process each station individually due to minimal automatic metadata 

735 extraction capabilities. 

736 

737 Examples 

738 -------- 

739 Create MTH5 from LEMI-424 data: 

740 

741 >>> from mth5.clients import MakeMTH5 

742 >>> from pathlib import Path 

743 >>> 

744 >>> data_dir = Path("data/lemi_mt01") 

745 >>> mth5_path = MakeMTH5.from_lemi424( 

746 ... data_dir, 

747 ... survey_id='MT2020', 

748 ... station_id='MT01', 

749 ... save_path="output" 

750 ... ) 

751 

752 With HDF5 compression: 

753 

754 >>> mth5_path = MakeMTH5.from_lemi424( 

755 ... "data/lemi_mt01", 

756 ... survey_id='MT2020', 

757 ... station_id='MT01', 

758 ... mth5_filename='MT2020_MT01.h5', 

759 ... h5_compression='gzip', 

760 ... h5_compression_opts=1 

761 ... ) 

762 

763 Multiple stations (process individually): 

764 

765 >>> for station in ['MT01', 'MT02', 'MT03']: 

766 ... data_dir = Path(f"data/lemi_{station.lower()}") 

767 ... mth5_path = MakeMTH5.from_lemi424( 

768 ... data_dir, 

769 ... survey_id='MT2020', 

770 ... station_id=station, 

771 ... mth5_filename=f'MT2020_{station}.h5', 

772 ... save_path="output" 

773 ... ) 

774 

775 See Also 

776 -------- 

777 mth5.io.lemi424.LEMI424Client : LEMI-424 data reader 

778 """ 

779 maker = cls(**kwargs) 

780 kw_dict = maker.get_h5_kwargs() 

781 kw_dict.pop("mth5_filename", None) 

782 kw_dict.pop("save_path", None) 

783 

784 lemi_client = LEMI424Client( 

785 data_path, 

786 save_path=save_path, 

787 mth5_filename=mth5_filename, 

788 **kw_dict, 

789 ) 

790 

791 return lemi_client.make_mth5_from_lemi424(survey_id, station_id) 

792 

793 @classmethod 

794 def from_metronix( 

795 cls, 

796 data_path: str | Path, 

797 sample_rates: list[float] = [128], 

798 mth5_filename: str | None = None, 

799 save_path: str | Path | None = None, 

800 run_name_zeros: int = 0, 

801 **kwargs, 

802 ): 

803 """ 

804 Create MTH5 from Metronix Geophysics ATSS + JSON files. 

805 

806 Builds an MTH5 file from Metronix data in their new folder structure 

807 format with ATSS time series and JSON metadata files. 

808 

809 Parameters 

810 ---------- 

811 data_path : str or Path 

812 Highest level directory to archive data from, usually the survey 

813 level. For single station, use station folder path. 

814 sample_rates : list of float, default [128] 

815 Sample rates to archive in samples/second 

816 mth5_filename : str, optional 

817 Filename for the MTH5 file. If None, automatically generated from 

818 survey/station information. 

819 save_path : str or Path, optional 

820 Directory to save MTH5 file. If None, saves to current working 

821 directory. 

822 run_name_zeros : int, default 0 

823 Number of zeros for zero-padding in run names. Run names formatted 

824 as 'sr{sample_rate}_{run_id:0{run_name_zeros}}'. If 0, uses 

825 original run names (e.g., 'run_0001'). 

826 **kwargs : dict 

827 Additional keyword arguments. HDF5 parameters should be prefixed 

828 with 'h5_' (e.g., h5_compression='gzip'). 

829 

830 Returns 

831 ------- 

832 Path 

833 Path to created MTH5 file 

834 

835 Notes 

836 ----- 

837 Metronix Geophysics uses a specific folder structure with ATSS binary 

838 files and JSON metadata. The reader processes this structure and 

839 organizes data by survey, station, and run. 

840 

841 Run naming can be customized with run_name_zeros: 

842 - run_name_zeros=0: Keep original names like 'run_0001' 

843 - run_name_zeros=4: Format as 'sr128_0001' 

844 - run_name_zeros=2: Format as 'sr128_01' 

845 

846 Examples 

847 -------- 

848 Create MTH5 from Metronix survey data: 

849 

850 >>> from mth5.clients import MakeMTH5 

851 >>> from pathlib import Path 

852 >>> 

853 >>> data_dir = Path("data/metronix_survey") 

854 >>> mth5_path = MakeMTH5.from_metronix( 

855 ... data_dir, 

856 ... sample_rates=[128, 4096], 

857 ... save_path="output" 

858 ... ) 

859 

860 With custom run naming and compression: 

861 

862 >>> mth5_path = MakeMTH5.from_metronix( 

863 ... "data/metronix_survey", 

864 ... sample_rates=[128], 

865 ... mth5_filename="survey_2020.h5", 

866 ... run_name_zeros=4, 

867 ... h5_compression="gzip", 

868 ... h5_compression_opts=4 

869 ... ) 

870 

871 Single station with original run names: 

872 

873 >>> mth5_path = MakeMTH5.from_metronix( 

874 ... "data/metronix_survey/Station_001", 

875 ... sample_rates=[128, 512], 

876 ... run_name_zeros=0, 

877 ... save_path="output" 

878 ... ) 

879 

880 Multiple sample rates with formatted names: 

881 

882 >>> mth5_path = MakeMTH5.from_metronix( 

883 ... "data/metronix_survey", 

884 ... sample_rates=[32, 128, 512, 4096], 

885 ... run_name_zeros=3, 

886 ... mth5_filename="mt_data.h5" 

887 ... ) 

888 

889 See Also 

890 -------- 

891 mth5.io.metronix.MetronixClient : Metronix data reader 

892 """ 

893 maker = cls(**kwargs) 

894 kw_dict = maker.get_h5_kwargs() 

895 

896 metronix_client = MetronixClient( 

897 data_path, 

898 sample_rates=sample_rates, 

899 save_path=save_path, 

900 mth5_filename=mth5_filename, 

901 **kw_dict, 

902 ) 

903 

904 return metronix_client.make_mth5_from_metronix(run_name_zeros=run_name_zeros) 

905 

906 @classmethod 

907 def from_nims( 

908 cls, 

909 data_path, 

910 sample_rates=[4096, 1024, 256], 

911 save_path=None, 

912 calibration_path=None, 

913 survey_id=None, 

914 combine=True, 

915 **kwargs, 

916 ): 

917 """ 

918 Create an MTH5 from nims data. 

919 

920 Any H5 file parameters like compression, shuffle, etc need to have a 

921 prefix of 'h5'. For example h5_compression='gzip'. 

922 

923 >>> MakeMTH5.from_nims( 

924 data_path, **{'h5_compression_opts': 1} 

925 ) 

926 

927 :param data_path: directory to where data are stored 

928 :type data_path: Path, str 

929 :param sample_rates: sample rates to include, 

930 defaults to [4096, 1024, 256] 

931 :type sample_rates: list, optional 

932 :param save_path: path to save H5 file to, defaults to None which will 

933 place the file in `data_path` 

934 :type save_path: str or Path, optional 

935 :param calibration_path: path to calibration file amtant.cal, 

936 defaults to None 

937 :type calibration_path: str or Path, optional 

938 :param survey_id: survey ID to apply to all station found under 

939 `data_path`, defaults to None 

940 :type survey_id: string 

941 :param combine: if True combine the runs into a single run sampled at 1s, 

942 defaults to True 

943 :type combine: bool 

944 :return: MTH5 file name 

945 :rtype: Path 

946 

947 """ 

948 

949 maker = cls(**kwargs) 

950 kw_dict = maker.get_h5_kwargs() 

951 

952 nc = NIMSClient( 

953 data_path, 

954 sample_rates=sample_rates, 

955 save_path=save_path, 

956 calibration_path=calibration_path, 

957 **kw_dict, 

958 ) 

959 

960 return nc.make_mth5_from_nims(survey_id=survey_id, combine=combine, **kwargs)