def spikes_removal_traitsui(obj, **kwargs): thisOKButton = tu.Action(name="OK", action="OK", tooltip="Close the spikes removal tool") thisApplyButton = tu.Action(name="Remove spike", action="apply", tooltip="Remove the current spike by " "interpolating\n" "with the specified settings (and find\n" "the next spike automatically)") thisFindButton = tu.Action( name="Find next", action="find", tooltip="Find the next (in terms of navigation\n" "dimensions) spike in the data.") thisPreviousButton = tu.Action(name="Find previous", action="back", tooltip="Find the previous (in terms of " "navigation\n" "dimensions) spike in the data.") view = tu.View( tu.Group( tu.Group( tu.Item( 'click_to_show_instructions', show_label=False, ), tu.Item('show_derivative_histogram', show_label=False, tooltip="To determine the appropriate threshold,\n" "plot the derivative magnitude histogram, \n" "and look for outliers at high magnitudes \n" "(which represent sudden spikes in the data)"), 'threshold', show_border=True, ), tu.Group('add_noise', 'interpolator_kind', 'default_spike_width', tu.Group('spline_order', enabled_when='interpolator_kind == "Spline"'), show_border=True, label='Advanced settings'), ), buttons=[ thisOKButton, thisPreviousButton, thisFindButton, thisApplyButton, ], handler=SpikesRemovalHandler, title='Spikes removal tool', resizable=False, ) return obj, {"view": view}
class ConjointCalcState(_traits.HasTraits): messages = _traits.Str() is_done = _traits.Bool(True) traits_view = _traitsui.View( _traitsui.Item('messages', show_label=False, springy=True, style='custom'), title='Conjoint calculation status', height=300, width=600, resizable=True, buttons=[ # _traitsui.Action(name='Cancel', action='_on_close', enabled_when='not is_done'), _traitsui.Action(name='OK', action='_on_close', enabled_when='is_done') ], ) def _messages_changed(self, new): self.messages = '\n'.join( [line for line in new.split('\n') if not line.startswith('try')]) def _is_done_changed(self, new): pass
class newDarkPictureDialog(traits.HasTraits): # pathSourceImages = traits.Directory( os.path.join("\\\\192.168.16.71","Humphry","Data","eagleLogs") ) pathSourceImages = traits.Directory( eagleLogsFolder ) pathNewDarkPicture = traits.File( defaultDarkPictureFilename, editor = traitsui.FileEditor(dialog_style='save') ) cancelButton = traitsui.Action(name = 'Cancel', action = '_cancel') okButton = traitsui.Action(name = 'Calculate dark picture', action = '_ok') date = traits.String( time.strftime('%Y %m %d'), desc='Date' ) camera = traits.String( "Andor1" ) interval = traits.Float(0.003) filterCountLi = traits.Int(1) temperature = traits.Float(-40.0) autoFilename = traits.Button('Auto Filename') traits_view = traitsui.View( traitsui.Group( traitsui.Item('pathSourceImages'), traitsui.Group( traitsui.Item('date'), traitsui.Item('camera'), traitsui.Item('interval'), traitsui.Item('temperature'), traitsui.Item('autoFilename'), label='Auto Filename', show_border=True ), traitsui.Item('pathNewDarkPicture') ), buttons = [cancelButton, okButton], handler = newDarkPictureDialogHandler() ) def _autoFilename_fired(self): filename = self.date + ' - dark ' + self.camera + ' - ' filename += 'interval {} '.format(self.interval) filename += 'temperature {} '.format(self.temperature) filename = filename.replace('.','_') # filename += '.gz' filename += '.npy' path = os.path.join( defaultDarkPictureFilename, self.camera) if not os.path.exists( path ): os.mkdir( path ) self.pathNewDarkPicture = os.path.join( path, filename )
class Conf(trapi.HasTraits): N = trapi.Int(100, label='N') m = trapi.Int(5, label='m') goA = trui.Action(name='Generate Model A', action='compModelA') goBA = trui.Action(name='Generate Model B-A', action='compModelBA') comp = trui.Action(name='Compare approximations', action='compApprox') ex = trui.Action(name='Do exercise', action='doExercise') scale = trapi.Enum('Linear', 'Log-log') view = trui.View('N', 'm', 'scale', buttons=[goA, goBA, comp, ex]) def getScale(self): if self.scale == 'Log-log': return 'log' else: return 'linear' def doExercise(self, info): plotExercise() plt.show() exit() def compModelA(self, info): plotNmA(self.N, self.m, self.getScale()) plt.show() exit() def compModelBA(self, info): plotNmBA(self.N, self.m, self.getScale()) plt.show() exit() def compApprox(self, info): plotCompare(self.N, self.m, self.getScale()) plt.show() exit() def display(self): self.configure_traits()
class SpikesRemoval(SpanSelectorInSignal1D): interpolator_kind = t.Enum( 'Linear', 'Spline', default='Linear', desc="the type of interpolation to use when\n" "replacing the signal where a spike has been replaced") threshold = t.Float(desc="the derivative magnitude threshold above\n" "which to find spikes") click_to_show_instructions = t.Button() show_derivative_histogram = t.Button() spline_order = t.Range(1, 10, 3, desc="the order of the spline used to\n" "connect the reconstructed data") interpolator = None default_spike_width = t.Int( 5, desc="the width over which to do the interpolation\n" "when removing a spike (this can be " "adjusted for each\nspike by clicking " "and dragging on the display during\n" "spike replacement)") index = t.Int(0) add_noise = t.Bool(True, desc="whether to add noise to the interpolated\nportion" "of the spectrum. The noise properties defined\n" "in the Signal metadata are used if present," "otherwise\nshot noise is used as a default") thisOKButton = tu.Action(name="OK", action="OK", tooltip="Close the spikes removal tool") thisApplyButton = tu.Action(name="Remove spike", action="apply", tooltip="Remove the current spike by " "interpolating\n" "with the specified settings (and find\n" "the next spike automatically)") thisFindButton = tu.Action( name="Find next", action="find", tooltip="Find the next (in terms of navigation\n" "dimensions) spike in the data.") thisPreviousButton = tu.Action(name="Find previous", action="back", tooltip="Find the previous (in terms of " "navigation\n" "dimensions) spike in the data.") view = tu.View( tu.Group( tu.Group( tu.Item( 'click_to_show_instructions', show_label=False, ), tu.Item('show_derivative_histogram', show_label=False, tooltip="To determine the appropriate threshold,\n" "plot the derivative magnitude histogram, \n" "and look for outliers at high magnitudes \n" "(which represent sudden spikes in the data)"), 'threshold', show_border=True, ), tu.Group('add_noise', 'interpolator_kind', 'default_spike_width', tu.Group('spline_order', enabled_when='interpolator_kind == \'Spline\''), show_border=True, label='Advanced settings'), ), buttons=[ thisOKButton, thisPreviousButton, thisFindButton, thisApplyButton, ], handler=SpikesRemovalHandler, title='Spikes removal tool', resizable=False, ) def __init__(self, signal, navigation_mask=None, signal_mask=None): super(SpikesRemoval, self).__init__(signal) self.interpolated_line = None self.coordinates = [ coordinate for coordinate in signal.axes_manager._am_indices_generator() if (navigation_mask is None or not navigation_mask[coordinate[::-1]]) ] self.signal = signal self.line = signal._plot.signal_plot.ax_lines[0] self.ax = signal._plot.signal_plot.ax signal._plot.auto_update_plot = False if len(self.coordinates) > 1: signal.axes_manager.indices = self.coordinates[0] self.threshold = 400 self.index = 0 self.argmax = None self.derivmax = None self.kind = "linear" self._temp_mask = np.zeros(self.signal().shape, dtype='bool') self.signal_mask = signal_mask self.navigation_mask = navigation_mask md = self.signal.metadata from hyperspy.signal import BaseSignal if "Signal.Noise_properties" in md: if "Signal.Noise_properties.variance" in md: self.noise_variance = md.Signal.Noise_properties.variance if isinstance(md.Signal.Noise_properties.variance, BaseSignal): self.noise_type = "heteroscedastic" else: self.noise_type = "white" else: self.noise_type = "shot noise" else: self.noise_type = "shot noise" def _threshold_changed(self, old, new): self.index = 0 self.update_plot() def _click_to_show_instructions_fired(self): m = information(None, "\nTo remove spikes from the data:\n\n" " 1. Click \"Show derivative histogram\" to " "determine at what magnitude the spikes are present.\n" " 2. Enter a suitable threshold (lower than the " "lowest magnitude outlier in the histogram) in the " "\"Threshold\" box, which will be the magnitude " "from which to search. \n" " 3. Click \"Find next\" to find the first spike.\n" " 4. If desired, the width and position of the " "boundaries used to replace the spike can be " "adjusted by clicking and dragging on the displayed " "plot.\n " " 5. View the spike (and the replacement data that " "will be added) and click \"Remove spike\" in order " "to alter the data as shown. The tool will " "automatically find the next spike to replace.\n" " 6. Repeat this process for each spike throughout " "the dataset, until the end of the dataset is " "reached.\n" " 7. Click \"OK\" when finished to close the spikes " "removal tool.\n\n" "Note: Various settings can be configured in " "the \"Advanced settings\" section. Hover the " "mouse over each parameter for a description of what " "it does." "\n", title="Instructions"), def _show_derivative_histogram_fired(self): self.signal._spikes_diagnosis(signal_mask=self.signal_mask, navigation_mask=self.navigation_mask) def detect_spike(self): derivative = np.diff(self.signal()) if self.signal_mask is not None: derivative[self.signal_mask[:-1]] = 0 if self.argmax is not None: left, right = self.get_interpolation_range() self._temp_mask[left:right] = True derivative[self._temp_mask[:-1]] = 0 if abs(derivative.max()) >= self.threshold: self.argmax = derivative.argmax() self.derivmax = abs(derivative.max()) return True else: return False def _reset_line(self): if self.interpolated_line is not None: self.interpolated_line.close() self.interpolated_line = None self.reset_span_selector() def find(self, back=False): self._reset_line() ncoordinates = len(self.coordinates) spike = self.detect_spike() while not spike and ((self.index < ncoordinates - 1 and back is False) or (self.index > 0 and back is True)): if back is False: self.index += 1 else: self.index -= 1 spike = self.detect_spike() if spike is False: messages.information('End of dataset reached') self.index = 0 self._reset_line() return else: minimum = max(0, self.argmax - 50) maximum = min(len(self.signal()) - 1, self.argmax + 50) thresh_label = DerivativeTextParameters( text="$\mathsf{\delta}_\mathsf{max}=$", color="black") self.ax.legend([thresh_label], [repr(int(self.derivmax))], handler_map={ DerivativeTextParameters: DerivativeTextHandler() }, loc='best') self.ax.set_xlim( self.signal.axes_manager.signal_axes[0].index2value(minimum), self.signal.axes_manager.signal_axes[0].index2value(maximum)) self.update_plot() self.create_interpolation_line() def update_plot(self): if self.interpolated_line is not None: self.interpolated_line.close() self.interpolated_line = None self.reset_span_selector() self.update_spectrum_line() if len(self.coordinates) > 1: self.signal._plot.pointer._update_patch_position() def update_spectrum_line(self): self.line.auto_update = True self.line.update() self.line.auto_update = False def _index_changed(self, old, new): self.signal.axes_manager.indices = self.coordinates[new] self.argmax = None self._temp_mask[:] = False def on_disabling_span_selector(self): if self.interpolated_line is not None: self.interpolated_line.close() self.interpolated_line = None def _spline_order_changed(self, old, new): self.kind = self.spline_order self.span_selector_changed() def _add_noise_changed(self, old, new): self.span_selector_changed() def _interpolator_kind_changed(self, old, new): if new == 'linear': self.kind = new else: self.kind = self.spline_order self.span_selector_changed() def _ss_left_value_changed(self, old, new): if not (np.isnan(self.ss_right_value) or np.isnan(self.ss_left_value)): self.span_selector_changed() def _ss_right_value_changed(self, old, new): if not (np.isnan(self.ss_right_value) or np.isnan(self.ss_left_value)): self.span_selector_changed() def create_interpolation_line(self): self.interpolated_line = drawing.signal1d.Signal1DLine() self.interpolated_line.data_function = self.get_interpolated_spectrum self.interpolated_line.set_line_properties(color='blue', type='line') self.signal._plot.signal_plot.add_line(self.interpolated_line) self.interpolated_line.autoscale = False self.interpolated_line.plot() def get_interpolation_range(self): axis = self.signal.axes_manager.signal_axes[0] if np.isnan(self.ss_left_value) or np.isnan(self.ss_right_value): left = self.argmax - self.default_spike_width right = self.argmax + self.default_spike_width else: left = axis.value2index(self.ss_left_value) right = axis.value2index(self.ss_right_value) # Clip to the axis dimensions nchannels = self.signal.axes_manager.signal_shape[0] left = left if left >= 0 else 0 right = right if right < nchannels else nchannels - 1 return left, right def get_interpolated_spectrum(self, axes_manager=None): data = self.signal().copy() axis = self.signal.axes_manager.signal_axes[0] left, right = self.get_interpolation_range() if self.kind == 'linear': pad = 1 else: pad = 10 ileft = left - pad iright = right + pad ileft = np.clip(ileft, 0, len(data)) iright = np.clip(iright, 0, len(data)) left = int(np.clip(left, 0, len(data))) right = int(np.clip(right, 0, len(data))) x = np.hstack((axis.axis[ileft:left], axis.axis[right:iright])) y = np.hstack((data[ileft:left], data[right:iright])) if ileft == 0: # Extrapolate to the left data[left:right] = data[right + 1] elif iright == (len(data) - 1): # Extrapolate to the right data[left:right] = data[left - 1] else: # Interpolate intp = sp.interpolate.interp1d(x, y, kind=self.kind) data[left:right] = intp(axis.axis[left:right]) # Add noise if self.add_noise is True: if self.noise_type == "white": data[left:right] += np.random.normal(scale=np.sqrt( self.noise_variance), size=right - left) elif self.noise_type == "heteroscedastic": noise_variance = self.noise_variance( axes_manager=self.signal.axes_manager)[left:right] noise = [ np.random.normal(scale=np.sqrt(item)) for item in noise_variance ] data[left:right] += noise else: data[left:right] = np.random.poisson( np.clip(data[left:right], 0, np.inf)) return data def span_selector_changed(self): if self.interpolated_line is None: return else: self.interpolated_line.update() def apply(self): self.signal()[:] = self.get_interpolated_spectrum() self.signal.events.data_changed.trigger(obj=self.signal) self.update_spectrum_line() self.interpolated_line.close() self.interpolated_line = None self.reset_span_selector() self.find()
import traitsui.api as tu OurOKButton = tu.Action( name="OK", action="OK", ) OurApplyButton = tu.Action(name="Apply", action="apply") OurResetButton = tu.Action(name="Reset", action="reset") OurCloseButton = tu.Action(name="Close", action="close_directly") OurFindButton = tu.Action( name="Find next", action="find", ) OurPreviousButton = tu.Action( name="Find previous", action="back", ) OurFitButton = tu.Action(name="Fit", action="fit") StoreButton = tu.Action(name="Store", action="store") SaveButton = tu.Action(name="Save", action="save")
_traitsui.Item('controller.model.owner_ref.model_struct', style='simple', show_label=False), _traitsui.Item( 'controller.model_desc', editor=_traitsui.HTMLEditor(), # height=250, # width=400, resizable=True, show_label=False), title='Conjoint settings', ) ds_exp_action = _traitsui.Action( name='Copy to Data set', visible_when= 'object.node_name in ("Fixed residuals", "Full model residuals")', action='handler.export_data(editor, object)', ) conjoint_nodes = [ _traitsui.TreeNode(node_for=[ConjointController], label='name', children='', view=conjoint_view, menu=[]), _traitsui.TreeNode(node_for=[ConjointController], label='=Analysis results', children='table_win_launchers', auto_open=True, view=conjoint_view, menu=[]),
def find_peaks2D_traitsui(obj, **kwargs): ComputeButton = tu.Action(name="Compute over navigation axes", action="compute_navigation", tooltip="Find the peaks by iterating over \n" "the navigation axes.") axis_group, context = get_navigation_sliders_group( obj.signal.axes_manager.navigation_axes) view = tu.View( tu.Group( tu.Group(axis_group, tu.Item( 'obj.random_navigation_position', show_label=False, name='Set navigation index randomly', tooltip='Set the navigation index to a random \n' 'value.', ), visible_when='show_navigation_sliders==True', label='Navigator', show_border=True), tu.Item('obj.method', show_label=True), tu.Group(tu.Item('obj.local_max_distance', label='Distance'), tu.Item('obj.local_max_threshold', label='Threshold'), visible_when='obj.method == "Local max"', label='Method parameters', show_border=True), tu.Group(tu.Item('obj.max_alpha', label='Alpha'), tu.Item('obj.max_distance', label='Distance'), visible_when='obj.method == "Max"', label='Method parameters', show_border=True), tu.Group(tu.Item('obj.minmax_distance', label='Distance'), tu.Item('obj.minmax_threshold', label='Threshold'), visible_when='obj.method == "Minmax"', label='Method parameters', show_border=True), tu.Group(tu.Item('obj.zaefferer_grad_threshold', label='Grad threshold'), tu.Item('obj.zaefferer_window_size', label='Window size'), tu.Item('obj.zaefferer_distance_cutoff', label='Distance cutoff'), visible_when='obj.method == "Zaefferer"', label='Method parameters', show_border=True), tu.Group(tu.Item('obj.stat_alpha', label='Alpha'), tu.Item('obj.stat_window_radius', label='Window radius'), tu.Item('obj.stat_convergence_ratio', label='Convergence ratio'), visible_when='obj.method == "Stat"', label='Method parameters', show_border=True), tu.Group(tu.Item('obj.log_min_sigma', label='Min sigma'), tu.Item('obj.log_max_sigma', label='Max sigma'), tu.Item('obj.log_num_sigma', label='Num sigma'), tu.Item('obj.log_threshold', label='Threshold'), tu.Item('obj.log_overlap', label='Overlap'), tu.Item('obj.log_log_scale', label='Log scale'), visible_when="obj.method == 'Laplacian of Gaussian'", label='Method parameters', show_border=True), tu.Group(tu.Item('obj.dog_min_sigma', label='Min sigma'), tu.Item('obj.dog_max_sigma', label='Max sigma'), tu.Item('obj.dog_sigma_ratio', label='Sigma ratio'), tu.Item('obj.dog_threshold', label='Threshold'), tu.Item('obj.dog_overlap', label='Overlap'), visible_when="obj.method == 'Difference of Gaussian'", label='Method parameters', show_border=True), tu.Group(tu.Item('obj.xc_distance', label='Distance'), tu.Item('obj.xc_threshold', label='Threshold'), visible_when="obj.method == 'Template matching'", label='Method parameters', show_border=True), show_border=True), buttons=[ComputeButton, CancelButton], handler=FindPeaks2DHandler, title='Find Peaks 2D', resizable=True, width=500, ) context.update({"obj": obj}) return obj, {"view": view, "context": context}
self.summary += "{k1:6s}:{v1:4.3g}\t{k2:6s}:{v2:4.3g}\n".format( k1='Missing', v1=nans, k2='Total', v2=vals) self.summary += "{k1:6s}:{v1:4.3g}\t{k2:6s}:{v2:4.3g}\n".format( k1='Min', v1=vmin, k2='Max', v2=vmax) self.summary += "{k1:6s}:{v1:4.3g}\t{k2:6s}:{v2:4.3g}\n".format( k1='Mean', v1=vmean, k2='STD', v2=vstd) if len(info.object.subs) > 0: self.summary += "Row coloring classes: {}\n".format(", ".join( info.object.subs.keys())) if len(info.object.rsubs) > 0: self.summary += "Column coloring classes: {}\n".format(", ".join( info.object.rsubs.keys())) transpose_action = _traitsui.Action( name='Create transposed copy', action='handler.transpose_ds(editor, object)') tr_menu = _traitsui.Menu(transpose_action, _te.DeleteAction) ds_view = _traitsui.View( _traitsui.Group( _traitsui.Group( _traitsui.Item('id', style='readonly'), _traitsui.Label('Data set name:'), _traitsui.Item('display_name', show_label=False), _traitsui.Label('Data set type:'), _traitsui.Item('kind', show_label=False), ), _traitsui.Group( _traitsui.Item('handler.summary',
class LogFilePlots(traits.HasTraits): """just a several tabbed view of several log file plot objects""" lfps = traits.List( plotObjects.logFilePlot.LogFilePlot) #list of possible fits selectedLFP = traits.Instance(plotObjects.logFilePlot.LogFilePlot) #logFilePlotGroup = traitsui.Group(traitsui.Item("logFilePlotObject", editor = traitsui.InstanceEditor(), style="custom", show_label=False),label="Log File Plotter") logFilePlotsGroup = traitsui.Group(traitsui.Item( 'lfps', style="custom", editor=traitsui.ListEditor(use_notebook=True, deletable=True, selected="selectedLFP", export='DockWindowShell', page_name=".logFilePlotsTabName"), label="logFilePlots", show_label=False), springy=True) autoRefreshTimer = traits.Instance(Timer) autoRefreshDialog = traits.Instance( plotObjects.autoRefreshDialog.AutoRefreshDialog) #for saving and loading default_directory = os.path.join('N:', os.sep, 'Data', 'eagleLogs') file_wildcard = traits.String("CSV Master Settings (*.csv)|All files|*") menubar = traitsmenu.MenuBar( traitsmenu.Menu(traitsui.Action(name='Add Log File Plot', action='_add_lfp'), traitsui.Action(name='Clone selected', action='_add_with_current_lfp'), traitsui.Action(name='Print current', action='_print_current'), traitsui.Action(name='Auto refresh', action='_autoRefresh_dialog'), traitsui.Action(name='Matplotlibify', action='_matplotlibify_dialog'), traitsui.Action(name='Save as', action='_save_as_settings'), traitsui.Action(name='Load as', action='_open_settings'), name="Menu"), ) statusBarString = traits.String() traits_view = traitsui.View(logFilePlotsGroup, title="Log File Plots", statusbar="statusBarString", icon=pyface.image_resource.ImageResource( os.path.join('icons', 'eagles.ico')), resizable=True, menubar=menubar) def __init__(self, N, **traitsDict): """N is initial number of logFilePlots """ super(traits.HasTraits, self).__init__(**traitsDict) self.lfps = [ plotObjects.logFilePlot.LogFilePlot() for c in range(0, N) ] self.selectedLFP = self.lfps[0] for lfp, counter in zip(self.lfps, range(0, N)): lfp.logFilePlotsBool = True lfp.logFilePlotsTabName = "log file plot " + str(counter) lfp.logFilePlotsReference = self def _add_lfp(self): """called from menu. adds a new logfileplot to list and hence to gui in case you run out """ new = plotObjects.logFilePlot.LogFilePlot() new.logFilePlotsBool = True new.logFilePlotsReference = self self.lfps.append(new) def _add_with_current_lfp(self): """called from menu. adds a new logfileplot to list and hence to gui in case you run out """ cloneTraits = [ "logFile", "mode", "masterList", "xAxis", "yAxis", "aggregateAxis", "series", "xLogScale", "yLogScale", "interpretAsTimeAxis", "filterYs", "filterMinYs", "filterMaxYs", "filterXs", "filterMinXs", "filterMaxXs", "filterNaN", "logFilePlotsBool" ] new = self.selectedLFP.clone_traits(traits=cloneTraits, copy="deep") new.logFilePlotsReference = self new.__init__() self.lfps.append(new) def _print_current(self): """opens matplotlibify that allows user to save to one note or print the image """ self.selectedLFP._savePlotButton_fired() def _autoRefresh_dialog(self): """when user clicks autorefresh in the menu this function calls the dialog after user hits ok, it makes the choices of how to setup or stop the timer""" logger.info("auto refresh dialog called") if self.autoRefreshDialog is None: self.autoRefreshDialog = plotObjects.autoRefreshDialog.AutoRefreshDialog( ) self.autoRefreshDialog.configure_traits() logger.info("dialog edit traits finished") if self.autoRefreshDialog.autoRefreshBool: if self.autoRefreshTimer is not None: self.autoRefreshTimer.stop() self.selectedLFP.autoRefreshObject = self.autoRefreshDialog #this gives it all the info it needs self.autoRefreshTimer = Timer( self.autoRefreshDialog.minutes * 60.0 * 1000.0, self.selectedLFP.autoRefresh) logger.info("started auto refresh timer to autorefresh") else: self.selectedLFP.autoRefreshObject = None logger.info("stopping auto refresh") if self.autoRefreshTimer is not None: self.autoRefreshTimer.stop() def _matplotlibify_dialog(self): import matplotlibify.matplotlibify dialog = matplotlibify.matplotlibify.Matplotlibify( logFilePlotReference=self.selectedLFP, logFilePlotsReference=self) dialog.configure_traits() def _save_settings(self, settingsFile): logger.debug("_save_settings call saving settings") with open(settingsFile, 'wb') as sfile: writer = csv.writer(sfile) writer.writerow([-1, 'N', len(self.lfps)]) c = 0 lfp_traits = [ 'mode', 'logFilePlotBool', 'fitLogFileBool', 'autoFitWithRefresh', 'softRefresh', 'errorBarMode', 'logFile', 'xAxis', 'yAxis', 'aggregateAxis', 'masterList', 'series', 'xLogScale', 'yLogScale', 'interpretAsTimeAxis', 'filterYs', 'filterMinYs', 'filterMaxYs', 'filterXs', 'filterMinXs', 'filterMaxXs', 'filterNaN', 'filterSpecific', 'filterSpecificString', 'filterVariableSelector', 'logFilePlotsBool', 'logFilePlotsTabName' ] for lfp in self.lfps: for trait in lfp_traits: try: writer.writerow([ c, trait, getattr(lfp, trait), type(getattr(lfp, trait)) ]) except Exception as e: logger.error(e.message) c += 1 def _load_settings(self, settingsFile): load_df = pandas.read_csv( settingsFile, na_filter=False, header=None, names=['lfp_idx', 'variable', 'value', 'type']) global_settings_df = load_df[load_df['lfp_idx'] == -1] N = int( global_settings_df[global_settings_df['variable'] == 'N'].value[0]) self.__init__(N) for idx in range(0, N): df = load_df[load_df['lfp_idx'] == idx] traits = list(df.variable.values) values = list(df.value.values) types = list(df.type.values) traitsDict = { trait: (value, type_val) for (trait, value, type_val) in zip(traits, values, types) } logger.info("loading lfp %G" % idx) logger.info("dictionary %s" % traitsDict) self.lfps[idx].load_settings(traitsDict) def _save_as_settings(self): """Called when user presses save as in Menu bar """ dialog = FileDialog(action="save as", default_directory=self.default_directory, wildcard=self.file_wildcard) dialog.open() if dialog.return_code == OK: self.settingsFile = dialog.path if self.settingsFile[-4:] != ".csv": self.settingsFile += ".csv" self._save_settings(self.settingsFile) def _open_settings(self): logger.debug("_open_settings call . Opening a settings file") dialog = FileDialog(action="open", default_directory=self.default_directory, wildcard=self.file_wildcard) dialog.open() if dialog.return_code == OK: self.settingsFile = dialog.path self._load_settings(self.settingsFile)
show_border=True, ), _traitsui.Group( _traitsui.Group( _traitsui.Item('num_segments', style='readonly', label="Number of consumer segments"), ), _traitsui.Item('ev_export_segments', show_label=False), _traitsui.Item('ev_remove_segments', show_label=False), label='Consumer Segments', ), ) ds_dum_attr_action = _traitsui.Action( # FIXME: Remove this name='Export dummified attributes', # visible_when='object.node_name in ("Fixed residuals", "Full model residuals")', action='handler.export_dum_attr(editor, object)', ) ds_dum_seg_action = _traitsui.Action( # FIXME: Remove this name='Export dummified segments', # visible_when='object.node_name in ("Fixed residuals", "Full model residuals")', action='handler.export_dum_segments(editor, object)', ) ind_diff_nodes = [ _traitsui.TreeNode(node_for=[IndDiffController], label='name', children='', view=no_view,
import numpy as np import scipy as sp import matplotlib.pyplot as plt import traits.api as t import traitsui.api as tu from traitsui.menu import (OKButton, CancelButton, OKCancelButtons) from hyperspy import drawing from hyperspy.exceptions import SignalDimensionError from hyperspy.gui import messages from hyperspy.axes import AxesManager from hyperspy.drawing.widgets import DraggableVerticalLine OurApplyButton = tu.Action(name="Apply", action="apply") OurResetButton = tu.Action(name="Reset", action="reset") OurFindButton = tu.Action(name="Find", action="find") OurPreviousButton = tu.Action(name="Previous", action="back") class SmoothingHandler(tu.Handler): def close(self, info, is_ok): # Removes the span selector from the plot
class ImagePlotInspector(traits.HasTraits): #Traits view definitions: settingsGroup = traitsui.VGroup( traitsui.VGroup( traitsui.Item("watchFolderBool", label="Watch Folder?"), traitsui.HGroup(traitsui.Item("selectedFile", label="Select a File"), visible_when="not watchFolderBool"), traitsui.HGroup(traitsui.Item("watchFolder", label="Select a Directory"), visible_when="watchFolderBool"), traitsui.HGroup(traitsui.Item("searchString", label="Filename sub-string"), visible_when="watchFolderBool"), label="File Settings", show_border=True), traitsui.VGroup(traitsui.HGroup('autoRangeColor', 'colorMapRangeLow', 'colorMapRangeHigh'), traitsui.HGroup('horizontalAutoRange', 'horizontalLowerLimit', 'horizontalUpperLimit'), traitsui.HGroup('verticalAutoRange', 'verticalLowerLimit', 'verticalUpperLimit'), label="axis limits", show_border=True), traitsui.VGroup(traitsui.HGroup('object.model.scale', 'object.model.offset'), traitsui.HGroup( traitsui.Item('object.model.pixelsX', label="Pixels X"), traitsui.Item('object.model.pixelsY', label="Pixels Y")), traitsui.HGroup( traitsui.Item('object.model.ODCorrectionBool', label="Correct OD?"), traitsui.Item('object.model.ODSaturationValue', label="OD saturation value")), traitsui.HGroup( traitsui.Item('contourLevels', label="Contour Levels"), traitsui.Item('colormap', label="Colour Map")), traitsui.HGroup( traitsui.Item('fixAspectRatioBool', label="Fix Plot Aspect Ratio?")), traitsui.HGroup( traitsui.Item('updatePhysicsBool', label="Update Physics with XML?")), traitsui.HGroup( traitsui.Item("cameraModel", label="Update Camera Settings to:")), label="advanced", show_border=True), label="settings") plotGroup = traitsui.Group( traitsui.Item('container', editor=ComponentEditor(size=(800, 600)), show_label=False)) fitsGroup = traitsui.Group(traitsui.Item('fitList', style="custom", editor=traitsui.ListEditor( use_notebook=True, selected="selectedFit", deletable=False, export='DockWindowShell', page_name=".name"), label="Fits", show_label=False), springy=True) mainPlotGroup = traitsui.HSplit(plotGroup, fitsGroup, label="Image") fftGroup = traitsui.Group(label="Fourier Transform") physicsGroup = traitsui.Group(traitsui.Item( "physics", editor=traitsui.InstanceEditor(), style="custom", show_label=False), label="Physics") logFilePlotGroup = traitsui.Group(traitsui.Item( "logFilePlotObject", editor=traitsui.InstanceEditor(), style="custom", show_label=False), label="Log File Plotter") eagleMenubar = traitsmenu.MenuBar( traitsmenu.Menu( traitsui.Action(name='Save Image Copy As...', action='_save_image_as'), traitsui.Action(name='Save Image Copy', action='_save_image_default'), name="File", )) traits_view = traitsui.View(settingsGroup, mainPlotGroup, physicsGroup, logFilePlotGroup, buttons=traitsmenu.NoButtons, menubar=eagleMenubar, handler=EagleHandler, title="Experiment Eagle", statusbar="selectedFile", icon=pyface.image_resource.ImageResource( os.path.join('icons', 'eagles.ico')), resizable=True) model = CameraImage() physics = physicsProperties.physicsProperties.PhysicsProperties( ) #create a physics properties object logFilePlotObject = logFilePlot.LogFilePlot() fitList = model.fitList selectedFit = traits.Instance(fits.Fit) drawFitRequest = traits.Event drawFitBool = traits.Bool(False) # true when drawing a fit as well selectedFile = traits.File() watchFolderBool = traits.Bool(False) watchFolder = traits.Directory() searchString = traits.String( desc= "sub string that must be contained in file name for it to be shown in Eagle. Can be used to allow different instances of Eagle to detect different saved images." ) oldFiles = set() contourLevels = traits.Int(15) colormap = traits.Enum(colormaps.color_map_name_dict.keys()) autoRangeColor = traits.Bool(True) colorMapRangeLow = traits.Float colorMapRangeHigh = traits.Float horizontalAutoRange = traits.Bool(True) horizontalLowerLimit = traits.Float horizontalUpperLimit = traits.Float verticalAutoRange = traits.Bool(True) verticalLowerLimit = traits.Float verticalUpperLimit = traits.Float fixAspectRatioBool = traits.Bool(False) updatePhysicsBool = traits.Bool(True) cameraModel = traits.Enum("Custom", "ALTA0", "ANDOR0", "ALTA1", "ANDOR1") #--------------------------------------------------------------------------- # Private Traits #--------------------------------------------------------------------------- _image_index = traits.Instance(chaco.GridDataSource) _image_value = traits.Instance(chaco.ImageData) _cmap = traits.Trait(colormaps.jet, traits.Callable) #--------------------------------------------------------------------------- # Public View interface #--------------------------------------------------------------------------- def __init__(self, *args, **kwargs): super(ImagePlotInspector, self).__init__(*args, **kwargs) #self.update(self.model) self.create_plot() for fit in self.fitList: fit.imageInspectorReference = self fit.physics = self.physics self.selectedFit = self.fitList[0] self.logFilePlotObject.physicsReference = self.physics #self._selectedFile_changed() logger.info("initialisation of experiment Eagle complete") def create_plot(self): # Create the mapper, etc self._image_index = chaco.GridDataSource(scipy.array([]), scipy.array([]), sort_order=("ascending", "ascending")) image_index_range = chaco.DataRange2D(self._image_index) self._image_index.on_trait_change(self._metadata_changed, "metadata_changed") self._image_value = chaco.ImageData(data=scipy.array([]), value_depth=1) image_value_range = chaco.DataRange1D(self._image_value) # Create the contour plots #self.polyplot = ContourPolyPlot(index=self._image_index, self.polyplot = chaco.CMapImagePlot( index=self._image_index, value=self._image_value, index_mapper=chaco.GridMapper(range=image_index_range), color_mapper=self._cmap(image_value_range)) # Add a left axis to the plot left = chaco.PlotAxis(orientation='left', title="y", mapper=self.polyplot.index_mapper._ymapper, component=self.polyplot) self.polyplot.overlays.append(left) # Add a bottom axis to the plot bottom = chaco.PlotAxis(orientation='bottom', title="x", mapper=self.polyplot.index_mapper._xmapper, component=self.polyplot) self.polyplot.overlays.append(bottom) # Add some tools to the plot self.polyplot.tools.append( tools.PanTool(self.polyplot, constrain_key="shift", drag_button="middle")) self.polyplot.overlays.append( tools.ZoomTool(component=self.polyplot, tool_mode="box", always_on=False)) self.lineInspectorX = clickableLineInspector.ClickableLineInspector( component=self.polyplot, axis='index_x', inspect_mode="indexed", write_metadata=True, is_listener=False, color="white") self.lineInspectorY = clickableLineInspector.ClickableLineInspector( component=self.polyplot, axis='index_y', inspect_mode="indexed", write_metadata=True, color="white", is_listener=False) self.polyplot.overlays.append(self.lineInspectorX) self.polyplot.overlays.append(self.lineInspectorY) self.boxSelection2D = boxSelection2D.BoxSelection2D( component=self.polyplot) self.polyplot.overlays.append(self.boxSelection2D) # Add these two plots to one container self.centralContainer = chaco.OverlayPlotContainer(padding=0, use_backbuffer=True, unified_draw=True) self.centralContainer.add(self.polyplot) # Create a colorbar cbar_index_mapper = chaco.LinearMapper(range=image_value_range) self.colorbar = chaco.ColorBar( index_mapper=cbar_index_mapper, plot=self.polyplot, padding_top=self.polyplot.padding_top, padding_bottom=self.polyplot.padding_bottom, padding_right=40, resizable='v', width=30) self.plotData = chaco.ArrayPlotData( line_indexHorizontal=scipy.array([]), line_valueHorizontal=scipy.array([]), scatter_indexHorizontal=scipy.array([]), scatter_valueHorizontal=scipy.array([]), scatter_colorHorizontal=scipy.array([]), fitLine_indexHorizontal=scipy.array([]), fitLine_valueHorizontal=scipy.array([])) self.crossPlotHorizontal = chaco.Plot(self.plotData, resizable="h") self.crossPlotHorizontal.height = 100 self.crossPlotHorizontal.padding = 20 self.crossPlotHorizontal.plot( ("line_indexHorizontal", "line_valueHorizontal"), line_style="dot") self.crossPlotHorizontal.plot( ("scatter_indexHorizontal", "scatter_valueHorizontal", "scatter_colorHorizontal"), type="cmap_scatter", name="dot", color_mapper=self._cmap(image_value_range), marker="circle", marker_size=4) self.crossPlotHorizontal.index_range = self.polyplot.index_range.x_range self.plotData.set_data("line_indexVertical", scipy.array([])) self.plotData.set_data("line_valueVertical", scipy.array([])) self.plotData.set_data("scatter_indexVertical", scipy.array([])) self.plotData.set_data("scatter_valueVertical", scipy.array([])) self.plotData.set_data("scatter_colorVertical", scipy.array([])) self.plotData.set_data("fitLine_indexVertical", scipy.array([])) self.plotData.set_data("fitLine_valueVertical", scipy.array([])) self.crossPlotVertical = chaco.Plot(self.plotData, width=140, orientation="v", resizable="v", padding=20, padding_bottom=160) self.crossPlotVertical.plot( ("line_indexVertical", "line_valueVertical"), line_style="dot") self.crossPlotVertical.plot( ("scatter_indexVertical", "scatter_valueVertical", "scatter_colorVertical"), type="cmap_scatter", name="dot", color_mapper=self._cmap(image_value_range), marker="circle", marker_size=4) self.crossPlotVertical.index_range = self.polyplot.index_range.y_range # Create a container and add components self.container = chaco.HPlotContainer(padding=40, fill_padding=True, bgcolor="white", use_backbuffer=False) inner_cont = chaco.VPlotContainer(padding=40, use_backbuffer=True) inner_cont.add(self.crossPlotHorizontal) inner_cont.add(self.centralContainer) self.container.add(self.colorbar) self.container.add(inner_cont) self.container.add(self.crossPlotVertical) def initialiseFitPlot(self): """called if this is the first Fit Plot to be drawn """ xstep = 1.0 ystep = 1.0 self.contourXS = scipy.linspace(xstep / 2., self.model.pixelsX - xstep / 2., self.model.pixelsX - 1) self.contourYS = scipy.linspace(ystep / 2., self.model.pixelsY - ystep / 2., self.model.pixelsY - 1) logger.debug("contour initialise fit debug. xs shape %s" % self.contourXS.shape) logger.debug("contour initialise xs= %s" % self.contourXS) self._fit_value = chaco.ImageData(data=scipy.array([]), value_depth=1) self.lineplot = chaco.ContourLinePlot( index=self._image_index, value=self._fit_value, index_mapper=chaco.GridMapper( range=self.polyplot.index_mapper.range), levels=self.contourLevels) self.centralContainer.add(self.lineplot) self.plotData.set_data("fitLine_indexHorizontal", self.model.xs) self.plotData.set_data("fitLine_indexVertical", self.model.ys) self.crossPlotVertical.plot( ("fitLine_indexVertical", "fitLine_valueVertical"), type="line", name="fitVertical") self.crossPlotHorizontal.plot( ("fitLine_indexHorizontal", "fitLine_valueHorizontal"), type="line", name="fitHorizontal") logger.debug("initialise fit plot %s " % self.crossPlotVertical.plots) def addFitPlot(self, fit): """add a contour plot on top using fitted data and add additional plots to sidebars (TODO) """ logger.debug("adding fit plot with fit %s " % fit) if not fit.fitted: logger.error( "cannot add a fitted plot for unfitted data. Run fit first") return if not self.drawFitBool: logger.info("first fit plot so initialising contour plot") self.initialiseFitPlot() logger.info("attempting to set fit data") self.contourPositions = [ scipy.tile(self.contourXS, len(self.contourYS)), scipy.repeat(self.contourYS, len(self.contourXS)) ] #for creating data necessary for gauss2D function zsravelled = fit.fitFunc(self.contourPositions, *fit._getCalculatedValues()) # logger.debug("zs ravelled shape %s " % zsravelled.shape) self.contourZS = zsravelled.reshape( (len(self.contourYS), len(self.contourXS))) # logger.debug("zs contour shape %s " % self.contourZS.shape) # logger.info("shape contour = %s " % self.contourZS) self._fit_value.data = self.contourZS self.container.invalidate_draw() self.container.request_redraw() self.drawFitBool = True def update(self, model): logger.info("updating plot") # if self.selectedFile=="": # logger.warning("selected file was empty. Will not attempt to update plot.") # return if self.autoRangeColor: self.colorbar.index_mapper.range.low = model.minZ self.colorbar.index_mapper.range.high = model.maxZ self._image_index.set_data(model.xs, model.ys) self._image_value.data = model.zs self.plotData.set_data("line_indexHorizontal", model.xs) self.plotData.set_data("line_indexVertical", model.ys) if self.drawFitBool: self.plotData.set_data("fitLine_indexHorizontal", self.contourXS) self.plotData.set_data("fitLine_indexVertical", self.contourYS) self.updatePlotLimits() self._image_index.metadata_changed = True self.container.invalidate_draw() self.container.request_redraw() #--------------------------------------------------------------------------- # Event handlers #--------------------------------------------------------------------------- def _metadata_changed(self, old, new): """ This function takes out a cross section from the image data, based on the line inspector selections, and updates the line and scatter plots.""" if self.horizontalAutoRange: self.crossPlotHorizontal.value_range.low = self.model.minZ self.crossPlotHorizontal.value_range.high = self.model.maxZ if self.verticalAutoRange: self.crossPlotVertical.value_range.low = self.model.minZ self.crossPlotVertical.value_range.high = self.model.maxZ if self._image_index.metadata.has_key("selections"): selections = self._image_index.metadata["selections"] if not selections: #selections is empty list return #don't need to do update lines as no mouse over screen. This happens at beginning of script x_ndx, y_ndx = selections if y_ndx and x_ndx: self.plotData.set_data("line_valueHorizontal", self._image_value.data[y_ndx, :]) self.plotData.set_data("line_valueVertical", self._image_value.data[:, x_ndx]) xdata, ydata = self._image_index.get_data() xdata, ydata = xdata.get_data(), ydata.get_data() self.plotData.set_data("scatter_indexHorizontal", scipy.array([xdata[x_ndx]])) self.plotData.set_data("scatter_indexVertical", scipy.array([ydata[y_ndx]])) self.plotData.set_data( "scatter_valueHorizontal", scipy.array([self._image_value.data[y_ndx, x_ndx]])) self.plotData.set_data( "scatter_valueVertical", scipy.array([self._image_value.data[y_ndx, x_ndx]])) self.plotData.set_data( "scatter_colorHorizontal", scipy.array([self._image_value.data[y_ndx, x_ndx]])) self.plotData.set_data( "scatter_colorVertical", scipy.array([self._image_value.data[y_ndx, x_ndx]])) if self.drawFitBool: self.plotData.set_data("fitLine_valueHorizontal", self._fit_value.data[y_ndx, :]) self.plotData.set_data("fitLine_valueVertical", self._fit_value.data[:, x_ndx]) else: self.plotData.set_data("scatter_valueHorizontal", scipy.array([])) self.plotData.set_data("scatter_valueVertical", scipy.array([])) self.plotData.set_data("line_valueHorizontal", scipy.array([])) self.plotData.set_data("line_valueVertical", scipy.array([])) self.plotData.set_data("fitLine_valueHorizontal", scipy.array([])) self.plotData.set_data("fitLine_valueVertical", scipy.array([])) def _colormap_changed(self): self._cmap = colormaps.color_map_name_dict[self.colormap] if hasattr(self, "polyplot"): value_range = self.polyplot.color_mapper.range self.polyplot.color_mapper = self._cmap(value_range) value_range = self.crossPlotHorizontal.color_mapper.range self.crossPlotHorizontal.color_mapper = self._cmap(value_range) # FIXME: change when we decide how best to update plots using # the shared colormap in plot object self.crossPlotHorizontal.plots["dot"][0].color_mapper = self._cmap( value_range) self.crossPlotVertical.plots["dot"][0].color_mapper = self._cmap( value_range) self.container.request_redraw() def _colorMapRangeLow_changed(self): self.colorbar.index_mapper.range.low = self.colorMapRangeLow def _colorMapRangeHigh_changed(self): self.colorbar.index_mapper.range.high = self.colorMapRangeHigh def _horizontalLowerLimit_changed(self): self.crossPlotHorizontal.value_range.low = self.horizontalLowerLimit def _horizontalUpperLimit_changed(self): self.crossPlotHorizontal.value_range.high = self.horizontalUpperLimit def _verticalLowerLimit_changed(self): self.crossPlotVertical.value_range.low = self.verticalLowerLimit def _verticalUpperLimit_changed(self): self.crossPlotVertical.value_range.high = self.verticalUpperLimit def _autoRange_changed(self): if self.autoRange: self.colorbar.index_mapper.range.low = self.minz self.colorbar.index_mapper.range.high = self.maxz def _num_levels_changed(self): if self.num_levels > 3: self.polyplot.levels = self.num_levels self.lineplot.levels = self.num_levels def _colorMapRangeLow_default(self): logger.debug("setting color map rangle low default") return self.model.minZ def _colorMapRangeHigh_default(self): return self.model.maxZ def _horizontalLowerLimit_default(self): return self.model.minZ def _horizontalUpperLimit_default(self): return self.model.maxZ def _verticalLowerLimit_default(self): return self.model.minZ def _verticalUpperLimit_default(self): return self.model.maxZ def _selectedFit_changed(self, selected): logger.debug("selected fit was changed") def _fixAspectRatioBool_changed(self): if self.fixAspectRatioBool: #using zoom range works but then when you reset zoom this function isn't called... # rangeObject = self.polyplot.index_mapper.range # xrangeValue = rangeObject.high[0]-rangeObject.low[0] # yrangeValue = rangeObject.high[1]-rangeObject.low[1] # logger.info("xrange = %s, yrange = %s " % (xrangeValue, yrangeValue)) # aspectRatioSquare = (xrangeValue)/(yrangeValue) # self.polyplot.aspect_ratio=aspectRatioSquare self.centralContainer.aspect_ratio = float( self.model.pixelsX) / float(self.model.pixelsY) #self.polyplot.aspect_ratio = self.model.pixelsX/self.model.pixelsY else: self.centralContainer.aspect_ratio = None #self.polyplot.aspect_ratio = None self.container.request_redraw() self.centralContainer.request_redraw() def updatePlotLimits(self): """just updates the values in the GUI """ if self.autoRangeColor: self.colorMapRangeLow = self.model.minZ self.colorMapRangeHigh = self.model.maxZ if self.horizontalAutoRange: self.horizontalLowerLimit = self.model.minZ self.horizontalUpperLimit = self.model.maxZ if self.verticalAutoRange: self.verticalLowerLimit = self.model.minZ self.verticalUpperLimit = self.model.maxZ def _selectedFile_changed(self): self.model.getImageData(self.selectedFile) if self.updatePhysicsBool: self.physics.updatePhysics() for fit in self.fitList: fit.fitted = False fit.fittingStatus = fit.notFittedForCurrentStatus if fit.autoFitBool: #we should automatically start fitting for this Fit fit._fit_routine( ) #starts a thread to perform the fit. auto guess and auto draw will be handled automatically self.update_view() #update log file plot if autorefresh is selected if self.logFilePlotObject.autoRefresh: try: self.logFilePlotObject.refreshPlot() except Exception as e: logger.error("failed to update log plot - %s...." % e.message) def _cameraModel_changed(self): """camera model enum can be used as a helper. It just sets all the relevant editable parameters to the correct values. e.g. pixels size, etc. cameras: "Andor Ixon 3838", "Apogee ALTA" """ logger.info("camera model changed") if self.cameraModel == "ANDOR0": self.model.pixelsX = 512 self.model.pixelsY = 512 self.physics.pixelSize = 16.0 self.physics.magnification = 2.0 self.searchString = "ANDOR0" elif self.cameraModel == "ALTA0": self.model.pixelsX = 768 self.model.pixelsY = 512 self.physics.pixelSize = 9.0 self.physics.magnification = 0.5 self.searchString = "ALTA0" elif self.cameraModel == "ALTA1": self.model.pixelsX = 768 self.model.pixelsY = 512 self.physics.pixelSize = 9.0 self.physics.magnification = 4.25 self.searchString = "ALTA1" elif self.cameraModel == "ANDOR1": self.model.pixelsX = 512 self.model.pixelsY = 512 self.physics.pixelSize = 16.0 self.physics.magnification = 2.0 self.searchString = "ANDOR1" else: logger.error("unrecognised camera model") self.refreshFitReferences() self.model.getImageData(self.selectedFile) def refreshFitReferences(self): """When aspects of the image change so that the fits need to have properties updated, it should be done by this function""" for fit in self.fitList: fit.endX = self.model.pixelsX fit.endY = self.model.pixelsY def _pixelsX_changed(self): """If pixelsX or pixelsY change, we must send the new arrays to the fit functions """ logger.info("pixels X Change detected") self.refreshFitReferences() self.update(self.model) self.model.getImageData(self.selectedFile) def _pixelsY_changed(self): """If pixelsX or pixelsY change, we must send the new arrays to the fit functions """ logger.info("pixels Y Change detected") self.refreshFitReferences() self.update(self.model) self.model.getImageData(self.selectedFile) @traits.on_trait_change('model') def update_view(self): if self.model is not None: self.update(self.model) def _save_image(self, originalFilePath, newFilePath): """given the original file path this saves a new copy to new File path """ shutil.copy2(originalFilePath, newFilePath) def _save_image_as(self): """ opens a save as dialog and allows user to save a copy of current image to a custom location with a custom name""" originalFilePath = str( self.selectedFile ) #so that this can't be affected by auto update after the dialog is open file_wildcard = str("PNG (*.png)|All files|*") default_directory = os.path.join("\\\\ursa", "AQOGroupFolder", "Experiment Humphry", "Data", "savedEagleImages") dialog = FileDialog(action="save as", default_directory=default_directory, wildcard=file_wildcard) dialog.open() if dialog.return_code == OK: self._save_image(originalFilePath, dialog.path) logger.debug("custom image copy made") def _save_image_default(self): head, tail = os.path.split(self.selectedFile) default_file = os.path.join("\\\\ursa", "AQOGroupFolder", "Experiment Humphry", "Data", "savedEagleImages", tail) self._save_image(self.selectedFile, default_file) logger.debug("default image copy made")
class ExperimentSnake(traits.HasTraits): """Main Experiment Snake GUI that sends arbitrary actions based on the experiment runner sequence and actions that have been set up.""" #mainLog = utilities.TextDisplay() mainLog = outputStream.OutputStream() statusString = traits.String("Press Start Snake to begin...") isRunning = traits.Bool(False) # true when the snake is running sequenceStarted = traits.Bool( False) # flashes true for ~1ms when sequence starts queue = traits.Int(0) variables = traits.Dict( key_trait=traits.Str, value_trait=traits.Float ) #dictionary mapping variable names in Exp control to their values in this sequence timingEdges = traits.Dict( key_trait=traits.Str, value_trait=traits.Float ) #dictionary mapping timing Edge names in Exp control to their values in this sequence statusList = [ ] #eventually will contain the information gathered from experiment Runner each time we poll startAction = traitsui.Action(name='start', action='_startSnake', image=pyface.image_resource.ImageResource( os.path.join('icons', 'start.png'))) stopAction = traitsui.Action(name='stop', action='_stopSnakeToolbar', image=pyface.image_resource.ImageResource( os.path.join('icons', 'stop.png'))) reloadHWAsAction = traitsui.Action( name='reload', action='_reloadHWAsToolbar', image=pyface.image_resource.ImageResource( os.path.join('icons', 'reload.png'))) connectionTimer = traits.Instance( Timer ) # polls the experiment runner and starts off callbacks at appropriate times statusStringTimer = traits.Instance( Timer) #updates status bar at regular times (less freque) getCurrentTimer = traits.Instance( Timer ) #waits for get current to return which marks the beginning of a sequence getCurrentThread = traits.Instance(SocketThread) connectionPollFrequency = traits.Float( 1000.0) #milliseconds defines accuracy you will perform callbacks at statusStringFrequency = traits.Float(2000.0) #milliseconds getCurrentFrequency = traits.Float( 1000.0) #milliseconds should be shorter than the sequence timeRunning = traits.Float(0.0) #how long the sequence has been running totalTime = traits.Float(0.0) # total length of sequence runnerHalted = traits.Bool(True) # true if runner is halted haltedCount = 0 progress = traits.Float(0.0) # % of cycle complete #progressBar = ProgressDialog() hardwareActions = traits.List(hardwareAction.hardwareAction.HardwareAction) examineVariablesDictionary = traits.Instance( variableDictionary.ExamineVariablesDictionary) xmlString = "" # STRING that will contain entire XML File menubar = traitsui.MenuBar( traitsui.Menu( traitsui.Action(name='Start Snake', action='_startSnake'), traitsui.Action(name='Stop Snake', action='_stopSnake'), traitsui.Action(name='Reload', action='_reloadHWAs'), traitsui.Menu(traitsui.Action(name='DEBUG', action='_changeLoggingLevelDebug'), traitsui.Action(name='INFO', action='_changeLoggingLevelInfo'), traitsui.Action(name='WARNING', action='_changeLoggingLevelWarning'), traitsui.Action(name='ERROR', action='_changeLoggingLevelError'), name="Log Level"), name='Menu')) toolbar = traitsui.ToolBar(startAction, stopAction, reloadHWAsAction) mainSnakeGroup = traitsui.VGroup( traitsui.Item('statusString', show_label=False, style='readonly'), traitsui.Item('mainLog', show_label=False, springy=True, style='custom', editor=traitsui.InstanceEditor())) hardwareActionsGroup = traitsui.Group(traitsui.Item( 'hardwareActions', show_label=False, style='custom', editor=traitsui.ListEditor(style="custom")), label="Hardware Actions", show_border=True) variableExaminerGroup = traitsui.Group(traitsui.Item( "examineVariablesDictionary", editor=traitsui.InstanceEditor(), style="custom", show_label=False), label="Variable Examiner") sidePanelGroup = traitsui.VSplit(hardwareActionsGroup, variableExaminerGroup) traits_view = traitsui.View(traitsui.HSplit(sidePanelGroup, mainSnakeGroup, show_labels=True), resizable=True, menubar=menubar, toolbar=toolbar, width=0.5, height=0.75, title="Experiment Snake", icon=pyface.image_resource.ImageResource( os.path.join('icons', 'snakeIcon.ico'))) def __init__(self, **traits): """ takes no arguments to construct the snake. Everything is done through GUI. Snake construction makes a ExperimentSnakeConnection object and writes to the main log window""" super(ExperimentSnake, self).__init__(**traits) self.connection = experimentRunnerConnection.Connection( ) #can override default ports and IP self.hardwareActions = [ hardwareAction.sequenceLoggerHWA.SequenceLogger( 0.0, snakeReference=self), hardwareAction.experimentTablesHWA.ExperimentTables( 0.0, snakeReference=self, enabled=False), hardwareAction.dlicEvapHWA.EvaporationRamp(1.0, snakeReference=self), #hardwareAction.dlicRFSweepHWA.DLICRFSweep(1.0, snakeReference = self,enabled=False), hardwareAction.dlicRFSweepLZHWA.DLICRFSweep(1.0, snakeReference=self, enabled=False), hardwareAction.dlicRFSweepLZWithPowerCtrlHWA.DLICRFSweep( 1.0, snakeReference=self, enabled=False), hardwareAction.dlicRFSweepLZWithPowerCtrl13PreparationHWA. DLICRFSweep(1.0, snakeReference=self, enabled=True), hardwareAction.dlicPiPulseHWA.DLICPiPulse(1.0, snakeReference=self, enabled=False), hardwareAction.evapAttenuationHWA.EvapAttenuation( 1.0, snakeReference=self), hardwareAction.greyMollassesOffsetFreqHWA.GreyMollassesOffset( 1.0, snakeReference=self, enabled=False), hardwareAction.evapAttenuation2HWA.EvapAttenuation( "EvapSnakeAttenuationTimeFinal", snakeReference=self, enabled=False), hardwareAction.picomotorPlugHWA.PicomotorPlug(1.0, snakeReference=self, enabled=False), hardwareAction.windFreakOffsetLockHWA.WindFreak( 0.0, snakeReference=self, enabled=False), hardwareAction.windFreakOffsetLockHighFieldImagingHWA.WindFreak( 0.0, snakeReference=self, enabled=True), hardwareAction.windFreakOffsetLock6ImagingHWA.WindFreak( 2.0, snakeReference=self, enabled=False), hardwareAction.windFreak6To1HWA.WindFreak(2.0, snakeReference=self, enabled=False), hardwareAction.windFreakOffsetLockLaser3.WindFreak( 3.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaZSFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaZSAtten( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaZSEOMFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaZSEOMAtten( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaSpecFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiImaging( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiImagingDetuning( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiPushPulseAttenuation( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiPushPulseDetuning( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaDarkSpotAOMFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaDarkSpotAOMAtten( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaMOTFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaMOTAtten( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaMOTEOMAtten( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaImagingDP( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiMOTRep( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiMOTCool( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelLiOpticalPump( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNa2to2OpticalPumpingFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNa2to2OpticalPumpingAtt( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaHighFieldImagingFreq( 1.0, snakeReference=self, enabled=False), hardwareAction.AOMChannelHWAs.AOMChannelNaHighFieldImagingAtt( 1.0, snakeReference=self, enabled=False), hardwareAction.digitalMultimeterCurrentMeasureHWA. DigitalMultimeterMeasurement(1.0, snakeReference=self, enabled=True), hardwareAction.MXGPiPulseHWA.PiPulse(1.0, snakeReference=self, enabled=False), hardwareAction.variableExplorerHWA.VariableExplorer( 2.0, snakeReference=self, enabled=False), hardwareAction.jds6600HWA.JDS6600HWA(1.0, snakeReference=self, enabled=False), hardwareAction.watchdogHWA.WatchdogHWA(18.0, snakeReference=self, enabled=True) ] introString = """Welcome to experiment snake.""" self.mainLog.addLine(introString, 1) def initialiseHardwareActions(self): for hdwAct in self.hardwareActions: if hdwAct.enabled: returnString = hdwAct.init() hdwAct.variablesReference = self.variables self.mainLog.addLine(returnString) def closeHardwareActions(self): """ this function is called when the user presses stop key. it should cleanly close or shutdown all hardware. user must appropriately implement the hardware action close function""" for hdwAct in self.hardwareActions: if hdwAct.initialised: returnString = hdwAct.close() self.mainLog.addLine(returnString) def _startSnake(self): """action call back from menu or toolbar. Simply starts the timer that polls the runner and makes the isRunning bool true """ self.mainLog.addLine("Experiment Snake Started", 1) self.isRunning = True self.getCurrentBlocking() self.initialiseHardwareActions() self.startTimers() def newSequenceStarted(self): """called by GetCurrent Thread at the beginning of every sequence """ if self.isRunning: #otherwise we have already stopped before new sequence began again self.getStatusUpdate() self.mainLog.addLine("New cycle started: %s" % self.statusList[0], 1) self.refreshExamineVariablesDictionary( ) # update the examine variables dictionary to reflect the latest values self.refreshVariableDependentCallbackTimes( ) # if a callback time is a timing edge name or variable name we must pull the value here else: self.mainLog.addLine("final connection closed") for hdwAct in self.hardwareActions: hdwAct.awaitingCallback = True def _stopSnakeToolbar(self): """if snake is stopped, addLine to main log and then run stopSnake """ self.mainLog.addLine( "Experiment Snake Stopped (you should still wait till the end of this sequence before continuing)", 1) self._stopSnake() def _reloadHWAsToolbar(self): """if snake is stopped, addLine to main log and then run stopSnake """ self.mainLog.addLine( "Experiment Snake Stopped (you should still wait till the end of this sequence before continuing)", 1) self._reloadHWAs() def _reloadHWAs(self): """if snake is stopped, addLine to main log and then run stopSnake """ self.mainLog.addLine("Reloading hardware actions (advanced feature)", 3) reload(hardwareAction.hardwareAction) reload(hardwareAction.sequenceLoggerHWA) reload(hardwareAction.dlicEvapHWA) reload(hardwareAction.dlicRFSweepHWA) reload(hardwareAction.dlicRFSweepHWA) reload(hardwareAction.evapAttenuationHWA) reload(hardwareAction.evapAttenuation2HWA) reload(hardwareAction.picomotorPlugHWA) reload(hardwareAction.windFreakOffsetLockHWA) #reload( hardwareAction.AOMChannelHWAs)#CAUSES REFERENCING PROBLEMS! reload(hardwareAction.experimentTablesHWA) reload(hardwareAction.windFreakOffsetLockHighFieldImagingHWA) reload(hardwareAction.greyMollassesOffsetFreqHWA) reload(hardwareAction.dlicRFSweepLZHWA) reload(hardwareAction.digitalMultimeterCurrentMeasureHWA) self.__init__() def stopTimers(self): """stops all timers with error catching """ try: #stop any previous timer, should only have 1 timer at a time if self.connectionTimer is not None: self.connectionTimer.stop() except Exception as e: logger.error( "couldn't stop current timer before starting new one: %s" % e.message) try: #stop any previous timer, should only have 1 timer at a time if self.statusStringTimer is not None: self.statusStringTimer.stop() except Exception as e: logger.error( "couldn't stop current timer before starting new one: %s" % e.message) try: #stop any previous timer, should only have 1 timer at a time if self.getCurrentTimer is not None: self.getCurrentTimer.stop() except Exception as e: logger.error( "couldn't stop current timer before starting new one: %s" % e.message) def _stopSnake(self): """Simply stops the timers, shuts down hardware and sets isRunning bool false """ self.stopTimers() self.closeHardwareActions() self.isRunning = False def startTimers(self): """This timer object polls the experiment runner regularly polling at any time""" #stop any previous timers self.stopTimers() #start timer self.connectionTimer = Timer(self.connectionPollFrequency, self.getStatus) time.sleep(0.1) self.statusStringTimer = Timer(self.statusStringFrequency, self.updateStatusString) time.sleep(0.1) self.getCurrentTimer = Timer(self.getCurrentFrequency, self.getCurrent) """Menu action function to change logger level """ logger.info("timers started") def getStatus(self): """calls the connection objects get status function and updates the statusList """ logger.debug("starting getStatus") try: self.getStatusUpdate() self.checkForCallback() except Exception as e: logger.error("error in getStatus Function") logger.error("error: %s " % e.message) self.mainLog.addLine( "error in getStatus Function. Error: %s" % e.message, 4) def getStatusUpdate(self): """Calls get status and updates times """ try: statusString = self.connection.getStatus() except socket.error as e: logger.error( "failed to get status . message=%s . errno=%s . errstring=%s " % (e.message, e.errno, e.strerror)) self.mainLog.addLine( "Failed to get status from Experiment Runner. message=%s . errno=%s . errstring=%s" % (e.message, e.errno, e.strerror), 3) self.mainLog.addLine( "Cannot update timeRunning - callbacks could be wrong this sequence!", 4) return self.statusList = statusString.split("\n") timeFormat = '%d/%m/%Y %H:%M:%S' timeBegin = datetime.datetime.strptime(self.statusList[2], timeFormat) timeCurrent = datetime.datetime.strptime(self.statusList[3], timeFormat) self.timeRunning = (timeCurrent - timeBegin).total_seconds() logger.debug("time Running = %s " % self.timeRunning) def checkForCallback(self): """if we've received a sequence, we check through all callback times and send off a callback on a hardware action if appropriate""" try: for hdwAct in [ hdwA for hdwA in self.hardwareActions if hdwA.enabled ]: #only iterate through enable hardware actions if hdwAct.awaitingCallback and self.timeRunning >= hdwAct.callbackTime: #callback should be started! try: logger.debug("attempting to callback %s " % hdwAct.hardwareActionName) hdwAct.setVariablesDictionary(self.variables) logger.debug("vars dictionary set to %s " % self.variables) callbackReturnString = hdwAct.callback() self.mainLog.addLine( "%s @ %s secs : %s" % (hdwAct.hardwareActionName, self.timeRunning, callbackReturnString), 2) hdwAct.awaitingCallback = False hdwAct.callbackCounter += 1 except Exception as e: logger.error( "error while performing callback on %s. see error message below" % (hdwAct.hardwareActionName)) logger.error("error: %s " % e.message) self.mainLog.addLine( "error while performing callback on %s. Error: %s" % (hdwAct.hardwareActionName, e.message), 4) except Exception as e: logger.error("error in checkForCallbackFunction") logger.error("error: %s " % e.message) self.mainLog.addLine( "error in checkForCallbackFunction. Error: %s" % e.message, 4) def getCurrent(self): """calls the connection objects get status function and updates the variables dictionary """ if self.getCurrentThread and self.getCurrentThread.isAlive(): #logger.debug( "getCurrent - already waiting - will not start new thread") #removed the above as it fills the log without any useful information self.sequenceStarted = False return else: logger.info("starting getCurrent Thread") self.getCurrentThread = SocketThread() self.getCurrentThread.snakeReference = self # for calling functions of the snake self.getCurrentThread.start() def getCurrentBlocking(self): """calls getCurrent and won't return until XML parsed. unlike above threaded function This is useful when starting up the snake so that we don't start looking for hardware events until a sequence has started and we have received XML""" self.mainLog.addLine("Waiting for next sequence to start") self.xmlString = self.connection.getCurrent( ) # only returns at the beginning of a sequence! Experiment runner then returns the entire XML file logger.debug("length of xml string = %s " % len(self.xmlString)) logger.debug("end of xml file is like [-30:]= %s" % self.xmlString[-30:]) try: root = ET.fromstring(self.xmlString) variables = root.find("variables") self.variables = { child[0].text: float(child[1].text) for child in variables } #timing edges dictionary : name--> value self.timingEdges = { timingEdge.find("name").text: float(timingEdge.find("value").text) for timingEdge in root.find("timing") } self.newSequenceStarted() except ET.ParseError as e: self.mainLog.addLine("Error. Could not parse XML: %s" % e.message, 3) self.mainLog.addLine( "Possible cause is that buffer is full. is XML length %s>= limit %s ????" % (len(self.xmlString), self.connection.BUFFER_SIZE_XML), 3) logger.error("could not parse XML: %s " % self.xmlString) logger.error(e.message) def updateStatusString(self): """update the status string with first element of return of GETSTATUS. similiar to experiment control and camera control. It also does the analysis of progress that doesn't need to be as accurate (e.g. progress bar)""" logger.info("starting update status string") self.statusString = self.statusList[ 0] + "- Time Running = %s " % self.timeRunning self.queue = int(self.statusList[1]) timeFormat = '%d/%m/%Y %H:%M:%S' timeBegin = datetime.datetime.strptime(self.statusList[2], timeFormat) timeEnd = datetime.datetime.strptime(self.statusList[4], timeFormat) self.timeTotal = (timeEnd - timeBegin).total_seconds() if self.timeRunning > self.timeTotal: self.haltedCount += 1 self.runnerHalted = True if self.haltedCount == 0: logger.critical("runner was stopped.") self.mainLog.addLine("Runner stopped!", 3) self.closeHardwareActions() else: if self.haltedCount > 0: self.initialiseHardwareActions() self.haltedCount = 0 self.runnerHalted = False self.progress = 100.0 * self.timeRunning / self.timeTotal def _examineVariablesDictionary_default(self): if len(self.hardwareActions) > 0: logger.debug( "returning first hardware action %s for examineVariablesDictionary default" % self.hardwareActions[0].hardwareActionName) return variableDictionary.ExamineVariablesDictionary( hdwA=self.hardwareActions[0] ) #default is the first in the list else: logger.warning( "hardwareActions list was empty. how should I populate variable examiner...?!." ) return None def updateExamineVariablesDictionary(self, hdwA): """Populates the examineVariablesDictionary Pane appropriately. It is passed the hdwA so that it can find the necessary variables""" self.examineVariablesDictionary.hdwA = hdwA self.examineVariablesDictionary.hardwareActionName = hdwA.hardwareActionName self.examineVariablesDictionary.updateDisplayList() logger.critical("examineVariablesDictionary changed") def refreshExamineVariablesDictionary(self): """calls the updateDisplayList function of examineVariables Dictionary this updates the values in the display list to the latest values in variables dictionary. useful for refereshing at the beginning of a sequence""" self.examineVariablesDictionary.updateDisplayList() logger.info("refreshed examine variables dictionary") def refreshVariableDependentCallbackTimes(self): """if a HWA is variable dependent call back time, we refresh the value using this function. THis should be called in each sequence""" [ hdwA.parseCallbackTime() for hdwA in self.hardwareActions if hdwA.callbackTimeVariableDependent ] def _changeLoggingLevelDebug(self): """Menu action function to change logger level """ logger.setLevel(logging.DEBUG) def _changeLoggingLevelInfo(self): """Menu action function to change logger level """ logger.setLevel(logging.INFO) def _changeLoggingLevelWarning(self): """Menu action function to change logger level """ logger.setLevel(logging.WARNING) def _changeLoggingLevelError(self): """Menu action function to change logger level """ logger.setLevel(logging.ERROR)
import traitsui.api as ui import traits.api as tr import pickle import os from traitsui.file_dialog import open_file, save_file from hcft.about_tool import AboutTool from hcft.utils.csv_joiner import CSVJoiner menu_exit = ui.Action(name='Exit', action='menu_exit') menu_save = ui.Action(name='Save', action='menu_save') menu_open = ui.Action(name='Open', action='menu_open') menu_utilities_csv_joiner = ui.Action(name='CSV Joiner', action='menu_utilities_csv_joiner') menu_about_tool = ui.Action(name='About', action='menu_about_tool') class ViewHandler(ui.Handler): # You can initialize this by obtaining it from the methods below and, self.info = info info = tr.Instance(ui.UIInfo) exit_view = ui.View(ui.VGroup( ui.Label('Do you really wish to end ' 'the session? Any unsaved data ' 'will be lost.'), ui.HGroup(ui.Item('ok', show_label=False, springy=True), ui.Item('cancel', show_label=False, springy=True))), title='Exit dialog',