from itertools import takewhile import numpy as np import pandas as pd 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, annotation=''): frame.ix[frame.index[index], check_name] = value if annotation: if frame.ix[frame.index[index], 'qc_notes']: frame.ix[frame.index[index], 'qc_notes'] = ','.join([frame.ix[frame.index[index],'qc_notes'], annotation]) else: frame.ix[frame.index[index], 'qc_notes'] = annotation corrupt_view = frame.iloc[index].sceneMirrorPosition if corrupt_view in [ord('H'),ord('A')]: def invalidate_neighbor(neighbor): if frame.sceneMirrorPosition.iloc[neighbor] == corrupt_view: # Made one cycle, break return True elif frame.sceneMirrorPosition.iloc[neighbor] in [ord('H'), ord('A')]: # Skip opposite calibration views return else: # Invalidate non-calibration views frame.ix[frame.index[neighbor], check_name] = value previous_notes = frame.ix[frame.index[neighbor], 'qc_notes'] if previous_notes: frame.ix[frame.index[neighbor], 'qc_notes'] = ','.join([previous_notes, 'invalid calibration:{:d}'.format(index)]) else: frame.ix[frame.index[neighbor], 'qc_notes'] = 'invalid calibration:{:d}'.format(index) # Corrupt calibration view, must also invalidate neighboring scenes _idx = index + 1 while _idx < len(frame): if invalidate_neighbor(_idx): break _idx += 1 _idx = index - 1 while _idx >= 0: if invalidate_neighbor(_idx): break _idx -= 1 return frame class BaseCheckList: def __init__(self, *args, **kwargs): self.check_results = {} self.parameters = {} def set_params(self, parameters): self.parameters = parameters def update_qc_percent(self, frame): for check_func in self.checks: name = check_func.__name__ if name in frame.columns: results = frame[name].fillna(0) # Compute P(A U B) previous_percent = frame['qc_percent'] frame['qc_percent'] = previous_percent + results - previous_percent*results return frame def compute(self, frame): # Filter bad records from previous level filtered_frame = frame.ix[frame.qc_percent < 1].copy() for check in self.checks: filtered_frame = check(filtered_frame, self.parameters) return self.update_qc_percent(frame.combine_first(filtered_frame))