def complete_loading(self, data=None, filename=''): """ Complete the loading and compute the slit size """ self.done = True self._data = [] if data is None: msg = "Couldn't load data" wx.PostEvent(self.parent.parent, StatusEvent(status=msg, info="warning", type='stop')) return if not data.__class__.__name__ == "list": self._data.append(data) self._reset_data.append(deepcopy(data)) else: self._data = deepcopy(data) self._reset_data = deepcopy(data) self.set_values() if self.parent.parent is None: return msg = "Load Complete" wx.PostEvent(self.parent.parent, StatusEvent(status=msg, info="info", type='stop'))
def _onEVT_SLICER_PARS(self, event): """ receive an event containing parameters values to reset the slicer @param event: event of type SlicerParameterEvent with params as attribute """ # # Post e message to declare what kind of event has being received wx.PostEvent(self.base.parent, StatusEvent(status="Boxsum._onEVT_SLICER_PARS")) event.Skip() # # reset the slicer with the values contains the event.params dictionary if event.type == self.__class__.__name__: self.set_params(event.params) self.base.update()
def load(self): """ load image files """ parent = self.parent if parent is None: location = os.getcwd() else: location = parent._default_save_location path_list = self.choose_data_file(location=location) if path_list is None: return if len(path_list) >= 0 and path_list[0] is not None: if parent is not None: parent._default_save_location = os.path.dirname(path_list[0]) err_msg = '' for file_path in path_list: basename = os.path.basename(file_path) _, extension = os.path.splitext(basename) try: # Note that matplotlib only reads png natively. # Any other formats (tiff, jpeg, etc) are passed # to PIL which seems to have a problem in version # 1.1.7 that causes a close error which shows up in # the log file. This does not seem to have any adverse # effects. PDB --- September 17, 2017. img = mpimg.imread(file_path) is_png = extension.lower() == '.png' plot_frame = ImageFrame(parent, -1, basename, img) plot_frame.Show(False) ax = plot_frame.plotpanel if not is_png: ax.subplot.set_ylim(ax.subplot.get_ylim()[::-1]) ax.subplot.set_xlabel('x [pixel]') ax.subplot.set_ylabel('y [pixel]') ax.figure.subplots_adjust(left=0.15, bottom=0.1, right=0.95, top=0.95) plot_frame.SetTitle('Picture -- %s --' % basename) plot_frame.Show(True) if parent is not None: parent.put_icon(plot_frame) except: err_msg += "Failed to load '%s'.\n" % basename if err_msg: if parent is not None: wx.PostEvent(parent, StatusEvent(status=err_msg, info="error")) else: print(err_msg)
def validate_inputs(self): msg = "You must select a" if self.q_input.GetPath() == '' and self.data_type != 'bsl': msg += " Q Axis input file." elif self.iq_input.GetPath() == '': msg += "n Intensity input file." elif self.output.GetPath() == '': msg += " destination for the converted file." if msg != "You must select a": wx.PostEvent(self.parent.manager.parent, StatusEvent(status=msg, info='error')) return return True
def extract_parameters(self, event=None): """ Called when "Extract Parameters" is clicked """ try: params = self._calculator.extract_parameters(self._transformed_data) except: params = None if params is None: msg = "Error extracting parameters." wx.PostEvent(self._manager.parent, StatusEvent(status=msg, info="Error")) return self.set_extracted_params(params)
def _onEVT_SLICER_PARS(self, event): """ receive an event containing parameters values to reset the slicer :param event: event of type SlicerParameterEvent with params as attribute """ wx.PostEvent(self.base, StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS")) event.Skip() if event.type == self.__class__.__name__: self.set_params(event.params) self.base.update()
def load_complete(self, output, message="", error_message="", path=None, info="warning"): """ post message to status bar and return list of data """ wx.PostEvent(self.parent, StatusEvent(status=message, info=info, type="stop")) # if error_message != "": # self.load_error(error_message) self.parent.add_data(data_list=output)
def on_fit(self, event): """ signal for fitting """ if self.fit_started: self._stop_fit() self.fit_started = False return flag = False # check if the current page a simultaneous fit page or a batch page if self == self._manager.sim_page: flag = (self._manager.sim_page.uid == self.uid) # making sure all parameters content a constraint if not self.batch_on and self.show_constraint.GetValue(): if not self._set_constraint(): return # model was actually selected from this page to be fit if len(self.model_to_fit) >= 1: self.manager._reset_schedule_problem(value=0) for item in self.model_list: if item[0].GetValue(): self.manager.schedule_for_fit(value=1, uid=item[2]) try: self.fit_started = True wx.CallAfter(self.set_fitbutton) if not self.manager.onFit(uid=self.uid): return except: msg = "Select at least one parameter to fit in the FitPages." wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) else: msg = "Select at least one model check box to fit " wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) self.set_state()
def complete_loading(self, data=None, filename=''): """ Complete the loading and compute the slit size """ if data is None or data.__class__.__name__ == 'Data2D': if self.parent.parent is None: return msg = "Slit Length cannot be computed for 2D Data" wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop')) return self.data_name_tcl.SetValue(str(data.filename)) #compute the slit size try: x = data.x y = data.y if x == [] or x is None or y == [] or y is None: msg = "The current data is empty please check x and y" raise ValueError, msg slit_length_calculator = SlitlengthCalculator() slit_length_calculator.set_data(x=x, y=y) slit_length = slit_length_calculator.calculate_slit_length() except: if self.parent.parent is None: return msg = "Slit Size Calculator: %s" % (sys.exc_value) wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop')) return self.slit_size_tcl.SetValue(str(slit_length)) #Display unit self.slit_size_unit_tcl.SetValue('[Unknown]') if self.parent.parent is None: return msg = "Load Complete" wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop'))
def on_convert(self, event): """Called when the Convert button is clicked""" if not self.validate_inputs(): return self.sample.ID = self.title try: if self.data_type == 'ascii': qdata = self.extract_ascii_data(self.q_input.GetPath()) iqdata = np.array( [self.extract_ascii_data(self.iq_input.GetPath())]) self.convert_1d_data(qdata, iqdata) elif self.data_type == 'otoko': qdata, iqdata = self.extract_otoko_data(self.q_input.GetPath()) self.convert_1d_data(qdata, iqdata) elif self.data_type == 'ascii2d': loader = ASCII2DLoader(self.iq_input.GetPath()) data = loader.load() dataset = [data] # ASCII 2D only ever contains 1 frame self.convert_2d_data(dataset) else: # self.data_type == 'bsl' dataset = self.extract_bsl_data(self.iq_input.GetPath()) if dataset is None: # Cancelled by user return self.convert_2d_data(dataset) except Exception as ex: msg = str(ex) wx.PostEvent(self.parent.manager.parent, StatusEvent(status=msg, info='error')) return wx.PostEvent(self.parent.manager.parent, StatusEvent(status="Conversion completed."))
def on_convert(self, event): """Called when the Convert button is clicked""" if not self.validate_inputs(): return self.sample.ID = self.title try: if self.data_type == 'ascii': qdata = self.extract_ascii_data(self.q_input.GetPath()) iqdata = np.array( [self.extract_ascii_data(self.iq_input.GetPath())]) self.convert_1d_data(qdata, iqdata) elif self.data_type == 'otoko': qdata, iqdata = self.extract_otoko_data(self.q_input.GetPath()) self.convert_1d_data(qdata, iqdata) else: # self.data_type == 'bsl' dataset = self.extract_bsl_data(self.iq_input.GetPath()) if dataset is None: # Cancelled by user return metadata = self.get_metadata() for key, value in metadata.iteritems(): setattr(dataset[0], key, value) w = NXcanSASWriter() w.write(dataset, self.output.GetPath()) except Exception as ex: msg = str(ex) wx.PostEvent(self.parent.manager.parent, StatusEvent(status=msg, info='error')) return wx.PostEvent(self.parent.manager.parent, StatusEvent(status="Conversion completed."))
def _compute_background(self, event=None): """ Compute the background level based on the position of the upper q bars """ if event is not None: event.Skip() self._on_enter_input() try: bg = self._calculator.compute_background(self.qmax) self.set_background(bg) except Exception as e: msg = "Error computing background level:\n" msg += str(e) wx.PostEvent(self._manager.parent, StatusEvent(status=msg, info="error"))
def _estimate_completed(self, alpha, message, elapsed): """ Parameter estimation completed, display the results to the user :param alpha: estimated best alpha :param elapsed: computation time """ # Save useful info self.elapsed = elapsed self.control_panel.alpha_estimate = alpha if message is not None: wx.PostEvent(self.parent, StatusEvent(status=str(message))) self.perform_estimateNT()
def _validate_inputs(self): """ Check that the values for qmin and qmax in the input boxes are valid """ if self._data is None: return False qmin_valid = check_float(self._qmin_input) qmax1_valid = check_float(self._qmax1_input) qmax2_valid = check_float(self._qmax2_input) qmax_valid = qmax1_valid and qmax2_valid background_valid = check_float(self._background_input) msg = "" if (qmin_valid and qmax_valid and background_valid): qmin = float(self._qmin_input.GetValue()) qmax1 = float(self._qmax1_input.GetValue()) qmax2 = float(self._qmax2_input.GetValue()) background = float(self._background_input.GetValue()) if not qmin > self._data.x.min(): msg = "qmin must be greater than the lowest q value" qmin_valid = False elif qmax2 < qmax1: msg = "qmax1 must be less than qmax2" qmax_valid = False elif qmin > qmax1: msg = "qmin must be less than qmax" qmin_valid = False elif background > self._data.y.max(): msg = "background must be less than highest I" background_valid = False if not qmin_valid: self._qmin_input.SetBackgroundColour('pink') if not qmax_valid: self._qmax1_input.SetBackgroundColour('pink') self._qmax2_input.SetBackgroundColour('pink') if not background_valid: self._background_input.SetBackgroundColour('pink') if msg != "": wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) if (qmin_valid and qmax_valid and background_valid): self._qmin_input.SetBackgroundColour(wx.WHITE) self._qmax1_input.SetBackgroundColour(wx.WHITE) self._qmax2_input.SetBackgroundColour(wx.WHITE) self._background_input.SetBackgroundColour(wx.WHITE) self._qmin_input.Refresh() self._qmax1_input.Refresh() self._qmax2_input.Refresh() self._background_input.Refresh() return (qmin_valid and qmax_valid and background_valid)
def _estimateNT_completed(self, nterms, alpha, message, elapsed): """ Parameter estimation completed, display the results to the user :param alpha: estimated best alpha :param nterms: estimated number of terms :param elapsed: computation time """ # Save useful info self.elapsed = elapsed self.control_panel.nterms_estimate = nterms self.control_panel.alpha_estimate = alpha if not message == None: wx.PostEvent(self.parent, StatusEvent(status=str(message)))
def ask_frame_range(self, n_frames): """ Display a dialog asking the user to input the range of frames they would like to export :param n_frames: How many frames the loaded data file has :return: A dictionary containing the parameters input by the user """ valid_input = False _, ext = os.path.splitext(self.output.GetPath()) show_single_btn = (ext == '.h5') dlg = FrameSelectDialog(n_frames, show_single_btn) frames = None increment = None single_file = True while not valid_input: if dlg.ShowModal() == wx.ID_OK: msg = "" try: first_frame = int(dlg.first_input.GetValue()) last_frame = int(dlg.last_input.GetValue()) increment = int(dlg.increment_input.GetValue()) if not show_single_btn: single_file = dlg.single_btn.GetValue() if last_frame < 0 or first_frame < 0: msg = "Frame values must be positive" elif increment < 1: msg = "Increment must be greater than or equal to 1" elif first_frame > last_frame: msg = "First frame must be less than last frame" elif last_frame >= n_frames: msg = "Last frame must be less than {}".format( n_frames) else: valid_input = True except: valid_input = False msg = "Please enter valid integer values" if not valid_input: wx.PostEvent(self.parent.manager.parent, StatusEvent(status=msg)) else: return {'frames': [], 'inc': None, 'file': single_file} frames = range(first_frame, last_frame + 1, increment) return {'frames': frames, 'inc': increment, 'file': single_file}
def onLeftDown(self, event): """ left button down and ready to drag """ # Check that the LEFT button was pressed PlotPanel.onLeftDown(self, event) ax = event.inaxes if ax is not None: # data coordinate position pos_x = "%8.3g" % event.xdata pos_y = "%8.3g" % event.ydata position = "x: %s y: %s" % (pos_x, pos_y) wx.PostEvent(self.parent, StatusEvent(status=position)) self.plottable_selected(self.data2D.id) self._manager.set_panel_on_focus(self) wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
def load(self, data): """ Load data. This will eventually be replaced by our standard DataLoader class. """ class FileData(object): x = None y = None err = None path = None def __init__(self, path): self.path = path self._current_file_data = FileData(data.path) # Use data loader to load file dataread = data # Notify the user if we could not read the file if dataread is None: raise RuntimeError, "Invalid data" x = None y = None err = None if dataread.__class__.__name__ == 'Data1D': x = dataread.x y = dataread.y err = dataread.dy else: if isinstance(dataread, list) and len(dataread) > 0: x = dataread[0].x y = dataread[0].y err = dataread[0].dy msg = "PrView only allows a single data set at a time. " msg += "Only the first data set was loaded." wx.PostEvent(self.parent, StatusEvent(status=msg)) else: if dataread is None: return x, y, err raise RuntimeError, "This tool can only read 1D data" self._current_file_data.x = x self._current_file_data.y = y self._current_file_data.err = err return x, y, err
def _display_constraint(self, event): """ Show fields to add constraint """ if len(self.model_to_fit) < 1: msg = "Select at least 1 model to add constraint " wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) # hide button self._hide_constraint() return if self.show_constraint.GetValue(): self._show_all_constraint() self._show_constraint() self.FitInside() return else: self._hide_constraint() return
def load(self): """ load image files """ parent = self.parent if parent == None: location = os.getcwd() else: location = parent._default_save_location path_list = self.choose_data_file(location=location) if path_list == None: return if len(path_list) >= 0 and not (path_list[0] is None): if parent != None: parent._default_save_location = os.path.dirname(path_list[0]) err_msg = '' for file_path in path_list: basename = os.path.basename(file_path) _, extension = os.path.splitext(basename) try: img = mpimg.imread(file_path) is_png = extension.lower() == '.png' plot_frame = ImageFrame(parent, -1, basename, img) plot_frame.Show(False) ax = plot_frame.plotpanel if not is_png: ax.subplot.set_ylim(ax.subplot.get_ylim()[::-1]) ax.subplot.set_xlabel('x [pixel]') ax.subplot.set_ylabel('y [pixel]') ax.figure.subplots_adjust(left=0.15, bottom=0.1, right=0.95, top=0.95) plot_frame.SetTitle('Picture -- %s --' % basename) plot_frame.Show(True) if parent != None: parent.put_icon(plot_frame) except: err_msg += "Failed to load '%s'.\n" % basename if err_msg: if parent is not None: wx.PostEvent(parent, StatusEvent(status=err_msg, info="error")) else: print err_msg
def resetValues(self, event): """ reset detector info """ try: zmin = self.reset_zmin_ctl zmax = self.reset_zmax_ctl if zmin == None: zmin = "" if zmax == None: zmax = "" self.zmin_ctl.SetValue(str(zmin)) self.zmax_ctl.SetValue(str(zmax)) self.cmap = DEFAULT_CMAP self.cmap_selector.SetStringSelection("jet") self._on_select_cmap(event=None) except: msg = "error occurs while resetting Detector: %s" % sys.exc_value wx.PostEvent(self.parent, StatusEvent(status=msg))
def show_data(self, path=None, data=None, reset=False): """ Show data read from a file :param path: file path :param reset: if True all other plottables will be cleared """ #if path is not None: if data is not None: try: pr = self._create_file_pr(data) except: status = "Problem reading data: %s" % sys.exc_value wx.PostEvent(self.parent, StatusEvent(status=status)) raise RuntimeError, status # If the file contains nothing, just return if pr is None: raise RuntimeError, "Loaded data is invalid" self.pr = pr # Make a plot of I(q) data if self.pr.err is None: new_plot = Data1D(self.pr.x, self.pr.y) new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM else: new_plot = Data1D(self.pr.x, self.pr.y, dy=self.pr.err) new_plot.name = IQ_DATA_LABEL new_plot.xaxis("\\rm{Q}", 'A^{-1}') new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") new_plot.interactive = True new_plot.group_id = GROUP_ID_IQ_DATA new_plot.id = self.data_id new_plot.title = "I(q)" wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="I(q)", reset=reset)) self.current_plottable = new_plot # Get Q range self.control_panel.q_min = min(self.pr.x) self.control_panel.q_max = max(self.pr.x)
def onLeftDown(self, event): """ left button down and ready to drag """ # Check that the LEFT button was pressed if event.button == 1: self.leftdown = True ax = event.inaxes if ax is not None: self.xInit, self.yInit = event.xdata, event.ydata try: pos_x = float(event.xdata) # / size_x pos_y = float(event.ydata) # / size_y pos_x = "%8.3g" % pos_x pos_y = "%8.3g" % pos_y self.position = str(pos_x), str(pos_y) wx.PostEvent(self.parent, StatusEvent(status=self.position)) except: self.position = None
def extract_otoko_data(self, filename): """ Extracts data from a 1D OTOKO file :param filename: The OTOKO file to load the data from :return: A numpy array containing the extracted data """ loader = OTOKOLoader(self.q_input.GetPath(), self.iq_input.GetPath()) otoko_data = loader.load_otoko_data() qdata = otoko_data.q_axis.data iqdata = otoko_data.data_axis.data if len(qdata) > 1: msg = ("Q-Axis file has multiple frames. Only 1 frame is " "allowed for the Q-Axis") wx.PostEvent(self.parent.manager.parent, StatusEvent(status=msg, info="error")) return else: qdata = qdata[0] return qdata, iqdata
def setup_plot_inversion(self, alpha, nfunc, d_max, q_min=None, q_max=None, bck=False, height=0, width=0): """ Set up inversion from plotted data """ self.alpha = alpha self.nfunc = nfunc self.max_length = d_max self.q_min = q_min self.q_max = q_max self.has_bck = bck self.slit_height = height self.slit_width = width try: pr = self._create_plot_pr() if pr is not None: self.pr = pr self.perform_inversion() except: wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))
def estimate_file_inversion(self, alpha, nfunc, d_max, data, path=None, q_min=None, q_max=None, bck=False, height=0, width=0): """ Estimate parameters for inversion """ self.alpha = alpha self.nfunc = nfunc self.max_length = d_max self.q_min = q_min self.q_max = q_max self.has_bck = bck self.slit_height = height self.slit_width = width try: pr = self._create_file_pr(data) if pr is not None: self.pr = pr self.perform_estimate() except: wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))
def set_extracted_params(self, params=None, reset=False): """ Displays the values of the parameters extracted from the Fourier transform """ self.extracted_params = params error = False if params is None: if not reset: error = True for output in self._output_boxes.values(): output.SetValue('-') else: if len(params) < len(OUTPUT_STRINGS): # Not all parameters were calculated error = True for key, value in params.iteritems(): rounded = self._round_sig_figs(value, 6) self._output_boxes[key].SetValue(rounded) if error: msg = 'Not all parameters were able to be calculated' wx.PostEvent(self._manager.parent, StatusEvent(status=msg, info='error'))
def onEditLabels(self, event): """ Edit legend label """ try: selected_plot = self.plots[self.graph.selected_plottable] except: selected_plot = self.plots[self.data2D.id] label = selected_plot.label dial = TextDialog(None, -1, 'Change Label', label) if dial.ShowModal() == wx.ID_OK: try: FONT = FontProperties() newlabel = dial.getText() font = FONT.copy() font.set_size(dial.getSize()) font.set_family(dial.getFamily()) font.set_style(dial.getStyle()) font.set_weight(dial.getWeight()) colour = dial.getColor() if len(newlabel) > 0: # update Label selected_plot.label = newlabel self.graph.title(newlabel) self.title_label = selected_plot.label self.title_font = font self.title_color = colour ## render the graph self.subplot.set_title(label=self.title_label, fontproperties=self.title_font, color=self.title_color) self._is_changed_legend_label = True self.subplot.figure.canvas.draw_idle() except: msg = "Add Text: Error. Check your property values..." logger.error(msg) if self.parent is not None: wx.PostEvent(self.parent, StatusEvent(status=msg)) dial.Destroy()
def transform_complete(self, transform=None): """ Called from FourierThread when calculation has completed """ self._transform_btn.SetLabel("Transform") if transform is None: msg = "Error calculating Transform." if self.transform_type == 'hilbert': msg = "Not yet implemented" wx.PostEvent(self._manager.parent, StatusEvent(status=msg, info="Error")) self._extract_btn.Disable() return self._transformed_data = transform import numpy as np plot_x = transform.x[np.where(transform.x <= 200)] plot_y = transform.y[np.where(transform.x <= 200)] self._manager.show_data(Data1D(plot_x, plot_y), TRANSFORM_LABEL1) # Only enable extract params button if a fourier trans. has been done if self.transform_type == 'fourier': self._extract_btn.Enable() else: self._extract_btn.Disable()
def onLeftDown(self, event): """ left button down and ready to drag Display the position of the mouse on the statusbar """ # self.parent.set_plot_unfocus() self._get_cusor_lines(event) ax = event.inaxes PlotPanel.onLeftDown(self, event) if ax is not None: try: pos_x = float(event.xdata) # / size_x pos_y = float(event.ydata) # / size_y pos_x = "%8.3g" % pos_x pos_y = "%8.3g" % pos_y self.position = str(pos_x), str(pos_y) wx.PostEvent(self.parent, StatusEvent(status=self.position)) except: self.position = None # unfocus all self.parent.set_plot_unfocus() # post nd event to notify guiframe that this panel is on focus wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))