diff --git a/scene_checks.py b/scene_checks.py index ccdf896b3ee441e638e1984ac5c05367913b3539..17c6c13186e4e6be9391d252dbdc2da048b8a287 100644 --- a/scene_checks.py +++ b/scene_checks.py @@ -1,15 +1,69 @@ -from util import BaseCheckList +from util import BaseCheckList, invalidate_records +import pandas as pd +import numpy as np def hatch_check(frame, parameters): + """ + Check that the hatch is open on sky views + """ + if not np.in1d(['hatchOpen','sceneMirrorPosition'], frame.columns).all(): + return frame + + frame['hatch_check'] = ((frame.hatchOpen != 1) & + (~frame.sceneMirrorPosition.isin([ord('H'), ord('A')]))) * 1 + return frame + def safing_check(frame, parameters): + """ + Check that the mirror doesn't safe during a calibration view and contaminate other records + """ + if not np.in1d(['hatchOpen','sceneMirrorPosition'], frame.columns).all(): + return frame + + hatch_closing = ((frame.hatchOpen == 1) & ((frame.hatchOpen == -3).diff(-1) == 1)).shift(1) + frame['safing_check'] = hatch_closing & frame.sceneMirrorPosition.isin([ord('H'), ord('A')]) + frame = invalidate_records(frame, 'safing_check') return frame + def encoder_check(frame, parameters): return frame + class CheckList(BaseCheckList): checks = [hatch_check, safing_check, encoder_check] + +#### TESTS ##### + +def test_hatch_check(): + frame = pd.DataFrame({ + 'hatchOpen':[1,1,0], + 'sceneMirrorPosition':[ord('H'), ord('A'), ord('S')] + }) + assert hatch_check(frame, {})['hatch_check'].values.tolist() == [0,0,1] + + frame = pd.DataFrame({ + 'hatchOpen':[1,0,1], + 'sceneMirrorPosition':[ord('H'), ord('A'), ord('S')] + }) + assert hatch_check(frame, {})['hatch_check'].values.tolist() == [0,0,0] + + +def test_safing_check(): + frame = pd.DataFrame({ + 'hatchOpen':[0,0,0], + 'sceneMirrorPosition':[ord('H'), ord('A'), ord('S')] + }) + assert safing_check(frame, {})['safing_check'].values.tolist() == [0,0,0] + + frame = pd.DataFrame({ + 'hatchOpen':[1,-3,0,0], + 'sceneMirrorPosition':[ord('S'), ord('H'), ord('A'), ord('S')] + }) + assert safing_check(frame, {})['safing_check'].values.tolist() == [1,1,0,1] + + diff --git a/state_checks.py b/state_checks.py index 0af097e3bff32af0ab22b3d1ebd6f8143cd954f8..df3f37460723e25fd95a5dc96eacf75ff999e004 100644 --- a/state_checks.py +++ b/state_checks.py @@ -1,9 +1,29 @@ -from util import BaseCheckList +from util import BaseCheckList, invalidate_records +import pandas as pd +import numpy as np def detector_check(frame, parameters): + """ + Check that the detector temp is in range + """ + if 'detectorTemp' not in frame.columns: + return frame + frame['detector_check'] = (frame['detectorTemp'] > 90) * 1 + frame = invalidate_records(frame, 'detector_check') return frame def hbb_thermistor_check(frame, parameters): + """ + Check that all HBB thermistor temps are in range + """ + if not np.in1d(['HBBbottomTemp','HBBapexTemp','HBBtopTemp'], frame.columns).all(): + return frame + frame['hbb_thermistor_check'] = ( + (abs(frame['HBBbottomTemp'] - 333) > 2) | + (abs(frame['HBBapexTemp'] - 333) > 2) | + (abs(frame['HBBtopTemp'] - 333) > 2) + ) * 1 + frame = invalidate_records(frame, 'hbb_thermistor_check') return frame def hbb_stable_check(frame, parameters): @@ -11,3 +31,32 @@ def hbb_stable_check(frame, parameters): class CheckList(BaseCheckList): checks = [detector_check, hbb_thermistor_check, hbb_stable_check] + + +#### TESTS #### + +def test_hbb_thermistor_check(): + frame = hbb_thermistor_check(pd.DataFrame({ + 'HBBbottomTemp':[300,333,336], + 'HBBapexTemp':[300,333,336], + 'HBBtopTemp':[300,333,336], + 'sceneMirrorPosition':[ord('H'), ord('A'), ord('S')] + }), {}) + assert all(frame['hbb_thermistor_check'] == [1,0,1]) + +def test_hbb_thermistor_check2(): + frame = hbb_thermistor_check(pd.DataFrame({ + 'HBBbottomTemp':[300,333,333], + 'HBBapexTemp':[300,333,333], + 'HBBtopTemp':[300,333,333], + 'sceneMirrorPosition':[ord('H'), ord('A'), ord('S')] + }), {}) + assert all(frame['hbb_thermistor_check'] == [1,0,1]) + +def test_detector_check(): + frame = detector_check(pd.DataFrame({ + 'detectorTemp':[50,100], + 'sceneMirrorPosition':[ord('H'), ord('A')] + }), {}) + assert all(frame['detector_check'] == [0,1]) + diff --git a/test.py b/test.py index 79a0d007f97d921e0aeb81d4f159fb716bea6f90..5e759c1557a49c63dc87b5c89b652e459a6a2cf8 100644 --- a/test.py +++ b/test.py @@ -1,4 +1,5 @@ from main import check_frame +from util import invalidate_record, invalidate_records import pandas as pd @@ -9,3 +10,33 @@ def test_it_works(): qc_frame = check_frame(random_dataframe, {}) assert 'qc_percent' in qc_frame.columns print(qc_frame) + +def test_invalidate_record(): + invalidated = invalidate_record(three_scenes.copy(), 2, 'test', .5) + assert invalidated.iloc[2].test == .5 + assert pd.np.isnan(invalidated.iloc[3].test) + assert pd.np.isnan(invalidated.iloc[1].test) + + tricky_index = three_scenes.copy() + tricky_index.index = tricky_index.index - 1 + invalidated = invalidate_record(tricky_index, 2, 'test', .5) + assert invalidated.iloc[2].test == .5, invalidated.test + assert pd.np.isnan(invalidated.iloc[3].test) + assert pd.np.isnan(invalidated.iloc[1].test) + + corrupt_cal = three_scenes.copy() + invalidated = invalidate_record(corrupt_cal, 3, 'test', .5) + assert invalidated.iloc[2].test == .5, invalidated.test + assert invalidated.iloc[5].test == .5, invalidated.test + + +def test_invalidate_records(): + corrupt_cal = three_scenes.copy() + corrupt_cal['test'] = 0 + corrupt_cal['test'][3] = 1 + + invalidated = invalidate_records(corrupt_cal, 'test') + assert invalidated.iloc[2].test == 1, invalidated.test + assert invalidated.iloc[5].test == 1, invalidated.test + +three_scenes = pd.DataFrame({'sceneMirrorPosition': list(map(ord, 'HASAHSAHSAH'))}) diff --git a/util.py b/util.py index 188905534b0ce608c101b57c1a78cbf4f9e95321..3209df47435b3899871efa36208288e5bc66b9a3 100644 --- a/util.py +++ b/util.py @@ -1,7 +1,47 @@ +from itertools import takewhile +import numpy as np +import pandas as pd -def invalidate_record(frame, record, reason): - pass +def invalidate_records(frame, check_name): + for index,percent in frame.ix[frame[check_name] > 0, check_name].iteritems(): + invalidate_record(frame, index, check_name, percent) + return frame +def invalidate_record(frame, index, check_name, value): + frame.ix[frame.index[index], check_name] = value + corrupt_view = frame.iloc[index].sceneMirrorPosition + if corrupt_view in [ord('H'),ord('A')]: + + # Corrupt calibration view, must also invalidate neighboring scenes + _idx = index + 1 + while _idx < len(frame): + if frame.sceneMirrorPosition.iloc[_idx] == corrupt_view: + # Made one cycle + break + elif frame.sceneMirrorPosition.iloc[_idx] in [ord('H'), ord('A')]: + # Skip opposite calibration views + _idx += 1 + continue + else: + # Invalidate non-calibration views + frame.ix[frame.index[_idx], check_name] = value + _idx += 1 + + _idx = index - 1 + while _idx >= 0: + if frame.sceneMirrorPosition.iloc[_idx] == corrupt_view: + # Made one cycle + break + elif frame.sceneMirrorPosition.iloc[_idx] in [ord('H'), ord('A')]: + # Skip opposite calibration views + _idx -= 1 + continue + else: + # Invalidate non-calibration views + frame.ix[frame.index[_idx], check_name] = value + _idx -= 1 + + return frame class BaseCheckList: