@@ -29,15 +29,23 @@ def test_get_points_from_fraction(n_samples, fraction, maximum, expected):
2929 ([1 , 1 , 2 , 2 ], 0.5 , 'backward' , 2 ),
3030 # fractional basis
3131 ([1 , 3 , 4 , 6 ], 0.25 , 'forward' , 1 ),
32- ([1 , 3 , 5 , 6 ], 0.75 , 'forward' , 3 )
32+ ([1 , 3 , 5 , 6 ], 0.75 , 'forward' , 3 ),
33+
34+ # Test for nans
35+ ([1 ]* 10 + [2 ] * 5 + [np .nan ]* 5 , 0.5 , 'backward' , 2 ),
36+ ([np .nan ] * 10 , 0.5 , 'backward' , np .nan )
37+
3338])
3439def test_directional_mean (data , fractional_basis , direction , expected ):
3540 """
3641 Test the directional mean function
3742 """
3843 df = pd .DataFrame ({'data' : np .array (data )})
3944 value = get_directional_mean (df ['data' ], fractional_basis = fractional_basis , direction = direction )
40- assert value == expected
45+ if np .isnan (expected ): # Handle the NaN case
46+ assert np .isnan (value )
47+ else :
48+ assert value == expected
4149
4250
4351@pytest .mark .parametrize ('data, fractional_basis, direction, zero_bias_idx' , [
@@ -70,20 +78,41 @@ def test_get_normalized_at_border(data, fractional_basis, direction, ideal_norm_
7078 result = get_normalized_at_border (df ['data' ], fractional_basis = fractional_basis , direction = direction )
7179 assert result .iloc [ideal_norm_index ] == 1
7280
81+ def poly_function (elapsed , amplitude = 4096 , frequency = 1 ):
82+ return amplitude * np .sin (2 * np .pi * frequency * elapsed )
83+
84+
7385@pytest .mark .parametrize ('data1_hz, data2_hz, desired_hz' , [
74- (10 , 5 , 20 )
86+ (75 , 100 , 16000 ),
87+ (100 , 75 , 100 ),
88+
7589])
7690def test_merge_on_to_time (data1_hz , data2_hz , desired_hz ):
77- df1 = pd .DataFrame ({'data1' :np .arange (1 ,stop = data1_hz + 1 ), 'time' : np .arange (0 , 1 , 1 / data1_hz )})
78- df2 = pd .DataFrame ({'data2' :np .arange (100 ,stop = data2_hz + 100 ), 'time' : np .arange (0 , 1 , 1 / data2_hz )})
79- desired = np .arange (0 , 1 , 1 / desired_hz )
91+ """
92+ Test merging multi sample rate timeseries into a single dataframe
93+ specifically focused on timing of the final product
94+ """
95+ t1 = np .arange (0 , 1 , 1 / data1_hz )
96+ d1 = poly_function (t1 )
97+ df1 = pd .DataFrame ({'data1' :d1 , 'time' : t1 })
98+ df1 = df1 .set_index ('time' )
8099
100+ t2 = np .arange (0 , 1 , 1 / data2_hz )
101+ d2 = poly_function (t2 )
102+ df2 = pd .DataFrame ({'data2' :d2 , 'time' : t2 })
103+ df2 = df2 .set_index ('time' )
104+
105+ desired = np .arange (0 , 1 , 1 / desired_hz )
81106 final = merge_on_to_time ([df1 , df2 ], desired )
82- # Ensure we have essentially the same timestep
83- tsteps = np .unique (np .round (final ['time' ].diff (), 6 ))
84- tsteps = tsteps [~ np .isnan (tsteps )]
85- # Assert only a nan and a real number exist for timesteps
86- assert tsteps == np .round (1 / desired_hz , 6 )
107+
108+ # Check timing on both dataframes
109+ assert df1 ['data1' ].idxmax () == pytest .approx (final ['data1' ].idxmax (), abs = 3e-2 )
110+ assert df1 ['data1' ].idxmin () == pytest .approx (final ['data1' ].idxmin (), abs = 3e-2 )
111+ # Confirm the handling of multiple datasets
112+ assert len (final .columns ) == 2
113+ # Confirm an exact match of length of data
114+ assert len (final ['data1' ][~ np .isnan (final ['data1' ])]) == len (desired )
115+
87116
88117@pytest .mark .parametrize ('data_list, expected' , [
89118 # Typical use, low sample to high res
@@ -125,7 +154,7 @@ def test_merge_time_series(data_list, expected):
125154 # Test normal situation with ambient present
126155 ([200 , 200 , 400 , 1000 ], [200 , 200 , 50 , 50 ], 100 , [1.0 , 1.0 , 275 , 1000 ]),
127156 # Test no cleaning required
128- # ([200, 200, 400, 400], [210, 210, 200, 200], 90, [200, 200, 400, 400])
157+ ([200 , 200 , 400 , 400 ], [210 , 210 , 200 , 200 ], 90 , [200 , 200 , 400 , 400 ])
129158])
130159def test_remove_ambient (active , ambient , min_ambient_range , expected ):
131160 """
@@ -137,10 +166,6 @@ def test_remove_ambient(active, ambient, min_ambient_range, expected):
137166 result = remove_ambient (active , ambient , min_ambient_range = 100 )
138167 np .testing .assert_equal (result .values , expected )
139168
140- # @pytest.mark.parametrize('fname', ['2024-01-31--104419.csv'])
141- # def test_remove_ambient_real(raw_df, fname):
142- # remove_ambient(raw_df['Sensor3'], raw_df['Sensor2'])
143-
144169@pytest .mark .parametrize ('data, coefficients, expected' , [
145170 ([1 , 2 , 3 , 4 ], [2 , 0 ], [2 , 4 , 6 , 8 ])
146171])
@@ -153,15 +178,13 @@ def test_apply_calibration(data, coefficients, expected):
153178
154179@pytest .mark .parametrize ("data, depth, new_depth, resolution, agg_method, expected_data" , [
155180 # Test with negative depths
156- # ([[2, 4, 6, 8]], [-10, -20, -30, -40], [-20, -40], None, 'mean', [[3, 7]]),
181+ ([[2 , 4 , 6 , 8 ]], [- 10 , - 20 , - 30 , - 40 ], [- 20 , - 40 ], None , 'mean' , [[3 , 7 ]]),
157182 # Test with column specific agg methods
158- # ([[2, 4, 6, 8], [1, 1, 1, 1]], [-10, -20, -30, -40], [-20, -40], None, {'data0': 'mean','data1':'sum'}, [[3, 7], [2, 2]]),
183+ ([[2 , 4 , 6 , 8 ], [1 , 1 , 1 , 1 ]], [- 10 , - 20 , - 30 , - 40 ], [- 20 , - 40 ], None , {'data0' : 'mean' ,'data1' :'sum' }, [[3 , 7 ], [2 , 2 ]]),
159184 # Test with resolution
160185 ([[2 , 4 , 6 , 8 ]], [- 10 , - 20 , - 30 , - 40 ], None , 20 , 'mean' , [[3 , 7 ]]),
161186])
162187def test_aggregate_by_depth (data , depth , new_depth , resolution , agg_method , expected_data ):
163- """
164- """
165188 data_dict = {f'data{ i } ' :d for i ,d in enumerate (data )}
166189 data_dict ['depth' ] = depth
167190 df = pd .DataFrame .from_dict (data_dict )
0 commit comments