diff --git a/ph5/clients/ph5toms.py b/ph5/clients/ph5toms.py index 3322d281..58fdc82b 100755 --- a/ph5/clients/ph5toms.py +++ b/ph5/clients/ph5toms.py @@ -140,6 +140,7 @@ class PH5toMSeed(object): def __init__(self, ph5API_object, out_dir=".", reqtype="FDSN", netcode=None, station=[], station_id=[], channel=[], + location=[], component=[], array=[], shotline=None, eventnumbers=None, length=None, starttime=None, stoptime=None, offset=None, das_sn=None, use_deploy_pickup=False, decimation=None, @@ -161,6 +162,7 @@ def __init__(self, ph5API_object, out_dir=".", reqtype="FDSN", self.sample_rate_list = sample_rate_keep self.doy_keep = doy_keep self.channel = channel + self.location = location self.netcode = netcode self.length = length self.out_dir = out_dir @@ -531,7 +533,6 @@ def create_trace(self, station_to_cut, mp=False): else: start_time = stc.starttime - nt = stc.notimecorrect if stc.sample_rate > 0: @@ -539,7 +540,6 @@ def create_trace(self, station_to_cut, mp=False): stc.sample_rate) / float(stc.sample_rate_multiplier) else: actual_sample_rate = 0 - if stc.sample_rate != 0: traces = self.ph5.cut(stc.das, start_time, stc.endtime, @@ -693,6 +693,10 @@ def create_cut(self, seed_network, ph5_station, seed_station, cha_patterns = self.channel if not ph5utils.does_pattern_exists(cha_patterns, seed_channel): return + if self.location: + loc_list = self.location + if not ph5utils.does_pattern_exists(loc_list, location): + return if self.das_sn and self.das_sn != das: return @@ -729,7 +733,6 @@ def create_cut(self, seed_network, ph5_station, seed_station, ph5api.fepoch(deploy, deploy_micro) ) station_cut_times.append(sct) - for sct in station_cut_times: start_fepoch = sct.time if self.reqtype == "SHOT" or self.reqtype == "RECEIVER": @@ -957,7 +960,6 @@ def create_cut_list(self): else: seed_station = station_list[ deployment][st_num]['id_s'] - if self.station: sta_patterns = self.station if not ph5utils.does_pattern_exists(sta_patterns, @@ -1052,6 +1054,13 @@ def get_args(): metavar="channel", default=[]) + parser.add_argument( + "--location", action="store", + type=str, dest="location", + help="Comma separated list of SEED locations to extract", + metavar="location", + default=[]) + parser.add_argument( "-c", "--component", action="store", type=str, dest="component", @@ -1188,6 +1197,8 @@ def main(): args.component = args.component.split(',') if args.channel: args.channel = args.channel.split(',') + if args.location: + args.location = args.location.split(',') args.reqtype = args.reqtype.upper() args.format = args.format.upper() @@ -1207,7 +1218,8 @@ def main(): ph5ms = PH5toMSeed(ph5API_object, out_dir=args.out_dir, reqtype=args.reqtype, netcode=args.network, station=args.sta_list, station_id=args.sta_id_list, - channel=args.channel, component=args.component, + channel=args.channel, location=args.location, + component=args.component, array=args.array, shotline=args.shotline, eventnumbers=args.eventnumbers, length=args.length, starttime=args.start_time, stoptime=args.stop_time, diff --git a/ph5/clients/tests/test_ph5toms.py b/ph5/clients/tests/test_ph5toms.py index bb047657..465c12a9 100644 --- a/ph5/clients/tests/test_ph5toms.py +++ b/ph5/clients/tests/test_ph5toms.py @@ -5,6 +5,9 @@ import unittest from ph5.clients.ph5toms import StationCut, PH5toMSeed import copy +import os +from ph5.core import ph5api +from ph5.clients.ph5availability import PH5Availability class RestrictedRequest(object): @@ -29,8 +32,155 @@ def get_restricted_request_testcase(st, et): starttime=st, endtime=et) -class TestPH5toMSeed(unittest.TestCase): +class TestPH5CUT(unittest.TestCase): + + def setUp(self): + super(TestPH5CUT, self).setUp() + self.home = os.getcwd() + self.ph5cut_object = ph5api.PH5( + path=os.path.join(self.home, 'ph5/test_data/ph5'), + nickname='master.ph5') + + def tearDown(self): + self.ph5cut_object.close() + super(TestPH5CUT, self).tearDown() + + def test_load_ph5(self): + """ + Tries to load the PH5 test file. + Checks if it is an instance of ph5.core.ph5api.PH5 + """ + self.assertTrue(isinstance(self.ph5cut_object, ph5api.PH5)) + self.assertTrue(self.ph5cut_object.ph5.isopen) + + def test_experiment_t(self): + """ + check reading of experiment table + """ + + # experiment table is initally empty + self.assertIsNone(self.ph5cut_object.Experiment_t) + # load experiment table and it shouldn't be empty + self.ph5cut_object.read_experiment_t() + self.assertIsNotNone(self.ph5cut_object.Experiment_t) + + # keys should match + keys = ['experiment_id_s', 'net_code_s', 'nickname_s', 'longname_s', + 'PIs_s', 'institutions_s', 'north_west_corner/X/value_d', + 'north_west_corner/X/units_s', 'north_west_corner/Y/value_d', + 'north_west_corner/Y/units_s', 'north_west_corner/Z/value_d', + 'north_west_corner/Z/units_s', + 'north_west_corner/coordinate_system_s', + 'north_west_corner/projection_s', + 'north_west_corner/ellipsoid_s', + 'north_west_corner/description_s', + 'south_east_corner/X/value_d', 'south_east_corner/X/units_s', + 'south_east_corner/Y/value_d', 'south_east_corner/Y/units_s', + 'south_east_corner/Z/value_d', 'south_east_corner/Z/units_s', + 'south_east_corner/coordinate_system_s', + 'south_east_corner/projection_s', + 'south_east_corner/ellipsoid_s', + 'south_east_corner/description_s', 'summary_paragraph_s', + 'time_stamp/ascii_s', 'time_stamp/epoch_l', + 'time_stamp/micro_seconds_i', 'time_stamp/type_s'] + self.assertEqual(keys, self.ph5cut_object.Experiment_t['keys']) + + # expect only one row in experiment table + self.assertEqual(1, len(self.ph5cut_object.Experiment_t['rows'])) + + # make sure experiment table matches what we think it should + experiment_t = self.ph5cut_object.Experiment_t['rows'] + experiment_t[0]['net_code_s'] + self.assertEqual(experiment_t[0]['net_code_s'], 'AA') + self.assertEqual(experiment_t[0]['experiment_id_s'], '99-999') + self.assertEqual(experiment_t[0]['nickname_s'], 'PH5 Test') + self.assertEqual(experiment_t[0]['longname_s'], 'PH5 TEST SET') + self.assertEqual(experiment_t[0]['PIs_s'], 'Derick Hess') + self.assertEqual(experiment_t[0]['institutions_s'], 'PASSCAL') + + ph5availability = PH5Availability(self.ph5cut_object) + ph5tomseed = PH5toMSeed(self.ph5cut_object, out_dir=".", + reqtype="FDSN", netcode=None, + station=[], station_id=[], + channel=[], location=['01'], + component=[], + array=None, shotline=[], + eventnumbers=[], length=None, + starttime=None, stoptime=None, + offset=None, das_sn=None, + use_deploy_pickup=True, + decimation=None, + sample_rate_keep=None, + doy_keep=None, stream=False, + reduction_velocity=-1, + notimecorrect=True, + format='MSEED') + self.ph5cut_object.read_array_t_names() + array_names = sorted(self.ph5cut_object.Array_t_names) + self.ph5cut_object.read_array_t('Array_t_001') + keys = ['id_s', 'location/X/value_d', 'location/X/units_s', + 'location/Y/value_d', 'location/Y/units_s', + 'location/Z/value_d', 'location/Z/units_s', + 'location/coordinate_system_s', 'location/projection_s', + 'location/ellipsoid_s', 'location/description_s', + 'deploy_time/ascii_s', 'deploy_time/epoch_l', + 'deploy_time/micro_seconds_i', 'deploy_time/type_s', + 'pickup_time/ascii_s', 'pickup_time/epoch_l', + 'pickup_time/micro_seconds_i', 'pickup_time/type_s', + 'das/serial_number_s', 'das/model_s', 'das/manufacturer_s', + 'das/notes_s', 'sensor/serial_number_s', 'sensor/model_s', + 'sensor/manufacturer_s', 'sensor/notes_s', 'description_s', + 'seed_band_code_s', 'sample_rate_i', + 'sample_rate_multiplier_i', 'seed_instrument_code_s', + 'seed_orientation_code_s', 'seed_location_code_s', + 'seed_station_name_s', 'channel_number_i', + 'receiver_table_n_i', 'response_table_n_i'] + + self.assertEqual(keys, + self.ph5cut_object.Array_t['Array_t_001']['keys']) + + # Block to get the table names from the array table + for array_name in array_names: + self.ph5cut_object.read_array_t(array_name) + arraybyid = self.ph5cut_object.Array_t[array_name]['byid'] + arrayorder = self.ph5cut_object.Array_t[array_name]['order'] + + for ph5_station in arrayorder: + station_list = arraybyid.get(ph5_station) + for deployment in station_list: + station_len = len(station_list[deployment]) + for st_num in range(0, station_len): + st = station_list[deployment][st_num] + ret = ph5availability.get_slc_info(st, '*', '*', '*') + if ret == -1: + continue + ph5_seed_station, ph5_loc, ph5_channel = ret + cuts = ph5tomseed.create_cut_list() + for cut in cuts: + self.assertEqual(str(cut), + 'net_code: AAexperiment_id:' + + ' 99-999station:' + + ' 8001seed_station:' + + ' 8001array_code: 008location:' + + ' 01seed_channel: HLZcomponent:' + + ' 1das: 9EEFdas_manufacturer:' + + ' reftekdas_model:' + + ' rt130sensor_type:' + + ' guralp cmg-3tstarttime:' + + ' 1463568480.0endtime:' + + ' 1463568540.0sample_rate:' + + ' 100sample_rate_multiplier:' + + ' 1notimecorrect: Truelatitude:' + + ' 34.154673longitude:' + + ' -106.916169elev:' + + ' 1403.0receiver_n_i:' + + ' 0response_n_i: 1shot_id:' + + ' Noneshot_lat: Noneshot_lng:' + + ' Noneshot_elevation: None') + + +class TestPH5toMSeed(unittest.TestCase): def test_get_nonrestricted_segments(self): """ Tests get_nonrestricted_segments() diff --git a/ph5/test_data/metadata/array_8_130.kef b/ph5/test_data/metadata/array_8_130.kef index 3546587b..e65b5e80 100644 --- a/ph5/test_data/metadata/array_8_130.kef +++ b/ph5/test_data/metadata/array_8_130.kef @@ -28,6 +28,8 @@ seed_band_code_s = H seed_instrument_code_s = L seed_orientation_code_s = Z + seed_location_code_s=01 + # 1 /Experiment_g/Sorts_g/Array_t_008 sensor/model_s = cmg-3t