25
25
from openhtf .core import measurements
26
26
from examples import all_the_things
27
27
from openhtf .util import test as htf_test
28
+ import pandas
28
29
29
30
# Fields that are considered 'volatile' for record comparison.
30
31
_VOLATILE_FIELDS = {
@@ -231,14 +232,19 @@ def test_to_dataframe__no_pandas(self):
231
232
with self .assertRaises (RuntimeError ):
232
233
self .test_to_dataframe (units = True )
233
234
234
- def test_to_dataframe (self , units = True ):
235
+ def _make_multidim_measurement (self , units = '' ):
235
236
measurement = htf .Measurement ('test_multidim' )
236
237
measurement .with_dimensions ('ms' , 'assembly' , htf .Dimension ('my_zone' ))
238
+ if units :
239
+ measurement .with_units (units )
240
+ return measurement
237
241
242
+ def test_to_dataframe (self , units = True ):
238
243
if units :
239
- measurement . with_units ('°C' )
244
+ measurement = self . _make_multidim_measurement ('°C' )
240
245
measure_column_name = 'degree Celsius'
241
246
else :
247
+ measurement = self ._make_multidim_measurement ()
242
248
measure_column_name = 'value'
243
249
244
250
for t in range (5 ):
@@ -260,6 +266,100 @@ def test_to_dataframe(self, units=True):
260
266
def test_to_dataframe__no_units (self ):
261
267
self .test_to_dataframe (units = False )
262
268
269
+ def _multidim_testdata (self ):
270
+ return {
271
+ 'ms' : [1 , 2 , 3 ],
272
+ 'assembly' : ['A' , 'B' , 'C' ],
273
+ 'my_zone' : ['X' , 'Y' , 'Z' ],
274
+ 'degree_celsius' : [10 , 20 , 30 ],
275
+ }
276
+
277
+ def test_from_dataframe_raises_if_dimensions_missing_in_dataframe (self ):
278
+ measurement = self ._make_multidim_measurement ('°C' )
279
+ source_data = self ._multidim_testdata ()
280
+ del source_data ['assembly' ]
281
+ with self .assertRaisesRegex (
282
+ ValueError , 'DataFrame is missing dimensions'
283
+ ) as cm :
284
+ measurement .from_dataframe (
285
+ pandas .DataFrame (source_data ),
286
+ metric_column = 'degree_celsius' ,
287
+ )
288
+ with self .assertRaisesRegex (
289
+ KeyError , r"None of \['assembly'\] are in the columns"
290
+ ):
291
+ raise cm .exception .__cause__
292
+
293
+ def test_from_dataframe_raises_if_metric_missing_in_dataframe (self ):
294
+ measurement = self ._make_multidim_measurement ('°C' )
295
+ source_data = self ._multidim_testdata ()
296
+ del source_data ['degree_celsius' ]
297
+ with self .assertRaisesRegex (
298
+ ValueError , 'DataFrame does not have a column named degree_celsius'
299
+ ):
300
+ measurement .from_dataframe (
301
+ pandas .DataFrame (source_data ),
302
+ metric_column = 'degree_celsius' ,
303
+ )
304
+
305
+ def _assert_multidim_measurement_matches_testdata (self , measurement ):
306
+ self .assertEqual (measurement .measured_value [(1 , 'A' , 'X' )], 10 )
307
+ self .assertEqual (measurement .measured_value [(2 , 'B' , 'Y' )], 20 )
308
+ self .assertEqual (measurement .measured_value [(3 , 'C' , 'Z' )], 30 )
309
+ pandas .testing .assert_frame_equal (
310
+ measurement .to_dataframe ().rename (
311
+ columns = {
312
+ 'ms' : 'ms' ,
313
+ 'assembly' : 'assembly' ,
314
+ 'my_zone' : 'my_zone' ,
315
+ # The metric column name comes from the unit.
316
+ 'degree Celsius' : 'degree_celsius' ,
317
+ }
318
+ ),
319
+ pandas .DataFrame (self ._multidim_testdata ()),
320
+ )
321
+
322
+ def test_from_flat_dataframe (self ):
323
+ measurement = self ._make_multidim_measurement ('°C' )
324
+ source_dataframe = pandas .DataFrame (self ._multidim_testdata ())
325
+ measurement .from_dataframe (source_dataframe , metric_column = 'degree_celsius' )
326
+ measurement .outcome = measurements .Outcome .PASS
327
+ self ._assert_multidim_measurement_matches_testdata (measurement )
328
+
329
+ def test_from_dataframe_with_multiindex_dataframe (self ):
330
+ measurement = self ._make_multidim_measurement ('°C' )
331
+ source_dataframe = pandas .DataFrame (self ._multidim_testdata ()).set_index (
332
+ ['ms' , 'assembly' , 'my_zone' ]
333
+ )
334
+ measurement .from_dataframe (source_dataframe , metric_column = 'degree_celsius' )
335
+ measurement .outcome = measurements .Outcome .PASS
336
+ self ._assert_multidim_measurement_matches_testdata (measurement )
337
+
338
+ def test_from_dataframe_ignores_extra_columns (self ):
339
+ measurement = self ._make_multidim_measurement ('°C' )
340
+ source_data = self ._multidim_testdata ()
341
+ source_data ['degrees_fahrenheit' ] = [11 , 21 , 31 ]
342
+ source_dataframe = pandas .DataFrame (source_data )
343
+ measurement .from_dataframe (source_dataframe , metric_column = 'degree_celsius' )
344
+ measurement .outcome = measurements .Outcome .PASS
345
+ self ._assert_multidim_measurement_matches_testdata (measurement )
346
+
347
+ def test_from_dataframe_with_duplicate_dimensions_overwrites (self ):
348
+ """Verifies multi-dim measurement overwrite with duplicate dimensions."""
349
+ measurement = self ._make_multidim_measurement ('°C' )
350
+ source_dataframe = pandas .DataFrame ({
351
+ 'ms' : [1 , 2 , 3 , 1 ],
352
+ 'assembly' : ['A' , 'B' , 'C' , 'A' ],
353
+ 'my_zone' : ['X' , 'Y' , 'Z' , 'X' ],
354
+ 'degree_celsius' : [10 , 20 , 30 , 11 ],
355
+ })
356
+ measurement .from_dataframe (source_dataframe , metric_column = 'degree_celsius' )
357
+ measurement .outcome = measurements .Outcome .PASS
358
+ # Overwritten value.
359
+ self .assertEqual (measurement .measured_value [(1 , 'A' , 'X' )], 11 )
360
+ self .assertEqual (measurement .measured_value [(2 , 'B' , 'Y' )], 20 )
361
+ self .assertEqual (measurement .measured_value [(3 , 'C' , 'Z' )], 30 )
362
+
263
363
def test_bad_validator (self ):
264
364
measurement = htf .Measurement ('bad_measure' )
265
365
measurement .with_dimensions ('a' )
0 commit comments