from unittest import TestCase from pathlib import Path from sohstationviewer.model.mseed_data.mseed import MSeed from sohstationviewer.model.general_data.general_data import \ ProcessingDataError TEST_DATA_DIR = Path(__file__).resolve().parent.parent.parent.joinpath( 'test_data') pegasus_data = TEST_DATA_DIR.joinpath("Pegasus-sample") q330_data = TEST_DATA_DIR.joinpath("Q330-sample") blockettes_data = TEST_DATA_DIR.joinpath("Q330_unimplemented_ascii_block") multiplex_data = TEST_DATA_DIR.joinpath("Q330_multiplex") centaur_data = TEST_DATA_DIR.joinpath("Centaur-sample") class TestMSeed(TestCase): def test_path_not_exist(self): # raise exception when path not exist args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': '_', 'on_unittest': True } with self.assertRaises(ProcessingDataError) as context: MSeed(**args) self.assertEqual( str(context.exception), "Path '_' not exist" ) def test_read_text_only(self): # There is no station recognized, add text to key 'TEXT' in log_data args = { 'data_type': 'Pegasus', 'is_multiplex': False, 'folder': pegasus_data, 'req_soh_chans': ['_'], 'on_unittest': True } obj = MSeed(**args) self.assertEqual(list(obj.log_data.keys()), ['TEXT']) self.assertEqual(len(obj.log_data['TEXT']), 2) self.assertEqual( obj.log_data['TEXT'][0][:100], '\n\n** STATE OF HEALTH: XX.KC01...D.2020.130' '\n2020-05-09 00:00:09.839 UTC: I(TimingThread): timing unce') self.assertEqual( obj.log_data['TEXT'][1][:100], '\n\n** STATE OF HEALTH: XX.KC01...D.2020.129' '\n2020-05-08 22:55:45.390 UTC: I(Initializations): Firmware') def test_read_text_with_soh(self): # text get station from soh data with TXT as channel to add to log_data args = { 'data_type': 'Pegasus', 'is_multiplex': False, 'folder': pegasus_data, 'req_soh_chans': ['VE1'], 'on_unittest': True } obj = MSeed(**args) self.assertEqual(list(obj.log_data.keys()), ['TEXT', 'KC01']) self.assertEqual(len(obj.log_data['TEXT']), 0) self.assertEqual(list(obj.log_data['KC01'].keys()), ['TXT']) self.assertEqual(len(obj.log_data['KC01']['TXT']), 2) self.assertEqual( obj.log_data['KC01']['TXT'][0][:100], '\n\n** STATE OF HEALTH: XX.KC01...D.2020.130' '\n2020-05-09 00:00:09.839 UTC: I(TimingThread): timing unce') self.assertEqual( obj.log_data['KC01']['TXT'][1][:100], '\n\n** STATE OF HEALTH: XX.KC01...D.2020.129' '\n2020-05-08 22:55:45.390 UTC: I(Initializations): Firmware') def test_read_text_with_waveform(self): # text get station from waveform data with TXT as channel to add to # log_data args = { 'data_type': 'Pegasus', 'is_multiplex': False, 'folder': pegasus_data, 'req_wf_chans': ['HH1'], 'req_soh_chans': ['_'], 'on_unittest': True } obj = MSeed(**args) self.assertEqual(list(obj.log_data.keys()), ['TEXT', 'KC01']) self.assertEqual(len(obj.log_data['TEXT']), 0) self.assertEqual(list(obj.log_data['KC01'].keys()), ['TXT']) self.assertEqual(len(obj.log_data['KC01']['TXT']), 2) self.assertEqual( obj.log_data['KC01']['TXT'][0][:100], '\n\n** STATE OF HEALTH: XX.KC01...D.2020.130' '\n2020-05-09 00:00:09.839 UTC: I(TimingThread): timing unce') self.assertEqual( obj.log_data['KC01']['TXT'][1][:100], '\n\n** STATE OF HEALTH: XX.KC01...D.2020.129' '\n2020-05-08 22:55:45.390 UTC: I(Initializations): Firmware') def test_read_ascii(self): # info is text wrapped in mseed format args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': q330_data, 'req_soh_chans': ['LOG'], } obj = MSeed(**args) self.assertEqual(list(obj.log_data.keys()), ['TEXT', 'AX08']) self.assertEqual(list(obj.log_data['AX08'].keys()), ['LOG']) self.assertEqual(obj.log_data['TEXT'], []) self.assertEqual(len(obj.log_data['AX08']['LOG']), 16) self.assertEqual( obj.log_data['AX08']['LOG'][0][:100], '\n\nSTATE OF HEALTH: From:1625456260.12 To:1625456260.12\n\r' '\nQuanterra Packet Baler Model 14 Restart. V' ) self.assertEqual( obj.log_data['AX08']['LOG'][1][:100], '\n\nSTATE OF HEALTH: From:1625456366.62 To:1625456366.62' '\nReducing Status Polling Interval\r\n[2021-07-0' ) def test_read_blockettes_info(self): # info in blockette 500 args = { 'data_type': 'Q330', 'is_multiplex': True, 'folder': blockettes_data, 'req_soh_chans': ['ACE'], } obj = MSeed(**args) self.assertEqual(list(obj.log_data.keys()), ['TEXT', '3203']) self.assertEqual(list(obj.log_data['3203'].keys()), ['ACE']) self.assertEqual(obj.log_data['TEXT'], []) self.assertEqual(len(obj.log_data['3203']['ACE']), 1) self.assertEqual( obj.log_data['3203']['ACE'][0][:100], '\n\nSTATE OF HEALTH: From:1671729287.00014 To:1671729287.0' '\n===========\nVCO correction: 53.7109375\nTim' ) def test_not_is_multiplex_read_channel(self): # is_multiplex = False => stop when reach to channel not match req # so the channel 'EL1' is read but not finished args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': multiplex_data, 'req_soh_chans': [], 'req_wf_chans': ['EL1'] } obj = MSeed(**args) self.assertEqual(list(obj.waveform_data.keys()), ['3203']) self.assertEqual(list(obj.waveform_data['3203'].keys()), ['EL1']) self.assertEqual(obj.waveform_data['3203']['EL1']['samplerate'], 200) self.assertEqual(obj.waveform_data['3203']['EL1']['startTmEpoch'], 1671730004.145029) self.assertEqual(obj.waveform_data['3203']['EL1']['endTmEpoch'], 1671730013.805) self.assertEqual(obj.waveform_data['3203']['EL1']['size'], 1932) self.assertEqual(obj.waveform_data['3203']['EL1']['gaps'], []) self.assertEqual(len(obj.waveform_data['3203']['EL1']['tracesInfo']), 1) def test_is_multiplex_read_channel(self): # is_multiplex = True => read every record args = { 'data_type': 'Q330', 'is_multiplex': True, 'folder': multiplex_data, 'req_soh_chans': [], 'req_wf_chans': ['EL1'] } obj = MSeed(**args) self.assertEqual(list(obj.waveform_data.keys()), ['3203']) self.assertEqual(list(obj.waveform_data['3203'].keys()), ['EL1']) self.assertEqual(obj.waveform_data['3203']['EL1']['samplerate'], 200) self.assertEqual(obj.waveform_data['3203']['EL1']['startTmEpoch'], 1671730004.145029) self.assertEqual(obj.waveform_data['3203']['EL1']['endTmEpoch'], 1671730720.4348998) self.assertEqual(obj.waveform_data['3203']['EL1']['size'], 143258) self.assertEqual(obj.waveform_data['3203']['EL1']['gaps'], []) self.assertEqual(len(obj.waveform_data['3203']['EL1']['tracesInfo']), 1) def test_not_is_multiplex_selected_channel_in_middle(self): # won't reached selected channel because previous record doesn't meet # requirement when is_multiplex = False args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': multiplex_data, 'req_soh_chans': [], 'req_wf_chans': ['EL2'] } obj = MSeed(**args) self.assertEqual(list(obj.waveform_data.keys()), []) def test_is_multiplex_selected_channel_in_middle(self): # is_multiplex = True => the selected channel will be read args = { 'data_type': 'Q330', 'is_multiplex': True, 'folder': multiplex_data, 'req_soh_chans': [], 'req_wf_chans': ['EL2'] } obj = MSeed(**args) self.assertEqual(list(obj.waveform_data.keys()), ['3203']) self.assertEqual(list(obj.waveform_data['3203'].keys()), ['EL2']) self.assertEqual(obj.waveform_data['3203']['EL2']['samplerate'], 200) self.assertEqual(obj.waveform_data['3203']['EL2']['startTmEpoch'], 1671730004.3100293) self.assertEqual(obj.waveform_data['3203']['EL2']['endTmEpoch'], 1671730720.5549) self.assertEqual(obj.waveform_data['3203']['EL2']['size'], 143249) self.assertEqual(obj.waveform_data['3203']['EL2']['gaps'], []) self.assertEqual(len(obj.waveform_data['3203']['EL2']['tracesInfo']), 1) def test_existing_time_range(self): import os print(os.getcwd()) # check if data_time is from the given range, end time may get # a little greater than read_end according to record's end time args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': q330_data, 'req_soh_chans': [], 'read_start': 1625456018.0, 'read_end': 1625505627.9998999 } obj = MSeed(**args) self.assertEqual(obj.keys, ['AX08']) self.assertEqual(list(obj.soh_data['AX08'].keys()), ['VKI']) self.assertEqual(list(obj.mass_pos_data['AX08'].keys()), []) self.assertEqual(list(obj.waveform_data['AX08'].keys()), []) self.assertEqual(obj.data_time['AX08'], [1625446018.0, 1625510338.0]) def test_non_existing_time_range(self): # if given time range out of the data time, no station will be created args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': q330_data, 'req_soh_chans': [], 'read_start': 1625356018.0, 'read_end': 1625405627.9998999 } obj = MSeed(**args) self.assertEqual(obj.keys, []) self.assertEqual(obj.soh_data, {}) self.assertEqual(obj.mass_pos_data, {}) self.assertEqual(obj.waveform_data, {}) self.assertEqual(obj.data_time, {}) def test_read_waveform(self): # data from tps similar to waveform but not separated at gaps args = { 'data_type': 'Q330', 'is_multiplex': False, 'folder': q330_data, 'req_soh_chans': [], 'req_wf_chans': ['LHE'] } obj = MSeed(**args) self.assertEqual(list(obj.waveform_data.keys()), ['AX08']) self.assertEqual(list(obj.waveform_data['AX08'].keys()), ['LHE']) self.assertEqual(obj.waveform_data['AX08']['LHE']['samplerate'], 1) self.assertEqual(obj.waveform_data['AX08']['LHE']['startTmEpoch'], 1625445156.000001) self.assertEqual(obj.waveform_data['AX08']['LHE']['endTmEpoch'], 1625532950.0) self.assertEqual(obj.waveform_data['AX08']['LHE']['size'], 87794) self.assertEqual(obj.waveform_data['AX08']['LHE']['gaps'], []) self.assertEqual(len(obj.waveform_data['AX08']['LHE']['tracesInfo']), 1) def test_read_mass_pos_channel(self): # mass position channels will be read if one or both include_mpxxxxxx # are True args = { 'data_type': 'Q330', 'is_multiplex': True, 'folder': q330_data, 'req_soh_chans': [], 'req_wf_chans': [], 'include_mp123zne': True } obj = MSeed(**args) self.assertEqual(list(obj.mass_pos_data.keys()), ['AX08']) self.assertEqual(list(obj.mass_pos_data['AX08'].keys()), ['VM1']) self.assertEqual(obj.mass_pos_data['AX08']['VM1']['samplerate'], 0.1) self.assertEqual(obj.mass_pos_data['AX08']['VM1']['startTmEpoch'], 1625444970.0) self.assertEqual(obj.mass_pos_data['AX08']['VM1']['endTmEpoch'], 1625574580.0) self.assertEqual(obj.mass_pos_data['AX08']['VM1']['size'], 12961) self.assertEqual(obj.mass_pos_data['AX08']['VM1']['gaps'], []) self.assertEqual(len(obj.mass_pos_data['AX08']['VM1']['tracesInfo']), 1) def test_gap(self): # gaps will be detected when gap_minimum is set args = { 'data_type': 'Centaur', 'is_multiplex': True, 'folder': centaur_data, 'req_soh_chans': [], 'gap_minimum': 60 } obj = MSeed(**args) self.assertEqual(list(obj.soh_data.keys()), ['3734']) self.assertEqual(sorted(list(obj.soh_data['3734'].keys())), ['EX1', 'EX2', 'EX3', 'GAN', 'GEL', 'GLA', 'GLO', 'GNS', 'GPL', 'GST', 'LCE', 'LCQ', 'VCO', 'VDT', 'VEC', 'VEI', 'VPB']) self.assertAlmostEqual(obj.soh_data['3734']['EX1']['samplerate'], 0.0166, 3) self.assertEqual(obj.soh_data['3734']['EX1']['startTmEpoch'], 1534512840.0) self.assertEqual(obj.soh_data['3734']['EX1']['endTmEpoch'], 1534550400.0) self.assertEqual(obj.soh_data['3734']['EX1']['size'], 597) self.assertEqual(obj.gaps['3734'], [[1534521420.0, 1534524000.0]]) def test_not_detect_gap(self): # if gap_minimum isn't set but gap exist, data still be separated, but # gap won't be added to gap list args = { 'data_type': 'Centaur', 'is_multiplex': True, 'folder': centaur_data, 'req_soh_chans': [], 'gap_minimum': None } obj = MSeed(**args) self.assertEqual(list(obj.soh_data.keys()), ['3734']) self.assertEqual(sorted(list(obj.soh_data['3734'].keys())), ['EX1', 'EX2', 'EX3', 'GAN', 'GEL', 'GLA', 'GLO', 'GNS', 'GPL', 'GST', 'LCE', 'LCQ', 'VCO', 'VDT', 'VEC', 'VEI', 'VPB']) self.assertAlmostEqual(obj.soh_data['3734']['EX1']['samplerate'], 0.0166, 3) self.assertEqual(obj.soh_data['3734']['EX1']['startTmEpoch'], 1534512840.0) self.assertEqual(obj.soh_data['3734']['EX1']['endTmEpoch'], 1534550400.0) self.assertEqual(obj.soh_data['3734']['EX1']['size'], 597) self.assertEqual(obj.gaps['3734'], []) # no gaps