def move_peak_start(self, x_axis_time, peak_index): """ Moves the peak window start point to where ever the user clicked on the screen :param x_axis_time: :param peak_index: :return: """ picked_peak_start = int( self.slk_data.peak_starts[self.current_nutrient][peak_index]) win_start = int( self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowStart']) win_length = int( self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowSize']) # If picked point is less than the end of the peak window i.e. valid if x_axis_time < (picked_peak_start + win_start + win_length): # If picked point is further along than the current peak window if x_axis_time > (picked_peak_start + win_start): window_start_time = x_axis_time - picked_peak_start new_window_length = win_length - ( x_axis_time - (picked_peak_start + win_start)) self.processing_parameters['nutrientprocessing'][ 'processingpars'][self.current_nutrient][ 'windowStart'] = window_start_time self.processing_parameters['nutrientprocessing'][ 'processingpars'][self.current_nutrient][ 'windowSize'] = new_window_length # If picked point is less than the start of the peak window if x_axis_time < (picked_peak_start + win_start): window_start_time = x_axis_time - picked_peak_start new_window_length = win_length + ( (picked_peak_start + win_start) - x_axis_time) self.processing_parameters['nutrientprocessing'][ 'processingpars'][self.current_nutrient][ 'windowStart'] = window_start_time self.processing_parameters['nutrientprocessing'][ 'processingpars'][self.current_nutrient][ 'windowSize'] = new_window_length # If point is actually less than the value given of the peak starts... if x_axis_time < picked_peak_start: time_offset = picked_peak_start - x_axis_time adjusted_peak_starts = [ p_s - time_offset for p_s in self.slk_data.peak_starts ] self.slk_data.peak_starts = adjusted_peak_starts self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine(trace_redraw=True)
def update_from_dialog(self, index): self.slk_data.cup_types[index] = self.peak_display.peakcupline.text() self.w_d.dilution_factor[index] = int( self.peak_display.dilutionline.text()) # TODO: Add validation check to these user editable fields rev_flag_convert = {x: y for y, x in self.FLAG_CONVERTER.items()} self.w_d.quality_flag[index] = rev_flag_convert[ self.peak_display.flagbox.currentText()] self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine(trace_redraw=True)
def shift_trace(self, x_axis_time, direction): """ Function for physically shifting the whole trace by 3 time points. Used to realign the trace if necessary :param x_axis_time: :param direction: :return: """ if direction == 'right': for i in range(3): self.chd_data.ad_data[self.current_nutrient].insert( int(x_axis_time), 100) elif direction == 'left': for i in range(3): self.chd_data.ad_data[self.current_nutrient].pop( int(x_axis_time)) self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine(trace_redraw=True)
def move_peak_end(self, x_axis_time, peak_index): """ Moves the peak end after a user has clicked into a spot on the trace and pressed move end :param x_axis_time: :param peak_index: :return: """ picked_peak_start = int( self.slk_data.peak_starts[self.current_nutrient][peak_index]) win_start = int( self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowStart']) win_length = int( self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowSize']) peak_window_start = picked_peak_start + win_start if x_axis_time > (picked_peak_start + win_start): window_end = picked_peak_start + win_start + win_length if x_axis_time > window_end: window_end_increase = x_axis_time - window_end print(window_end_increase) self.processing_parameters['nutrientprocessing'][ 'processingpars'][self.current_nutrient][ 'windowSize'] = win_length + window_end_increase if window_end > x_axis_time: window_end_decrease = window_end - x_axis_time self.processing_parameters['nutrientprocessing'][ 'processingpars'][self.current_nutrient][ 'windowSize'] = win_length - window_end_decrease self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine(trace_redraw=True)
def proceed(self): #self.main_trace.cla() #self.tracecanvas.draw() self.store_data() # If the matching lat/lons check box is active assume the file is a underway one. Pull out samples and # find the latitude and longitudes that correspond if self.find_lat_lons.isChecked(): print('Checked') try: complete = psn.match_lat_lons_routine( self.path, self.project, self.database, self.current_nutrient, self.processing_parameters, self.w_d, self.slk_data) except Exception: print(traceback.print_exc()) index = self.slk_data.active_nutrients.index(self.current_nutrient) try: self.current_nutrient = self.slk_data.active_nutrients[index + 1] except IndexError: print('Processing completed') logging.info( f'Processing successfully completed for nutrient file - {self.file}' ) #plt.close('all') self.close() self.analysistraceLabel.setText( '<b>Processing file: </b>' + str(self.file) + ' | <b>Analysis Trace: </b>' + str(self.current_nutrient).capitalize()) self.w_d.analyte = self.current_nutrient self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine()
def keyPressEvent(self, event): """ Handles keyboard button presses and completes functions accordingly :param event: :return: """ print(event.key()) if event.key() == 65: # Assign A to move left self.move_camera_left() elif event.key() == 68: # Assign D to move right self.move_camera_right() elif event.key() == 87: # Assign W to zoom in self.zoom_in() elif event.key() == 88: # Assign X to zoom out self.zoom_out() elif event.key() == 83: # Assign S to zoom fit self.zoom_fit() elif event.key() == 81: # Assign Q to auto zoom toggle if self.auto_size.isChecked(): self.auto_size.setChecked(False) else: self.auto_size.setChecked(True) elif event.key() == 78: # Assign N to iterate through tabs curr_tab = self.qctabs.currentIndex() if curr_tab == (len(self.qctabs) - 1): self.qctabs.setCurrentIndex(0) else: self.qctabs.setCurrentIndex(curr_tab + 1) elif event.key() == 90: # Assign Z to shift peak window left ws = int(self.processing_parameters['nutrientprocessing'] ['processingpars'][self.current_nutrient]['windowStart']) ws = ws - 2 self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowStart'] = ws self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine(trace_redraw=True) elif event.key() == 67: # Assign C to shift peak window right ws = int(self.processing_parameters['nutrientprocessing'] ['processingpars'][self.current_nutrient]['windowStart']) ws = ws + 2 self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowStart'] = ws self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.interactive_routine(trace_redraw=True) # Below is only meant to be used for DEVELOPMENT PURPOSES, used to inject random values into peak picking # to check how the software responds, used to check speed of processing and robustness elif event.key( ) == 82: # R Imitates changing peak windows etc, for testing optimisation of processing and draw random_modifier = np.random.randint(low=15, high=45) random_modifier2 = np.random.randint(low=2, high=30) print(random_modifier) print(random_modifier2) self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowStart'] = random_modifier self.processing_parameters['nutrientprocessing']['processingpars'][ self.current_nutrient]['windowSize'] = random_modifier self.w_d.quality_flag = [ self.w_d.quality_flag[i] if x not in [4, 5] else 1 for i, x in enumerate(self.w_d.quality_flag) ] self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) self.draw_data(self.chd_data, self.w_d, self.current_nutrient, False) self.interactive_routine(trace_redraw=True)
def __init__(self, file, database, path, project, interactive=True, rereading=False, perf_mode=False, ultra_perf_mode=False): screenwidth = QDesktopWidget().availableGeometry().width() screenheight = QDesktopWidget().availableGeometry().height() super().__init__((screenwidth * 0.85), (screenheight * 0.85), 'HyPro - Process Nutrient Analysis') # Set flagging colours self.FLAG_COLORS = { 1: '#68C968', 2: '#45D4E8', 3: '#C92724', 4: '#3CB6C9', 5: '#C92724', 6: '#DC9530', 91: '#9CCDD6', 92: '#F442D9', 8: '#3CB6C9' } self.FLAG_CONVERTER = { 1: 'Good', 2: 'Suspect', 3: 'Bad', 4: 'Shape Sus', 5: 'Shape Bad', 91: 'CalError Sus', 92: 'CalError Bad', 8: 'Dup Diff' } # Load in the processing parameters self.processing_parameters = load_proc_settings(path, project) self.file_path = path + '/' + 'Nutrients' + '/' + file self.file = file self.path = path self.project = project self.database = database self.interactive = interactive self.rereading = rereading self.perf_mode = perf_mode self.ultra_perf_mode = ultra_perf_mode # General HyPro settings, use for setting theme of window with open('C:/HyPro/hyprosettings.json', 'r') as temp: params = json.loads(temp.read()) # Load up theme for window if params['theme'] == 'normal': plt.style.use(style.mplstyle['normal']) self.theme = 'normal' else: plt.style.use(style.mplstyle['dark']) self.theme = 'dark' # Holds all the calculation data self.w_d = WorkingData(file) # Pull out the data from the files in the directory try: self.slk_data, self.chd_data, self.w_d, self.current_nutrient = rsn.get_data_routine( self.file_path, self.w_d, self.processing_parameters, self.database) self.slk_data.run_number = int( file[len(self.processing_parameters['analysisparams']['seal'] ['filePrefix']):-4]) # Process the data and return calculated values self.w_d = psn.processing_routine(self.slk_data, self.chd_data, self.w_d, self.processing_parameters, self.current_nutrient) # If interactive processing is activated on the Processing Menu window, then continue to plot everything up # Otherwise store data and exit without drawing or creating any UI elements if self.interactive: self.init_ui() self.create_standard_qc_tabs() qc_cups = self.processing_parameters['nutrientprocessing'][ 'qcsamplenames'] self.create_custom_qc_tabs(self.slk_data.sample_ids, qc_cups) self.interactive_routine() else: # TODO: Store data if not interactive processing sys.exit() except TypeError: logging.error( f'Formatting error in .SLK file. Processing aborted.') traceback.print_exc() except FileNotFoundError: logging.error( 'Could not find the nutrient file, is it in the right spot? Does a Nutrient folder exist?' ) except IndexError: logging.error( 'HyPro could not find any nutrients! Please check the spelling of your analyte names' )