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
Exemple #3
0
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()
Exemple #5
0
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()
Exemple #6
0
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")
Exemple #7
0
    _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}
Exemple #9
0
        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)
Exemple #11
0
        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,
Exemple #12
0
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")
Exemple #14
0
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)
Exemple #15
0
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',