def render_measurement(self): self.measurement.clear() option = self.test_measurement.currentText() if option == 'gradient': self.signal, self.grad_from, self.grad_to = self.measurement.addWidgets([ DropDown('Gradient of:', data_manager.get_growth_variables()), TextEntry('Between:', placeholder='Y = '), TextEntry('And:', placeholder='Y = ')]) elif option == 'time to': self.signal, self.time_to = self.measurement.addWidgets([ DropDown('Time for:', data_manager.get_growth_variables()), TextEntry('To reach:', placeholder='Y = ')]) elif option == 'fit parameter': model = get_model(config.fit_options[0]) self.fit, self.signal, self.param, self.fit_from, self.fit_to = self.measurement.addWidgets([ DropDown('Fit:', config.fit_options, change_action=self.update_param_list), DropDown('Of:', data_manager.get_growth_variables()), DropDown('Parameter:', model.params), TextEntry('From:', placeholder=config.xvar), TextEntry('To:', placeholder=config.xvar)]) else: self.measurement.hide() return self.measurement.show() return
def render_bounds(self): self.bounds = [] self.bound_input.clear() if self.set_bounds.isChecked(): self.resize(self.width * 3, self.height) model = get_model(self.fit_option.currentText(), '', '') for i, param in enumerate(model.params): self.bounds.append(ParameterBounds(param)) self.bound_input.addWidget(self.bounds[i]) self.bound_input.addWidget(Spacer()) self.bound_input.show() else: self.bound_input.hide() self.resize(self.width, self.height)
def get_replicate_fits(self, index, signal_name, fit_name, fit_from, fit_to, fit_param): fit_start = None if fit_name == 'exponential': fit_start = [1, 1./config.unit_map[config.xvar]] model = get_model(fit_name) func = model.func() xdatas, ydatas = self.get_replicate_xy_data(index, signal_name) values = [] for rep_i, xdata in enumerate(xdatas): fit_x, fit_y, _ = get_fit_data_range(xdata, ydatas[rep_i], None, fit_from, fit_to) fit_result, _ = curve_fit(func, fit_x, fit_y, p0=fit_start) for i, param in enumerate(model.params): if param == fit_param: values.append(fit_result[i]) return values
def get_all_fit_params(self, signal_name, fit_name, fit_from, fit_to, fit_param): logger.debug('Fitting %s with %s from %.2f to %.2f and recording %s' % ( signal_name, fit_name, fit_from, fit_to, fit_param)) values = [] errors = [] for i, _ in enumerate(self.growth_data.data_files): fit_result, covm = self.get_fit( i, signal_name, fit_name, fit_from, fit_to) param_errors = np.sqrt(np.diag(covm)) model = get_model(fit_name) for i, param in enumerate(model.params): if param == fit_param: values.append(fit_result[i]) errors.append(param_errors[i]) return values, errors
def fit_data(self): logger.debug('Fitting %s with %s' % (config.fit_curve, config.fit_type)) # Find the curve to fit fit_index = -1 for i, dat in enumerate(data_manager.get_growth_data_files()): if config.fit_curve == dat.label: fit_index = i # If the data hasn't been found if fit_index == -1: return fit_x, _, _ = data_manager.get_fit_data(fit_index) x_unit, y_unit = data_manager.get_units(fit_index) model = get_model(config.fit_type, x_unit, y_unit) func = model.func() fit_result, covm = data_manager.get_fit(fit_index) self.axes.plot(fit_x, func(fit_x, *fit_result), '-', color='r', label='Fit') bounding_box = dict(boxstyle="round", ec=( 1., 0.5, 0.5), fc=(1., 0.8, 0.8)) if config.show_fit_text: self.axes.text(0.25, 0.95, model.latex, transform=self.axes.transAxes, bbox=bounding_box, picker=True) if config.show_fit_result and not config.show_fit_errors: self.axes.text(0.25, 0.65, model.param_text(fit_result), transform=self.axes.transAxes, bbox=bounding_box, picker=True) if config.show_fit_result and config.show_fit_errors: self.axes.text(0.25, 0.65, model.param_text_error(fit_result, covm), transform=self.axes.transAxes, bbox=bounding_box, picker=True) return
def get_fit(self, index, signal_name=None, fit_name=None, fit_from=None, fit_to=None, fit_start=None, fit_min=None, fit_max=None): if signal_name is None: signal_name = config.yvar if fit_name is None: fit_name = config.fit_type if fit_from is None: fit_from = config.fit_from if fit_to is None: fit_to = config.fit_to if fit_start is None: fit_start = config.fit_start if fit_min is None: fit_min = config.fit_min if fit_max is None: fit_max = config.fit_max bounds = (-np.inf, np.inf) if fit_min is not None and fit_min != [] and fit_max is not None and fit_max != []: bounds = (fit_min, fit_max) if fit_start == []: fit_start = None if fit_start is None and fit_name == 'exponential': fit_start = [1, 1./config.unit_map[config.xvar]] fit_x, fit_y, fit_sigma = self.get_fit_data( index, signal_name, fit_from, fit_to) model = get_model(fit_name) func = model.func() # If there are replicate files then average the data if fit_sigma is not None: fit_result, covm = curve_fit(func, fit_x, fit_y, sigma=fit_sigma, p0=fit_start, bounds=bounds) else: fit_result, covm = curve_fit(func, fit_x, fit_y, p0=fit_start, bounds=bounds) return fit_result, covm
def test_models(self): with self.assertRaises(RuntimeError): get_model('none') model = get_model('flat line', 'xunit', 'yunit') func = model.func() self.assertEqual(func([2], 4), 4) self.assertEqual(model.param_text([4]), '$p$ = 4.00 yunit') self.assertEqual(model.param_text_error( [4], [1]), '$p$ = 4.00 ($\pm$1.00) yunit') self.assertEqual(model.get_latex_param('Y intercept (p)'), '$p$') self.assertEqual(model.get_units('Y intercept (p)'), 'yunit') model = get_model('linear') func = model.func() self.assertEqual(func([2], 4, 4), 12) model = get_model('quadratic') func = model.func() self.assertEqual(func([2], 4, 4, 4), 28) model = get_model('exponential') func = model.func() self.assertEqual(math.floor(func([2], 4, 2)), 218) model = get_model('zweitering') func = model.func() self.assertEqual(math.floor(func([2], 0, 40, 0.4, 4)), 4)
def update_param_list(self, fit_name): self.param.clear() model = get_model(fit_name, "", "") self.param.addItems(model.params)
def __init__(self, text, parent=None): self.item = QListWidgetItem() self.type = text # Horizontal box layout layout = LayoutWidget(QHBoxLayout) spacer = layout.addWidget(QWidget()) spacer.setFixedWidth(10 * config.wr) # Add a delete button layout.addWidget(DeleteButton(clicked=parent.remove_item)) # Add a label with row type if (text == 'profile'): layout.addWidget(RoundLabel('Profile')) if (text == 'reactor'): layout.addWidget(RoundLabel('Reactor')) # Add other options based on type # Gradient needs a start and end measurement point in Y if (text == 'gradient'): self.data, self.grad_from, self.grad_to = layout.addWidgets([ DropDown('Gradient of:', data_manager.get_growth_variables()), TextEntry('Between:', default=-1, placeholder='Y = '), TextEntry('And:', default=-1, placeholder='Y = ') ]) # Time to needs a Y point to reach if (text == 'time to'): self.data, self.time_to = layout.addWidgets([ DropDown('Time for:', data_manager.get_growth_variables()), TextEntry('To reach:', default=-1, placeholder='Y = ') ]) # Average of a condition needs condition and start and end time if (text == 'average of condition'): self.condition, self.start_t, self.end_t = layout.addWidgets([ DropDown('Average of:', data_manager.get_condition_variables()), TextEntry('Between:', default=-1, placeholder=config.xvar), TextEntry('And:', default=-1, placeholder=config.xvar) ]) # Condition at time needs condition and time if (text == 'condition at time'): self.condition, self.time = layout.addWidgets([ DropDown('Value of:', data_manager.get_condition_variables()), TextEntry('At:', default=-1, placeholder=config.xvar) ]) # Value of fit parameter needs fit and parameter if (text == 'fit parameter'): model = get_model(config.fit_options[0], '', '') self.fit, self.data, self.param, self.fit_from, self.fit_to, self.show_error = layout.addWidgets( [ DropDown('Fit:', config.fit_options, change_action=self.update_param_list), DropDown('Data:', data_manager.get_growth_variables()), DropDown('Parameter:', model.params), TextEntry('From:', default=-1, placeholder=config.xvar), TextEntry('To:', default=-1, placeholder=config.xvar), CheckBox("Show error") ]) # Pad out the row layout.layout.addStretch() layout.layout.setSpacing(5) layout.layout.setContentsMargins(10, 10, 50, 5) self.widget = layout.widget self.item.setSizeHint(self.widget.sizeHint())
def initUI(self): self.setGeometry(self.left, self.top, self.width, self.height) # Configuration tab corr_config = LayoutWidget(QVBoxLayout, margin=5, spacing=0) # X axis selection = condition variable # Dropdown of condition variables OR take from main plot self.condition = corr_config.addWidget( DropDown('X-axis: Average of', data_manager.get_condition_variables())) # Y axis selection = growth related measurement # Dropdown of y variables (OD/CD) OR take from main plot self.data = corr_config.addWidget( DropDown('Y-axis:', data_manager.get_growth_variables())) # Choice of fit and fit parameter fit_option = LayoutWidget(QHBoxLayout) model = get_model(config.fit_options[0]) self.fit, self.param = fit_option.addWidgets([ DropDown('Fit:', config.fit_options, change_action=self.update_param_list), DropDown('Parameter:', model.params) ]) corr_config.addWidget(fit_option.widget) range_option = LayoutWidget(QHBoxLayout) self.start_t, self.end_t = range_option.addWidgets([ TextEntry('Between:', default=-1, placeholder=config.xvar), TextEntry('And:', default=-1, placeholder=config.xvar) ]) corr_config.addWidget(range_option.widget) self.figure_title = corr_config.addWidget(TextEntry('Figure title:')) title_option = LayoutWidget(QHBoxLayout) self.x_title, self.y_title = title_option.addWidgets( [TextEntry('X-axis title:'), TextEntry('Y-axis title:')]) corr_config.addWidget(title_option.widget) options = LayoutWidget(QHBoxLayout) self.label, self.calc_correlation = options.addWidgets( [CheckBox('Label'), CheckBox('Calculate correlation')]) corr_config.addWidget(options.widget) # Plot button corr_config.addWidget(Button('Plot', clicked=self.update_plot)) self.tabs.addTab(corr_config.widget, 'Configuration') # Plot tab plot_view = LayoutWidget(QGridLayout, margin=5, spacing=10) # Plot self.plot = plot_view.addWidget( CorrelationCanvas(self, width=10 * config.wr, height=4 * config.hr, dpi=100 * config.wr), 0, 0, 4, 4) shadow = QGraphicsDropShadowEffect(blurRadius=10 * config.wr, xOffset=3 * config.wr, yOffset=3 * config.hr) self.plot.setGraphicsEffect(shadow) self.plot.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Save button plot_view.addWidget(Button('Save', clicked=self.save_plot), 4, 0, 1, 4) self.tabs.addTab(plot_view.widget, 'Plot')
def update_plot(self): self.parent.update_config() logger.debug('Updating the correlation plot') self.plot_config.clear() # Process the data here x_data, x_error = data_manager.get_averages( self.condition.currentText(), self.start_t.get_float(), self.end_t.get_float()) y_data, y_error = data_manager.get_all_fit_params( self.data.currentText(), self.fit.currentText(), self.start_t.get_float(), self.end_t.get_float(), self.param.currentText()) tunit = 's' if config.xvar == 'minutes': tunit = 'min' if config.xvar == 'hours': tunit = 'hr' if config.xvar == 'days': tunit = 'day' # Create the X axis title x_title = self.x_title.text() if x_title == '': condition_unit = data_manager.get_condition_unit( self.condition.currentText()) x_title = ('Average %s [%s]' % (self.condition.currentText(), condition_unit)) self.plot_config.x_title = x_title # Create the Y axis title y_title = self.y_title.text() if y_title == '': data_unit = data_manager.get_growth_unit(self.data.currentText()) model = get_model(self.fit.currentText(), tunit, data_unit) y_title = ('%s [%s] (%s)' % (model.get_latex_param(self.param.currentText()), model.get_units(self.param.currentText()), self.data.currentText())) self.plot_config.y_title = y_title self.plot_config.title = self.figure_title.text() labels = [] for dat in data_manager.get_growth_data_files(): labels.append('Name: %s\nReactor: %s\nProfile: %s' % (dat.label, dat.reactor, dat.profile)) # Remove any broken fits for i, yerr in enumerate(y_error): logger.debug('Fit %i: x=%.2f (%.2f), y=%.2f (%.2f)' % (i, x_data[i], x_error[i], y_data[i], y_error[i])) if y_data[i] == 1 and yerr > 50: logger.warning('Fit ' + str(i) + ' failed') else: self.plot_config.x_data.append(x_data[i]) self.plot_config.y_data.append(y_data[i]) self.plot_config.x_error.append(x_error[i]) self.plot_config.y_error.append(y_error[i]) if self.label.isChecked(): self.plot_config.labels.append(labels[i]) # Work out correlation coefficient if self.calc_correlation.isChecked(): corr_coef = np.corrcoef(self.plot_config.x_data, self.plot_config.y_data) self.plot_config.correlation_coeff = corr_coef[1][0] else: self.plot_config.correlation_coeff = None self.plot.plot(self.plot_config)