def test_split_segments_data_3(self): '''Splits on both Engine and Heading parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_3.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf, {}) #for a, e in zip(segment_tuples, expected): #print(a,e,a==e) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3989.0, None), 0), ('START_AND_STOP', slice(3989.0, 7049.0, None), 1), ('START_AND_STOP', slice(7049.0, 9569.0, None), 1), ('START_AND_STOP', slice(9569.0, 12889.0, None), 1), ('START_AND_STOP', slice(12889.0, 15867.0, None), 1), ('START_AND_STOP', slice(15867.0, 18526.0, None), 3), ('START_AND_STOP', slice(18526.0, 21726.0, None), 2), ('START_AND_STOP', slice(21726.0, 24209.0, None), 2), ('START_AND_STOP', slice(24209.0, 26607.0, None), 1), ('START_AND_STOP', slice(26607.0, 28534.0, None), 3), ('START_AND_STOP', slice(28534.0, 30875.0, None), 2), ('START_AND_STOP', slice(30875.0, 33488.0, None), 3), ('NO_MOVEMENT', slice(33488.0, 33680.0, None), 0),])
def test_split_segments_multiple_types(self): ''' Test data has multiple segments of differing segment types. Test data has already been validated ''' hdf_path = os.path.join(test_data_path, "split_segments_multiple_types.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) self.maxDiff = None segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 16, msg="Unexpected number of segments detected") segment_types = tuple(x[0] for x in segment_tuples) self.assertEqual(segment_types, ('STOP_ONLY', 'START_ONLY', 'START_AND_STOP', 'START_AND_STOP', 'START_AND_STOP', 'START_AND_STOP', 'STOP_ONLY', 'START_AND_STOP', 'STOP_ONLY', 'START_ONLY', 'START_ONLY', 'START_AND_STOP', 'START_ONLY', 'START_AND_STOP', 'START_AND_STOP', 'START_ONLY'))
def test_split_segments_146_300(self): hdf = hdf_file(os.path.join(test_data_path, "4_3377853_146-301.hdf5")) segment_tuples = split_segments(hdf) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 24801.0, None)), ('START_AND_STOP', slice(24801.0, 30000.0, None)), ('START_AND_STOP', slice(30000.0, 49999.0, None)), ('START_AND_STOP', slice(49999.0, 69999.0, None)), ('START_AND_STOP', slice(69999.0, 73552.0, None))])
def test_split_segments_737_3C(self): '''Splits on both DFC Jump and Engine parameters.''' hdf = hdf_file(os.path.join(test_data_path, "1_7295949_737-3C.hdf5")) segment_tuples = split_segments(hdf) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3168.0, None)), ('START_AND_STOP', slice(3168.0, 6260.0, None)), ('START_AND_STOP', slice(6260.0, 9504.0, None)), ('START_AND_STOP', slice(9504.0, 12680.0, None)), ('START_AND_STOP', slice(12680.0, 15571.0, None)), ('START_AND_STOP', slice(15571.0, 18752.0, None))])
def test_split_segments_737_3C(self): '''Splits on both DFC Jump and Engine parameters.''' hdf = hdf_file(os.path.join(test_data_path, "1_7295949_737-3C.hdf5")) segment_tuples = split_segments(hdf, {}) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3168.0, None)), ('START_AND_STOP', slice(3168.0, 6260.0, None)), ('START_AND_STOP', slice(6260.0, 9504.0, None)), ('START_AND_STOP', slice(9504.0, 12680.0, None)), ('START_AND_STOP', slice(12680.0, 15571.0, None)), ('START_AND_STOP', slice(15571.0, 18752.0, None))])
def test_split_segments_data_1(self): '''Splits on both DFC Jump and Engine parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_1.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf, {}) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 9952.0, None), 0), ('START_AND_STOP', slice(9952.0, 21799.0, None), 0), ('START_AND_STOP', slice(21799.0, 24665.0, None), 3), ('START_AND_STOP', slice(24665.0, 27898.0, None), 1), ('START_AND_STOP', slice(27898.0, 31424.0, None), 2)])
def test_split_segments_data_2(self): '''Splits on both DFC Jump and Engine parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_2.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf, {}) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3407.0, None)), ('START_AND_STOP', slice(3407.0, 6362.0, None)), ('START_AND_STOP', slice(6362.0, 9912.0, None)), ('START_AND_STOP', slice(9912.0, 13064.0, None)), ('START_AND_STOP', slice(13064.0, 16467.0, None)), ('START_AND_STOP', slice(16467.0, 19200.0, None))])
def test_split_segments_data_2(self): '''Splits on both DFC Jump and Engine parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_2.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3583.0, None)), ('START_AND_STOP', slice(3583.0, 6446.0, None)), ('START_AND_STOP', slice(6446.0, 9912.0, None)), ('START_AND_STOP', slice(9912.0, 13064.0, None)), ('START_AND_STOP', slice(13064.0, 16467.0, None)), ('START_AND_STOP', slice(16467.0, 19200.0, None))])
def test_split_segments_data_2(self): '''Splits on both DFC Jump and Engine parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_2.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf, {}) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3407.0, None), 0), ('START_AND_STOP', slice(3407.0, 6362.0, None), 15), ('START_AND_STOP', slice(6362.0, 9912.0, None), 26), ('START_AND_STOP', slice(9912.0, 13064.0, None), 56), ('START_AND_STOP', slice(13064.0, 16467.0, None), 8), ('START_AND_STOP', slice(16467.0, 19065.0, None), 19), ('GROUND_ONLY', slice(19065.0, 19200.0, None), 57)])
def test_rto_correct_side_of_split(self): ''' Test to ensure that RTO's are on the correct side of splitting, i.e. at the beginning of a flight. This example HDF5 file appears to have two stationary engine activities and an RTO between the two flights. This creates 6 sizeable slices (potential splitting points) where the engine parameters normalised to 0. We're interested in making the segment split within the first of these eng_min_slices slices (Between indices 11959.5 to 12336.5). Ideally the segment split should be halfway between this, at 12148.0. ''' hdf = hdf_file(os.path.join(test_data_path, "rto_split_segment.hdf5")) segment_tuples = split_segments(hdf, {}) split_idx = 12148.0 self.assertEqual(segment_tuples, [ ('START_AND_STOP', slice(0, split_idx, None), 0), ('START_AND_STOP', slice(split_idx, 21997.0, None), 52), ('GROUND_ONLY', slice(21997.0, 22784.0, None), 45), ])
def test_split_segments_data_3(self): '''Splits on both Engine and Heading parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_3.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf, {}) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3989.0, None)), ('START_AND_STOP', slice(3989.0, 7049.0, None)), ('START_AND_STOP', slice(7049.0, 9569.0, None)), ('START_AND_STOP', slice(9569.0, 12889.0, None)), ('START_AND_STOP', slice(12889.0, 15867.0, None)), ('START_AND_STOP', slice(15867.0, 18526.0, None)), ('START_AND_STOP', slice(18526.0, 21726.0, None)), ('START_AND_STOP', slice(21726.0, 24209.0, None)), ('START_AND_STOP', slice(24209.0, 26607.0, None)), ('START_AND_STOP', slice(26607.0, 28534.0, None)), ('START_AND_STOP', slice(28534.0, 30875.0, None)), ('START_AND_STOP', slice(30875.0, 33680.0, None))])
def test_rto_correct_side_of_split(self): ''' Test to ensure that RTO's are on the correct side of splitting, i.e. at the beginning of a flight. This example HDF5 file appears to have two stationary engine activities and an RTO between the two flights. This creates 6 sizeable slices (potential splitting points) where the engine parameters normalised to 0. We're interested in making the segment split within the first of these eng_min_slices slices (Between indices 11959.5 to 12336.5). Ideally the segment split should be halfway between this, at 12148.0. ''' hdf = hdf_file(os.path.join(test_data_path, "rto_split_segment.hdf5")) segment_tuples = split_segments(hdf, {}) split_idx = 12148.0 self.assertEqual( segment_tuples, [('START_AND_STOP', slice(0, split_idx, None), 0), ('START_AND_STOP', slice(split_idx, 21997.0, None), 52), ('GROUND_ONLY', slice(21997.0, 22784.0, None), 45),] )
def test_split_segments_data_3(self): '''Splits on both Engine and Heading parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_3.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf) self.assertEqual(segment_tuples, [('START_AND_STOP', slice(0, 3987.0, None)), ('START_AND_STOP', slice(3987.0, 7049.0, None)), ('START_AND_STOP', slice(7049.0, 9563.0, None)), ('START_AND_STOP', slice(9563.0, 12921.0, None)), ('START_AND_STOP', slice(12921.0, 15858.0, None)), ('START_AND_STOP', slice(15858.0, 18526.0, None)), ('START_AND_STOP', slice(18526.0, 21728.0, None)), ('START_AND_STOP', slice(21728.0, 24208.0, None)), ('START_AND_STOP', slice(24208.0, 26607.0, None)), ('START_AND_STOP', slice(26607.0, 28534.0, None)), ('START_AND_STOP', slice(28534.0, 30875.0, None)), ('START_AND_STOP', slice(30875.0, 33680.0, None))])
def test_split_segments_multiple_types(self, settings): ''' Test data has multiple segments of differing segment types. Test data has already been validated ''' # Overriding MINIMUM_FAST_DURATION. settings.AIRSPEED_THRESHOLD = 80 settings.AIRSPEED_THRESHOLD_TIME = 3 * 60 settings.HEADING_CHANGE_TAXI_THRESHOLD = 60 settings.MINIMUM_SPLIT_DURATION = 100 settings.MINIMUM_FAST_DURATION = 0 settings.MINIMUM_SPLIT_PARAM_VALUE = 0.175 settings.HEADING_RATE_SPLITTING_THRESHOLD = 0.1 settings.MAX_TIMEBASE_AGE = 365 * 10 settings.MIN_FAN_RUNNING = 10 hdf_path = os.path.join(test_data_path, "split_segments_multiple_types.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) self.maxDiff = None segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 16, msg="Unexpected number of segments detected") segment_types = tuple(x[0] for x in segment_tuples) self.assertEqual(segment_types, ('STOP_ONLY', 'START_ONLY', 'START_AND_STOP', 'START_AND_STOP', 'START_AND_STOP', 'START_AND_STOP', 'STOP_ONLY', 'START_AND_STOP', 'STOP_ONLY', 'START_ONLY', 'START_ONLY', 'START_AND_STOP', 'START_ONLY', 'START_AND_STOP', 'START_AND_STOP', 'START_ONLY'))
def test_split_segments_data_3(self): '''Splits on both Engine and Heading parameters.''' hdf_path = os.path.join(test_data_path, "split_segments_3.hdf5") temp_path = copy_file(hdf_path) hdf = hdf_file(temp_path) segment_tuples = split_segments(hdf, {}) expected = [('START_AND_STOP', slice(0, 3989.0, None), 0), ('START_AND_STOP', slice(3989.0, 7049.0, None), 1), ('START_AND_STOP', slice(7049.0, 9569.0, None), 1), ('START_AND_STOP', slice(9569.0, 12889.0, None), 1), ('START_AND_STOP', slice(12889.0, 15867.0, None), 1), ('START_AND_STOP', slice(15867.0, 18526.0, None), 3), ('START_AND_STOP', slice(18526.0, 21726.0, None), 2), ('START_AND_STOP', slice(21726.0, 24209.0, None), 2), ('START_AND_STOP', slice(24209.0, 26607.0, None), 1), ('START_AND_STOP', slice(26607.0, 28534.0, None), 3), ('START_AND_STOP', slice(28534.0, 30875.0, None), 2), ('START_AND_STOP', slice(30875.0, 33680.0, None), 3)] #for a, e in zip(segment_tuples, expected): #print(a,e,a==e) self.assertEqual(segment_tuples, [ ('START_AND_STOP', slice(0, 3989.0, None), 0), ('START_AND_STOP', slice(3989.0, 7049.0, None), 1), ('START_AND_STOP', slice(7049.0, 9569.0, None), 1), ('START_AND_STOP', slice(9569.0, 12889.0, None), 1), ('START_AND_STOP', slice(12889.0, 15867.0, None), 1), ('START_AND_STOP', slice(15867.0, 18526.0, None), 3), ('START_AND_STOP', slice(18526.0, 21726.0, None), 2), ('START_AND_STOP', slice(21726.0, 24209.0, None), 2), ('START_AND_STOP', slice(24209.0, 26607.0, None), 1), ('START_AND_STOP', slice(26607.0, 28534.0, None), 3), ('START_AND_STOP', slice(28534.0, 30875.0, None), 2), ('START_AND_STOP', slice(30875.0, 33488.0, None), 3), ('NO_MOVEMENT', slice(33488.0, 33680.0, None), 0), ])
def test_split_segments(self): # TODO: Test engine param splitting. # Mock hdf airspeed_array = np.ma.concatenate([np.ma.arange(300, dtype=float), np.ma.arange(300, 0, -1, dtype=float)]) airspeed_frequency = 2 airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.arange(len(airspeed_array) / 2, dtype=float) % 360 heading_frequency = 1 heading_array.mask = False eng_array = None eng_frequency = 1 dfc_array = np.ma.arange(0, 300, 2) hdf = mock.Mock() hdf.get = mock.Mock() hdf.get.return_value = None hdf.reliable_frame_counter = False hdf.duration = 50 def hdf_getitem(self, key, **kwargs): if key == 'Airspeed': return Parameter('Airspeed', array=airspeed_array, frequency=airspeed_frequency) elif key == 'Frame Counter': return Parameter('Frame Counter', array=dfc_array, frequency=0.25) elif key == 'Heading': # TODO: Give heading specific data. return Parameter('Heading', array=heading_array, frequency=heading_frequency) elif key == 'Eng (1) N1' and eng_array is not None: return Parameter('Eng (1) N1', array=eng_array, frequency=eng_frequency) else: raise KeyError hdf.__getitem__ = hdf_getitem def hdf_get_param(key, valid_only=False): # Pretend that we recorded Heading True only on this aircraft if key == 'Heading': raise KeyError elif key == 'Heading True': return Parameter('Heading True', array=heading_array, frequency=heading_frequency) hdf.get_param = hdf_get_param # Unmasked single flight. segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # DFC should not affect result. hdf.reliable_frame_counter = True # Mask within slow data should not affect result. airspeed_array[:50] = np.ma.masked airspeed_array[-50:] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked beginning of speedy data will affect result. airspeed_array[:100] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'STOP_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked end of speedy data will affect result. airspeed_array = np.ma.concatenate([np.ma.arange(300), np.ma.arange(300, 0, -1)]) airspeed_array[-100:] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked beginning and end of speedy data will affect result. airspeed_array[:100] = np.ma.masked airspeed_array[-100:] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'MID_FLIGHT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Two flights, split will be made using DFC. airspeed_array = np.ma.concatenate([np.ma.arange(0, 200, 0.5), np.ma.arange(200, 0, -0.5), np.ma.arange(0, 200, 0.5), np.ma.arange(200, 0, -0.5)]) airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.concatenate([np.ma.arange(len(airspeed_array) / 4, dtype=float) % 360, [0] * (len(airspeed_array) / 4)]) # DFC jumps exactly half way. dfc_array = np.ma.concatenate([np.ma.arange(0, 100), np.ma.arange(200, 300)]) segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 2) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 398) # Heading diff not exceed HEADING_CHANGE_TAXI_THRESHOLD segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 398) self.assertEqual(segment_slice.stop, airspeed_secs) # Split using engine params where DFC does not jump. eng_array = np.ma.concatenate([np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5), np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5)]) segment_tuples = split_segments(hdf, {}) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 398.0) # Heading diff not exceed HEADING_CHANGE_TAXI_THRESHOLD segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 398.0) self.assertEqual(segment_slice.stop, airspeed_secs) # Split using Turning where DFC does not jump. dfc_array = np.ma.concatenate([np.ma.arange(4000, 4096), np.ma.arange(0, 105)]) heading_array = np.ma.concatenate([np.ma.arange(390, 0, -1), np.ma.zeros(10), np.ma.arange(400, 800)]) eng_array = None segment_tuples = split_segments(hdf, {}) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 395) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 395) self.assertEqual(segment_slice.stop, airspeed_secs) # Same split conditions, but does not split on jumping DFC because # reliable_frame_counter is False. hdf.reliable_frame_counter = False dfc_array = np.ma.masked_array(np.random.randint(1000, size=((len(dfc_array),)))) segment_tuples = split_segments(hdf, {}) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 395) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 395) self.assertEqual(segment_slice.stop, airspeed_secs) # Test that no heading change returns "NO_MOVEMENT" heading_array = np.ones_like(airspeed_array) * 20 # add a bit of erroneous movement heading_array[5] += 2 heading_array[5] += 12 heading_array[5] += 9 heading_array[5] += 4 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 2) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 400) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 400) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed always slow. eng_array = np.ma.concatenate([np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5)]) eng_frequency = 2 airspeed_array = np.ma.concatenate([np.ma.arange(50), np.ma.arange(50, 0, -1)]) airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.arange(0, 100, 2) % 360 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'GROUND_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed Fully Masked slow. airspeed_array = np.ma.masked_all(100) heading_array = np.ma.arange(len(airspeed_array) / 2) % 360 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Unmasked single flight less than 3 minutes. airspeed_array = np.ma.concatenate([np.ma.arange(200), np.ma.arange(200, 0, -1)]) heading_array = np.ma.arange(len(airspeed_array) / 2) % 360 airspeed_secs = len(airspeed_array) / airspeed_frequency segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'GROUND_ONLY', msg="Fast should not be long enough to be a START_AND_STOP") self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Unmasked single flight less than 3 minutes. airspeed_array = np.ma.concatenate([np.ma.arange(200), np.ma.arange(200, 0, -1)]) airspeed_frequency = 0.5 heading_array = np.ma.arange(len(airspeed_array) / 2) % 360 airspeed_secs = len(airspeed_array) / airspeed_frequency segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP', msg="Fast should be long enough to be a START_AND_STOP") self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed always slow. No Eng so heading changes should be ignored. (eg Herc) eng_array = None eng_frequency = None airspeed_array = np.ma.concatenate([np.ma.arange(50), np.ma.arange(50, 0, -1)]) airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.arange(0, 100, 2) % 360 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs)
def test_split_segments(self): # TODO: Test engine param splitting. # Mock hdf airspeed_array = np.ma.concatenate([ np.ma.arange(300, dtype=float), np.ma.arange(300, 0, -1, dtype=float) ]) airspeed_frequency = 2 airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.arange(len(airspeed_array) / 2, dtype=float) % 360 heading_frequency = 1 heading_array.mask = False eng_array = None eng_frequency = 1 dfc_array = np.ma.arange(0, 300, 2) hdf = mock.Mock() hdf.get = mock.Mock() hdf.get.return_value = None hdf.__contains__ = mock.Mock() hdf.__contains__.return_value = False hdf.reliable_frame_counter = False hdf.duration = 50 def hdf_getitem(self, key, **kwargs): if key == 'Airspeed': return Parameter('Airspeed', array=airspeed_array, frequency=airspeed_frequency) elif key == 'Frame Counter': return Parameter('Frame Counter', array=dfc_array, frequency=0.25) elif key == 'Heading': # TODO: Give heading specific data. return Parameter('Heading', array=heading_array, frequency=heading_frequency) elif key == 'Eng (1) N1' and eng_array is not None: return Parameter('Eng (1) N1', array=eng_array, frequency=eng_frequency) elif key == 'Segment Split': seg_split = M('Segment Split', array=np.ma.zeros(len(heading_array), dtype=int), frequency=heading_frequency, values_mapping={ 0: "-", 1: "Split" }) seg_split.array[390 / heading_frequency] = "Split" return seg_split else: raise KeyError hdf.__getitem__ = hdf_getitem def hdf_get_param(key, valid_only=False): # Pretend that we recorded Heading True only on this aircraft if key == 'Heading': raise KeyError elif key == 'Heading True': return Parameter('Heading True', array=heading_array, frequency=heading_frequency) hdf.get_param = hdf_get_param # Unmasked single flight. segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # DFC should not affect result. hdf.reliable_frame_counter = True # Mask within slow data should not affect result. airspeed_array[:50] = np.ma.masked airspeed_array[-50:] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked beginning of speedy data will affect result. airspeed_array[:100] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'STOP_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked end of speedy data will affect result. airspeed_array = np.ma.concatenate( [np.ma.arange(300), np.ma.arange(300, 0, -1)]) airspeed_array[-100:] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked beginning and end of speedy data will affect result. airspeed_array[:100] = np.ma.masked airspeed_array[-100:] = np.ma.masked segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'MID_FLIGHT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Two flights, split will be made using DFC. airspeed_array = np.ma.concatenate([ np.ma.arange(0, 200, 0.5), np.ma.arange(200, 0, -0.5), np.ma.arange(0, 200, 0.5), np.ma.arange(200, 0, -0.5) ]) airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.concatenate([ np.ma.arange(len(airspeed_array) / 4, dtype=float) % 360, [0] * (len(airspeed_array) / 4) ]) # DFC jumps exactly half way. dfc_array = np.ma.concatenate( [np.ma.arange(0, 100), np.ma.arange(200, 300)]) segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 2) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 398) # Heading diff not exceed HEADING_CHANGE_TAXI_THRESHOLD segment_type, segment_slice, start_padding = segment_tuples[1] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 398) self.assertEqual(segment_slice.stop, airspeed_secs) # Split using engine params where DFC does not jump. eng_array = np.ma.concatenate([ np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5), np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5) ]) segment_tuples = split_segments(hdf, {}) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 398.0) # Heading diff not exceed HEADING_CHANGE_TAXI_THRESHOLD segment_type, segment_slice, start_padding = segment_tuples[1] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 398.0) self.assertEqual(segment_slice.stop, airspeed_secs) # Split using Turning where DFC does not jump. dfc_array = np.ma.concatenate( [np.ma.arange(4000, 4096), np.ma.arange(0, 105)]) heading_array = np.ma.concatenate([ np.ma.arange(390, 0, -1), np.ma.zeros(10), np.ma.arange(400, 800) ]) eng_array = None segment_tuples = split_segments(hdf, {}) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 395) segment_type, segment_slice, start_padding = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 395) self.assertEqual(segment_slice.stop, airspeed_secs) # Split Segment Split hdf.__contains__.return_value = True segment_tuples = split_segments(hdf, {}) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 390) segment_type, segment_slice, start_padding = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 390) self.assertEqual(segment_slice.stop, airspeed_secs) hdf.__contains__.return_value = False # Same split conditions, but does not split on jumping DFC because # reliable_frame_counter is False. hdf.reliable_frame_counter = False dfc_array = np.ma.masked_array( np.random.randint(1000, size=((len(dfc_array), )))) segment_tuples = split_segments(hdf, {}) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 395) segment_type, segment_slice, start_padding = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 395) self.assertEqual(segment_slice.stop, airspeed_secs) # Test that no heading change returns "NO_MOVEMENT" heading_array = np.ones_like(airspeed_array) * 20 # add a bit of erroneous movement heading_array[5] += 2 heading_array[5] += 12 heading_array[5] += 9 heading_array[5] += 4 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 2) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 400) segment_type, segment_slice, start_padding = segment_tuples[1] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 400) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed always slow. eng_array = np.ma.concatenate( [np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5)]) eng_frequency = 2 airspeed_array = np.ma.concatenate( [np.ma.arange(50), np.ma.arange(50, 0, -1)]) airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.arange(0, 100, 2) % 360 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'GROUND_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed Fully Masked slow. airspeed_array = np.ma.masked_all(100) heading_array = np.ma.arange(len(airspeed_array) / 2) % 360 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Unmasked single flight less than 3 minutes. airspeed_array = np.ma.concatenate( [np.ma.arange(200), np.ma.arange(200, 0, -1)]) heading_array = np.ma.arange(len(airspeed_array) / 2) % 360 airspeed_secs = len(airspeed_array) / airspeed_frequency segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual( segment_type, 'START_ONLY', msg="Fast should not be long enough to be a START_AND_STOP") self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Unmasked single flight less than 3 minutes. airspeed_array = np.ma.concatenate( [np.ma.arange(200), np.ma.arange(200, 0, -1)]) airspeed_frequency = 0.5 heading_array = np.ma.arange(len(airspeed_array) / 2) % 360 airspeed_secs = len(airspeed_array) / airspeed_frequency segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual( segment_type, 'START_AND_STOP', msg="Fast should be long enough to be a START_AND_STOP") self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed always slow. No Eng so heading changes should be ignored. (eg Herc) eng_array = None eng_frequency = None airspeed_array = np.ma.concatenate( [np.ma.arange(50), np.ma.arange(50, 0, -1)]) airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.arange(0, 100, 2) % 360 segment_tuples = split_segments(hdf, {}) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice, start_padding = segment_tuples[0] self.assertEqual(segment_type, 'NO_MOVEMENT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs)
def test_split_segments(self): # TODO: Test engine param splitting. # Mock hdf airspeed_array = np.ma.concatenate([np.ma.arange(200), np.ma.arange(200, 0, -1)]) airspeed_frequency = 2 airspeed_secs = len(airspeed_array) / airspeed_frequency heading_array = np.ma.zeros(len(airspeed_array) / 2) heading_frequency = 1 heading_array.mask = False eng_array = None eng_frequency = 1 dfc_array = np.ma.arange(0, 200, 2) hdf = mock.Mock() hdf.get = mock.Mock() hdf.get.return_value = None hdf.reliable_frame_counter = False def hdf_getitem(self, key, **kwargs): if key == 'Airspeed': return Parameter('Airspeed', array=airspeed_array, frequency=airspeed_frequency) elif key == 'Frame Counter': return Parameter('Frame Counter', array=dfc_array, frequency=0.25) elif key == 'Heading': # TODO: Give heading specific data. return Parameter('Heading', array=heading_array, frequency=heading_frequency) elif key == 'Eng (1) N1' and eng_array is not None: return Parameter('Eng (1) N1', array=eng_array, frequency=eng_frequency) else: raise KeyError hdf.__getitem__ = hdf_getitem def hdf_get_param(key, valid_only=False): # Pretend that we recorded Heading True only on this aircraft if key == 'Heading': raise KeyError elif key == 'Heading True': return Parameter('Heading True', array=heading_array, frequency=heading_frequency) hdf.get_param = hdf_get_param # Unmasked single flight. segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # DFC should not affect result. hdf.reliable_frame_counter = True # Mask within slow data should not affect result. airspeed_array[:50] = np.ma.masked airspeed_array[-50:] = np.ma.masked segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked beginning of speedy data will affect result. airspeed_array[:100] = np.ma.masked segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'STOP_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked end of speedy data will affect result. airspeed_array = np.ma.concatenate([np.ma.arange(200), np.ma.arange(200, 0, -1)]) airspeed_array[-100:] = np.ma.masked segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Masked beginning and end of speedy data will affect result. airspeed_array[:100] = np.ma.masked airspeed_array[-100:] = np.ma.masked segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'MID_FLIGHT') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Airspeed always slow. airspeed_array = np.ma.concatenate([np.ma.arange(50), np.ma.arange(50, 0, -1)]) airspeed_secs = len(airspeed_array) / airspeed_frequency segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 1) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'GROUND_ONLY') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, airspeed_secs) # Two flights, split will be made using DFC. airspeed_array = np.ma.concatenate([np.ma.arange(0, 200, 0.5), np.ma.arange(200, 0, -0.5), np.ma.arange(0, 200, 0.5), np.ma.arange(200, 0, -0.5),]) airspeed_secs = len(airspeed_array) / airspeed_frequency # DFC jumps exactly half way. dfc_array = np.ma.concatenate([np.ma.arange(0, 100), np.ma.arange(200, 300)]) segment_tuples = split_segments(hdf) self.assertEqual(len(segment_tuples), 2) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 398) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 398) self.assertEqual(segment_slice.stop, airspeed_secs) # Split using engine params where DFC does not jump. eng_array = np.ma.concatenate([np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5), np.ma.arange(0, 100, 0.5), np.ma.arange(100, 0, -0.5),]) segment_tuples = split_segments(hdf) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 398.0) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 398.0) self.assertEqual(segment_slice.stop, airspeed_secs) # Split using Turning where DFC does not jump. dfc_array = np.ma.concatenate([np.ma.arange(4000, 4096), np.ma.arange(0, 105)]) heading_array = np.ma.concatenate([np.ma.arange(390, 0, -1), np.ma.zeros(10), np.ma.arange(400, 800)]) eng_array = None segment_tuples = split_segments(hdf) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 395) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 395) self.assertEqual(segment_slice.stop, airspeed_secs) # Same split conditions, but does not split on jumping DFC because # reliable_frame_counter is False. hdf.reliable_frame_counter = False dfc_array = np.ma.masked_array(np.random.randint(1000, size=((len(dfc_array),)))) segment_tuples = split_segments(hdf) segment_type, segment_slice = segment_tuples[0] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 0) self.assertEqual(segment_slice.stop, 395) segment_type, segment_slice = segment_tuples[1] self.assertEqual(segment_type, 'START_AND_STOP') self.assertEqual(segment_slice.start, 395) self.assertEqual(segment_slice.stop, airspeed_secs)