Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mth5 \ mth5 \ data \ make_mth5_from_asc.py: 69%

173 statements  

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

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

2""" 

3Created on Fri Jun 25 16:03:21 2021 

4 

5@author: jpeacock 

6 

7This module is concerned with creating mth5 files from the synthetic test data 

8 that originally came from EMTF -- test1.asc and test2.asc. Each ascii file 

9 represents five channels of data sampled at 1Hz at a synthetic station. 

10 

11TODO: Separate the handling of legacy EMTF data files, such as 

12 reading into a dataframe from oddly delimited data, as well as flipping polarities of 

13 the electric channels (possibly due to a baked in sign convention error in the legacy 

14 data), so that a simple dataframe can be passed. That will make the methods here more 

15 easily generalize to work with other dataframes. That would be useful in future when 

16 we creating synthetic data at arbitrary sample rate. 

17 

18Development Notes: 

19 Mirroring the original ascii files are: 

20 data/test1.h5 

21 data/test2.h5 

22 data/test12rr.h5 

23 

24 Also created are some files with the same data but other channel_nomenclature schemes: 

25 data/test12rr_LEMI34.h5 

26 data/test1_LEMI12.h5 

27 

28 - 20231103: Added an 8Hz up-sampled version of test1. No spectral content was added 

29 so the band between the old and new Nyquist frequencies is bogus. 

30 

31 

32 

33""" 

34# ============================================================================= 

35# Imports 

36# ============================================================================= 

37 

38import pathlib 

39from typing import List, Literal, Optional, Union 

40 

41import numpy as np 

42import pandas as pd 

43from loguru import logger 

44from mt_metadata.common.comment import Comment 

45from mt_metadata.processing.aurora import ChannelNomenclature 

46from mt_metadata.timeseries import AppliedFilter, Electric, Magnetic, Survey 

47 

48from mth5.data.paths import SyntheticTestPaths 

49from mth5.data.station_config import ( 

50 make_filters, 

51 make_station_01, 

52 make_station_02, 

53 make_station_03, 

54 make_station_04, 

55 SyntheticRun, 

56 SyntheticStation, 

57) 

58from mth5.mth5 import MTH5 

59from mth5.timeseries import ChannelTS, RunTS 

60from mth5.utils.helpers import add_filters 

61 

62 

63# ============================================================================= 

64np.random.seed(0) 

65 

66synthetic_test_paths = SyntheticTestPaths() 

67MTH5_PATH = synthetic_test_paths.mth5_path 

68 

69 

70def create_run_ts_from_synthetic_run( 

71 run: SyntheticRun, df: pd.DataFrame, channel_nomenclature: ChannelNomenclature 

72) -> RunTS: 

73 """ 

74 Loop over channels of synthetic data in df and make ChannelTS objects. 

75 

76 :param run: One-off data structure with information mth5 needs to initialize. Specifically sample_rate, filters. 

77 :type run: mth5.data.station_config.SyntheticRun 

78 :param df: time series data in columns labelled from ["ex", "ey", "hx", "hy", "hz"] 

79 :type df: pandas.DataFrame 

80 :param channel_nomenclature : Keyword corresponding to channel nomenclature mapping 

81 in CHANNEL_MAPS variable from channel_nomenclature.py module in mt_metadata. 

82 Supported values include ['default', 'lemi12', 'lemi34', 'phoenix123'] 

83 :type channel_nomenclature : string 

84 

85 :return runts: MTH5 run time series object, data and metadata bound into one. 

86 :rtype runts: RunTS 

87 

88 """ 

89 

90 ch_list = [] 

91 for i_col, col in enumerate(df.columns): 

92 data = df[col].values 

93 if col in channel_nomenclature.ex_ey: 

94 channel_metadata = Electric() 

95 channel_metadata.units = "milliVolt per kilometer" 

96 elif col in channel_nomenclature.hx_hy_hz: 

97 channel_metadata = Magnetic() 

98 channel_metadata.units = "nanotesla" 

99 else: 

100 msg = f"column {col} not in channel_nomenclature {channel_nomenclature}" 

101 logger.error(msg) 

102 raise ValueError(msg) 

103 

104 channel_metadata.component = col 

105 channel_metadata.channel_number = i_col # not required 

106 channel_metadata.sample_rate = run.run_metadata.sample_rate 

107 channel_metadata.time_period.start = run.run_metadata.time_period.start 

108 chts = ChannelTS( 

109 channel_type=channel_metadata.type, # "electric" or "magnetic" 

110 data=data, 

111 channel_metadata=channel_metadata.to_dict(), 

112 ) 

113 

114 # Set dipole properties 

115 # (Not sure how to pass this in channel_metadata when intializing) 

116 if col in channel_nomenclature.ex_ey: 

117 chts.channel_metadata.dipole_length = 50 

118 if col == channel_nomenclature.ey: 

119 chts.channel_metadata.measurement_azimuth = 90.0 

120 

121 elif col in channel_nomenclature.hx_hy_hz: 

122 if col == channel_nomenclature.hy: 

123 chts.channel_metadata.measurement_azimuth = 90.0 

124 

125 # Set filters 

126 for stage_num, filter_name in enumerate(run.filters[col], start=1): 

127 applied_filter = AppliedFilter( 

128 name=filter_name, 

129 applied=True, 

130 stage=stage_num, 

131 comments=Comment(author="system", time_stamp="2024-01-01"), 

132 ) 

133 chts.channel_metadata.add_filter(applied_filter=applied_filter) 

134 

135 ch_list.append(chts) 

136 

137 # make a RunTS object 

138 if run.run_metadata.sample_rate == 0: 

139 msg = "Run sample rate cannot be zero, something is fishy, setting to 1.0 Hz" 

140 logger.warning(msg) 

141 run.run_metadata.sample_rate = 1.0 

142 runts = RunTS(array_list=ch_list, run_metadata=run.run_metadata) 

143 

144 return runts 

145 

146 

147def get_time_series_dataframe( 

148 run: SyntheticRun, 

149 source_folder: Union[pathlib.Path, str], 

150 add_nan_values: Optional[bool] = False, 

151) -> pd.DataFrame: 

152 """ 

153 Returns time series data in a dataframe with columns named for EM field component. 

154 

155 Up-samples data to run.sample_rate, which is treated as in integer. 

156 Only tested for 8, to make 8Hz data for testing. If run.sample_rate is default (1.0) 

157 then no up-sampling takes place. 

158 

159 TODO: Move noise, and nan addition out of this method. 

160 

161 :type run: mth5.data.station_config.SyntheticRun 

162 :param run: Information needed to define/create the run 

163 :type source_folder: Optional[Union[pathlib.Path, str]] 

164 :param source_folder: Where to load the ascii time series from. This overwrites any 

165 previous value that may have been stored in the SyntheticRun 

166 :type add_nan_values: bool 

167 :param add_nan_values: If True, add some NaN, if False, do not add Nan. 

168 :rtype df: pandas.DataFrame 

169 :return df: The time series data for the synthetic run 

170 

171 """ 

172 # point to the ascii time series 

173 if source_folder: 

174 run.raw_data_path = source_folder.joinpath(run.raw_data_path.name) 

175 

176 df = run._get_timeseries_dataframe() 

177 

178 # add noise if requested 

179 for col in run.channels: 

180 if run.noise_scalars[col]: 

181 df[col] += run.noise_scalars[col] * np.random.randn(len(df)) 

182 

183 # add nan if requested 

184 if add_nan_values: 

185 for col in run.channels: 

186 for [ndx, num_nan] in run.nan_indices[col]: 

187 df.loc[ndx : ndx + num_nan, col] = np.nan 

188 return df 

189 

190 

191def create_mth5_synthetic_file( 

192 station_cfgs: List[SyntheticStation], 

193 mth5_name: Union[pathlib.Path, str], 

194 target_folder: Optional[Union[pathlib.Path, str]] = "", 

195 source_folder: Union[pathlib.Path, str] = "", 

196 plot: bool = False, 

197 add_nan_values: bool = False, 

198 file_version: Literal["0.1.0", "0.2.0"] = "0.1.0", 

199 force_make_mth5: bool = True, 

200 survey_metadata: Optional[Survey] = None, 

201): 

202 """ 

203 Creates an MTH5 from synthetic data. 

204 

205 Development Notes: 

206 20250203: This function could be made more general, so that it operates on dataframes and legacy emtf ascii files. 

207 

208 :param station_cfgs: Iterable of objects of type SyntheticStation. These are one-off 

209 data structure used to hold information mth5 needs to initialize, specifically 

210 sample_rate, filters, etc. 

211 :type station_cfgs: List[SyntheticStation] 

212 :param mth5_name: Where the mth5 will be stored. This is generated by the station_config, 

213 but may change in this method based on add_nan_values or channel_nomenclature 

214 :type mth5_name: Union[pathlib.Path, str] 

215 :param target_folder: Where the mth5 file will be stored 

216 :type target_folder: Optional[Union[pathlib.Path, str]] 

217 :param source_folder: Where the ascii source data are stored 

218 :type source_folder: Optional[Union[pathlib.Path, str]] = "", 

219 :param plot: Set to false unless you want to look at a plot of the time series 

220 :type plot: bool 

221 :param add_nan_values: If true, some np.nan are sprinkled into the time series. Intended to be used for tests. 

222 :type add_nan_values: bool 

223 :param file_version: One of the supported mth5 file versions. This is the version of mth5 to create. 

224 :type file_version: Literal["0.1.0", "0.2.0"] = "0.1.0", 

225 :param force_make_mth5: If set to true, the file will be made, even if it already exists. 

226 If false, and file already exists, skip the make job. 

227 :type force_make_mth5: bool 

228 :param survey_metadata: Option to provide survey metadata, otherwise it will be created. 

229 :type survey_metadata: Survey 

230 :return: The path to the stored h5 file. 

231 :rtype: mth5_path: pathlib.Path 

232 

233 """ 

234 nomenclatures = [x.channel_nomenclature.keyword for x in station_cfgs] 

235 unconventional_nomenclatures = [x for x in nomenclatures if x.lower() != "default"] 

236 if unconventional_nomenclatures: 

237 nomenclature_str = "_".join(unconventional_nomenclatures) 

238 else: 

239 nomenclature_str = "" 

240 

241 # determine the path to the file that will be created 

242 target_folder = _get_target_folder(target_folder=target_folder) 

243 mth5_path = target_folder.joinpath(mth5_name) 

244 mth5_path = _update_mth5_path( 

245 mth5_path, add_nan_values, channel_nomenclature=nomenclature_str 

246 ) 

247 

248 # Only create file if needed 

249 if not force_make_mth5: 

250 if mth5_path.exists(): 

251 return mth5_path 

252 

253 # create survey metadata: 

254 if not survey_metadata: 

255 survey_id = "EMTF Synthetic" 

256 survey_metadata = Survey() 

257 survey_metadata.id = survey_id 

258 

259 # open output h5 

260 with MTH5(file_version=file_version) as m: 

261 m.open_mth5(mth5_path, mode="w") 

262 _add_survey(m, survey_metadata) 

263 

264 for station_cfg in station_cfgs: 

265 station_group = m.add_station( 

266 station_cfg.station_metadata.id, 

267 station_metadata=station_cfg.station_metadata, 

268 survey=survey_id, 

269 ) 

270 

271 for run in station_cfg.runs: 

272 # run is object of type SyntheticRun 

273 df = get_time_series_dataframe( 

274 run=run, source_folder=source_folder, add_nan_values=add_nan_values 

275 ) 

276 

277 # TODO: Add handling for noise, nan, and upsampling here 

278 # (They don't belong in get_time_Series_dataframe() 

279 

280 # cast to run_ts 

281 # TODO: This could be 

282 # synthetic_run.to_run_ts(df) 

283 # but channel types for each column name must come from the Station level. 

284 runts = create_run_ts_from_synthetic_run( 

285 run, df, channel_nomenclature=station_cfg.channel_nomenclature 

286 ) 

287 runts.station_metadata.id = station_group.metadata.id 

288 

289 # plot the data 

290 if plot: 

291 runts.plot() 

292 

293 run_group = station_group.add_run(run.run_metadata.id) 

294 run_group.from_runts(runts) 

295 

296 # add filters 

297 active_filters = make_filters(as_list=True) 

298 add_filters(m, active_filters, survey_id) 

299 

300 logger.info(f"Created synthetic mth5 file: {mth5_path}") 

301 

302 return mth5_path 

303 

304 

305def _get_target_folder(target_folder: Optional[Union[pathlib.Path, str]] = ""): 

306 """ 

307 Return the target folder where an mth5 file will be created 

308 

309 :param target_folder: This is where the mth5 will be created. If this argument is null, 

310 then set to MTH5_PATH 

311 :type target_folder: Optional[Union[pathlib.Path, str]] 

312 

313 :return: the path where an mth5 file will be created 

314 :rtype: pathlib.Path 

315 

316 """ 

317 # Handle path and file name conventions 

318 if not target_folder: 

319 msg = "No target folder provided for making mth5 file" 

320 logger.warning(msg) 

321 msg = f"Setting target folder to {MTH5_PATH}" 

322 logger.info(msg) 

323 target_folder = MTH5_PATH 

324 

325 if isinstance(target_folder, str): 

326 target_folder = pathlib.Path(target_folder) 

327 

328 try: 

329 target_folder.mkdir(exist_ok=True, parents=True) 

330 except OSError: 

331 msg = "MTH5 maybe installed on a read-only file system" 

332 msg = f"{msg}: try setting `target_folder` argument when calling create_mth5_synthetic_file" 

333 logger.error(msg) 

334 return target_folder 

335 

336 

337def create_test1_h5( 

338 file_version: Optional[str] = "0.1.0", 

339 channel_nomenclature: Optional[str] = "default", 

340 target_folder: Optional[Union[str, pathlib.Path]] = MTH5_PATH, 

341 source_folder: Optional[Union[str, pathlib.Path]] = "", 

342 force_make_mth5: Optional[bool] = True, 

343) -> pathlib.Path: 

344 """ 

345 Creates an MTH5 file for a single station named "test1". 

346 

347 :param file_version: One of ["0.1.0", "0.2.0"], corresponding to the version of mth5 to create 

348 :type file_version: str 

349 :type channel_nomenclature: Optional[str] 

350 :param channel_nomenclature: Keyword corresponding to channel nomenclature mapping in CHANNEL_MAPS variable 

351 from channel_nomenclature.py module in mt_metadata. Supported values are ['default', 'lemi12', 'lemi34', 'phoenix123'] 

352 A full list is in mt_metadata/transfer_functions/processing/aurora/standards/channel_nomenclatures.json 

353 :type target_folder: Optional[Union[str, pathlib.Path]] 

354 :param target_folder: Where the mth5 file will be stored 

355 :type source_folder: Optional[Union[str, pathlib.Path]] 

356 :param source_folder: Where the ascii source data are stored 

357 :type force_make_mth5: bool 

358 :param force_make_mth5: If set to true, the file will be made, even if it already exists. 

359 If false, and file already exists, skip the make job. 

360 :rtype: pathlib.Path 

361 :return: the path to the mth5 file 

362 

363 """ 

364 station_01_params = make_station_01(channel_nomenclature=channel_nomenclature) 

365 mth5_name = station_01_params.mth5_name 

366 station_params = [ 

367 station_01_params, 

368 ] 

369 

370 mth5_path = create_mth5_synthetic_file( 

371 station_params, 

372 mth5_name, 

373 plot=False, 

374 file_version=file_version, 

375 target_folder=target_folder, 

376 source_folder=source_folder, 

377 force_make_mth5=force_make_mth5, 

378 ) 

379 return mth5_path 

380 

381 

382def create_test2_h5( 

383 file_version: Optional[str] = "0.1.0", 

384 channel_nomenclature: Optional[str] = "default", 

385 target_folder: Optional[Union[str, pathlib.Path]] = MTH5_PATH, 

386 source_folder: Optional[Union[str, pathlib.Path]] = "", 

387 force_make_mth5: Optional[bool] = True, 

388) -> pathlib.Path: 

389 """ 

390 Creates an MTH5 file for a single station named "test2". 

391 

392 :type file_version: str 

393 :param file_version: One of ["0.1.0", "0.2.0"], corresponding to the version of mth5 to create 

394 :type channel_nomenclature: Optional[str] 

395 :param channel_nomenclature: Keyword corresponding to channel nomenclature mapping in CHANNEL_MAPS variable 

396 from channel_nomenclature.py module in mt_metadata. Supported values are ['default', 'lemi12', 'lemi34', 'phoenix123'] 

397 A full list is in mt_metadata/transfer_functions/processing/aurora/standards/channel_nomenclatures.json 

398 :type target_folder: Optional[str, pathlib.Path] 

399 :param target_folder: Where the mth5 file will be stored 

400 :type source_folder: Optional[str, pathlib.Path] 

401 :param source_folder: Where the ascii source data are stored 

402 :type force_make_mth5: bool 

403 :param force_make_mth5: If set to true, the file will be made, even if it already exists. 

404 If false, and file already exists, skip the make job. 

405 :rtype: pathlib.Path 

406 :return: the path to the mth5 file 

407 """ 

408 station_02_params = make_station_02(channel_nomenclature=channel_nomenclature) 

409 mth5_name = station_02_params.mth5_name 

410 station_params = [ 

411 station_02_params, 

412 ] 

413 mth5_path = create_mth5_synthetic_file( 

414 station_params, 

415 mth5_name, 

416 plot=False, 

417 file_version=file_version, 

418 force_make_mth5=force_make_mth5, 

419 target_folder=target_folder, 

420 source_folder=source_folder, 

421 ) 

422 return mth5_path 

423 

424 

425def create_test1_h5_with_nan( 

426 file_version: Optional[str] = "0.1.0", 

427 channel_nomenclature: Optional[str] = "default", 

428 target_folder: Optional[Union[str, pathlib.Path]] = MTH5_PATH, 

429 source_folder: Optional[Union[str, pathlib.Path]] = "", 

430 force_make_mth5: Optional[bool] = True, 

431) -> pathlib.Path: 

432 """ 

433 Creates an MTH5 file for a single station named "test1" with some nan values. 

434 

435 :type file_version: str 

436 :param file_version: One of ["0.1.0", "0.2.0"], corresponding to the version of mth5 to create 

437 :type channel_nomenclature: Optional[str] 

438 :param channel_nomenclature: Keyword corresponding to channel nomenclature mapping in CHANNEL_MAPS variable 

439 from channel_nomenclature.py module in mt_metadata. Supported values are ['default', 'lemi12', 'lemi34', 'phoenix123'] 

440 A full list is in mt_metadata/transfer_functions/processing/aurora/standards/channel_nomenclatures.json 

441 :type target_folder: Optional[str, pathlib.Path] 

442 :param target_folder: Where the mth5 file will be stored 

443 :type source_folder: Optional[str, pathlib.Path] 

444 :param source_folder: Where the ascii source data are stored 

445 :rtype: pathlib.Path 

446 :return: the path to the mth5 file 

447 """ 

448 station_01_params = make_station_01(channel_nomenclature=channel_nomenclature) 

449 mth5_name = station_01_params.mth5_name 

450 station_params = [ 

451 station_01_params, 

452 ] 

453 mth5_path = create_mth5_synthetic_file( 

454 station_params, 

455 mth5_name, 

456 plot=False, 

457 add_nan_values=True, 

458 file_version=file_version, 

459 force_make_mth5=force_make_mth5, 

460 target_folder=target_folder, 

461 source_folder=source_folder, 

462 ) 

463 return mth5_path 

464 

465 

466def create_test12rr_h5( 

467 file_version: Optional[str] = "0.1.0", 

468 channel_nomenclature: Optional[str] = "default", 

469 target_folder: Optional[Union[str, pathlib.Path]] = MTH5_PATH, 

470 source_folder: Optional[Union[str, pathlib.Path]] = "", 

471 force_make_mth5: Optional[bool] = True, 

472) -> pathlib.Path: 

473 """ 

474 Creates an MTH5 file with data from two stations station named "test1" and "test2". 

475 

476 :type file_version: str 

477 :param file_version: One of ["0.1.0", "0.2.0"], corresponding to the version of mth5 to create 

478 :type channel_nomenclature: Optional[str] 

479 :param channel_nomenclature: Keyword corresponding to channel nomenclature mapping in CHANNEL_MAPS variable 

480 from channel_nomenclature.py module in mt_metadata. Supported values are ['default', 'lemi12', 'lemi34', 'phoenix123'] 

481 A full list is in mt_metadata/transfer_functions/processing/aurora/standards/channel_nomenclatures.json 

482 :type target_folder: Optional[str, pathlib.Path] 

483 :param target_folder: Where the mth5 file will be stored 

484 :type source_folder: Optional[str, pathlib.Path] 

485 :param source_folder: Where the ascii source data are stored 

486 :rtype: pathlib.Path 

487 :return: the path to the mth5 file 

488 """ 

489 station_01_params = make_station_01(channel_nomenclature=channel_nomenclature) 

490 station_02_params = make_station_02(channel_nomenclature=channel_nomenclature) 

491 station_params = [station_01_params, station_02_params] 

492 mth5_name = "test12rr.h5" 

493 mth5_path = create_mth5_synthetic_file( 

494 station_params, 

495 mth5_name, 

496 file_version=file_version, 

497 target_folder=target_folder, 

498 source_folder=source_folder, 

499 force_make_mth5=force_make_mth5, 

500 ) 

501 mth5_path = pathlib.Path(mth5_path) 

502 return mth5_path 

503 

504 

505def create_test3_h5( 

506 file_version: Optional[str] = "0.1.0", 

507 channel_nomenclature: Optional[str] = "default", 

508 target_folder: Optional[Union[str, pathlib.Path]] = MTH5_PATH, 

509 source_folder: Optional[Union[str, pathlib.Path]] = "", 

510 force_make_mth5: Optional[bool] = True, 

511) -> pathlib.Path: 

512 """ 

513 Creates an MTH5 file for a single station named "test3". 

514 This example has several runs and can be used to test looping over runs. 

515 

516 :type file_version: str 

517 :param file_version: One of ["0.1.0", "0.2.0"], corresponding to the version of mth5 to create 

518 :type channel_nomenclature: Optional[str] 

519 :param channel_nomenclature: Keyword corresponding to channel nomenclature mapping in CHANNEL_MAPS variable 

520 from channel_nomenclature.py module in mt_metadata. Supported values are ['default', 'lemi12', 'lemi34', 'phoenix123'] 

521 A full list is in mt_metadata/transfer_functions/processing/aurora/standards/channel_nomenclatures.json 

522 :type target_folder: Optional[str, pathlib.Path] 

523 :param target_folder: Where the mth5 file will be stored 

524 :type source_folder: Optional[str, pathlib.Path] 

525 :param source_folder: Where the ascii source data are stored 

526 :type force_make_mth5: bool 

527 :param force_make_mth5: If set to true, the file will be made, even if it already exists. 

528 If false, and file already exists, skip the make job. 

529 :rtype: pathlib.Path 

530 :return: the path to the mth5 file 

531 """ 

532 station_03_params = make_station_03(channel_nomenclature=channel_nomenclature) 

533 station_params = [ 

534 station_03_params, 

535 ] 

536 mth5_path = create_mth5_synthetic_file( 

537 station_params, 

538 station_params[0].mth5_name, 

539 file_version=file_version, 

540 force_make_mth5=force_make_mth5, 

541 target_folder=target_folder, 

542 source_folder=source_folder, 

543 ) 

544 return mth5_path 

545 

546 

547def create_test4_h5( 

548 file_version: Optional[str] = "0.1.0", 

549 channel_nomenclature: Optional[str] = "default", 

550 target_folder: Optional[Union[str, pathlib.Path]] = MTH5_PATH, 

551 source_folder: Optional[Union[str, pathlib.Path]] = "", 

552 force_make_mth5: Optional[bool] = True, 

553) -> pathlib.Path: 

554 """ 

555 Creates an MTH5 file for a single station named "test1", data are up-sampled to 8Hz from 

556 original 1 Hz. 

557 

558 Note: Because the 8Hz data are derived from the 1Hz, only frequencies below 0.5Hz 

559 will have valid TFs that yield the apparent resistivity of the synthetic data (100 Ohm-m). 

560 

561 :type file_version: str 

562 :param file_version: One of ["0.1.0", "0.2.0"], corresponding to the version of mth5 to create 

563 :type channel_nomenclature: Optional[str] 

564 :param channel_nomenclature: Keyword corresponding to channel nomenclature mapping in CHANNEL_MAPS variable 

565 from channel_nomenclature.py module in mt_metadata. Supported values are ['default', 'lemi12', 'lemi34', 'phoenix123'] 

566 A full list is in mt_metadata/transfer_functions/processing/aurora/standards/channel_nomenclatures.json 

567 :type target_folder: Optional[str, pathlib.Path] 

568 :param target_folder: Where the mth5 file will be stored 

569 :type source_folder: Optional[str, pathlib.Path] 

570 :param source_folder: Where the ascii source data are stored 

571 :rtype: pathlib.Path 

572 :return: the path to the mth5 file 

573 """ 

574 station_04_params = make_station_04(channel_nomenclature=channel_nomenclature) 

575 mth5_path = create_mth5_synthetic_file( 

576 [ 

577 station_04_params, 

578 ], 

579 station_04_params.mth5_name, 

580 plot=False, 

581 file_version=file_version, 

582 target_folder=target_folder, 

583 source_folder=source_folder, 

584 force_make_mth5=force_make_mth5, 

585 ) 

586 return mth5_path 

587 

588 

589def _add_survey(m: MTH5, survey_metadata: Survey) -> None: 

590 """ 

591 :type m: mth5.mth5.MTH5 

592 :param m: The mth5 object to get/set survey_id with 

593 :type survey_metadata: mt_metadata.timeseries.Survey 

594 :param survey_metadata: The survey metadata in mt_metadata container 

595 

596 """ 

597 if m.file_version == "0.1.0": 

598 # "no need to pass survey id in v 0.1.0 -- just the metadata" 

599 m.survey_group.update_metadata(survey_metadata.to_dict()) 

600 elif m.file_version == "0.2.0": 

601 m.add_survey(survey_metadata.id, survey_metadata) 

602 else: 

603 msg = f"unexpected MTH5 file_version = {m.file_version}" 

604 raise NotImplementedError(msg) 

605 return 

606 

607 

608def _update_mth5_path( 

609 mth5_path: pathlib.Path, add_nan_values: bool, channel_nomenclature: str 

610) -> pathlib.Path: 

611 """ 

612 

613 Modify the name of output h5 file based on wheter or not nan-data are included 

614 as well as channel_nomenclature if not default for all stations. 

615 

616 :param mth5_path: 

617 :param add_nan_values: 

618 :param channel_nomenclature: designator for the channel nomenclatures in the mth5 

619 :type channel_nomenclature: str 

620 

621 :return: TODO 

622 :rtype: pathlib.Path 

623 

624 """ 

625 

626 path_str = mth5_path.__str__() 

627 if add_nan_values: 

628 path_str = path_str.replace(".h5", "_nan.h5") 

629 if channel_nomenclature: 

630 if channel_nomenclature != "default": 

631 path_str = path_str.replace(".h5", f"_{channel_nomenclature}.h5") 

632 return pathlib.Path(path_str) 

633 

634 

635def main(file_version="0.1.0"): 

636 """Allow the module to be called from the command line""" 

637 create_test1_h5(file_version=file_version) 

638 create_test1_h5_with_nan(file_version=file_version) 

639 create_test2_h5(file_version=file_version) 

640 create_test12rr_h5(file_version=file_version, channel_nomenclature="lemi12") 

641 create_test3_h5(file_version=file_version) 

642 create_test4_h5(file_version=file_version) 

643 

644 

645if __name__ == "__main__": 

646 main(file_version="0.2.0") 

647 main(file_version="0.1.0")