class Viz2DForceDeflectionX(Viz2D):
    '''Plot adaptor for the pull-out simulator.
    '''
    label = 'F-W'

    show_legend = tr.Bool(True, auto_set=False, enter_set=True)

    def plot(self, ax, vot, *args, **kw):
        P, W = self.vis2d.get_PW()
        ymin, ymax = np.min(P), np.max(P)
        L_y = ymax - ymin
        ymax += 0.05 * L_y
        ymin -= 0.05 * L_y
        xmin, xmax = np.min(W), np.max(W)
        L_x = xmax - xmin
        xmax += 0.03 * L_x
        xmin -= 0.03 * L_x
        ax.plot(W, P, linewidth=2, color='black', alpha=0.4, label='P(w;x=L)')
        ax.set_ylim(ymin=ymin, ymax=ymax)
        ax.set_xlim(xmin=xmin, xmax=xmax)
        ax.set_ylabel('Force P [N]')
        ax.set_xlabel('Deflection w [mm]')
        if self.show_legend:
            ax.legend(loc=4)
        self.plot_marker(ax, vot)

    def plot_marker(self, ax, vot):
        P, W = self.vis2d.get_PW()
        idx = self.vis2d.tloop.get_time_idx(vot)
        P, w = P[idx], W[idx]
        ax.plot([w], [P], 'o', color='black', markersize=10)

    def plot_tex(self, ax, vot, *args, **kw):
        self.plot(ax, vot, *args, **kw)

    traits_view = View(
        Item('name', style='readonly'),
        Item('show_legend'),
    )
class config(HasTraits):
    uuid = traits.Str(desc="UUID")
    desc = traits.Str(desc="Workflow Description")
    # Directories
    working_dir = Directory(mandatory=True,
                            desc="Location of the Nipype working directory")
    sink_dir = Directory(os.path.abspath('.'),
                         mandatory=True,
                         desc="Location where the BIP will store the results")
    crash_dir = Directory(mandatory=False,
                          desc="Location to store crash files")
    save_script_only = traits.Bool(False)
    # Execution

    run_using_plugin = Bool(
        False,
        usedefault=True,
        desc="True to run pipeline with plugin, False to run serially")
    plugin = traits.Enum("PBS",
                         "MultiProc",
                         "SGE",
                         "Condor",
                         usedefault=True,
                         desc="plugin to use, if run_using_plugin=True")
    plugin_args = traits.Dict({"qsub_args": "-q many"},
                              usedefault=True,
                              desc='Plugin arguments.')
    test_mode = Bool(
        False,
        mandatory=False,
        usedefault=True,
        desc='Affects whether where and if the workflow keeps its \
                            intermediary files. True to keep intermediary files. '
    )
    timeout = traits.Float(14.0)
    datagrabber = traits.Instance(Data, ())

    use_advanced_options = Bool(False)
    advanced_options = traits.Code()
class config(BaseWorkflowConfig):
    uuid = traits.Str(desc="UUID")

    # Directories
    base_dir = Directory(
        os.path.abspath('.'),
        mandatory=True,
        desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(mandatory=True,
                         desc="Location where the BIP will store the results")
    save_script_only = traits.Bool(False)

    datagrabber = traits.Instance(Data, ())

    # Regression
    run_one_sample_T_test = traits.Bool(True)
    run_regression = traits.Bool()
    design_csv = traits.File(desc="design .csv file")
    reg_contrasts = traits.Code(
        desc=
        "function named reg_contrasts which takes in 0 args and returns contrasts"
    )
    use_regressors = traits.Bool()
    estimation_method = traits.Enum('Classical', 'Bayesian', 'Bayesian2')
    include_intercept = traits.Bool(True)
    #Normalization

    norm_template = traits.File(desc='Template of files')
    use_mask = traits.Bool(False)
    mask_file = traits.File(desc='already binarized mask file to use')

    #Correction:
    p_threshold = traits.Float(0.05)
    height_threshold = traits.Float(0.05)
    min_cluster_size = traits.Int(25)
    # Advanced Options
    use_advanced_options = traits.Bool()
    advanced_script = traits.Code()

    # Buttons
    check_func_datagrabber = Button("Check")
Beispiel #4
0
class IntRangeEditor(EditorFactory):
    low = tr.Int(0)
    high = tr.Int(1)
    low_name = tr.Str
    high_name = tr.Str
    continuous_update = tr.Bool(False)

    def render(self):
        low = self.low
        high = self.high
        if self.low_name:
            self.low = getattr(self.model, str(self.low_name))
        if self.high_name:
            self.high = getattr(self.model, str(self.high_name))
        if self.n_steps_name:
            self.n_steps = getattr(self.model, str(self.n_steps_name))
        return ipw.IntRangeSlider(
            description=self.label,
            value=self.value, min=low, max=high,
            tooltip=self.tooltip,
            disabled=self.disabled,
            style=style
        )
Beispiel #5
0
class Viz2DStrainInCrack(Viz2D):
    '''Plot adaptor for the pull-out simulator.
    '''
    label = 'strain in crack'

    show_legend = tr.Bool(True, auto_set=False, enter_set=True)

    ax_sig = tr.Any

    def plot(self, ax, vot, *args, **kw):
        eps = self.vis2d.get_eps_t(vot)
        sig = self.vis2d.get_sig_t(vot)
        a_x = self.vis2d.get_a_x()
        ax.plot(eps,
                a_x,
                linewidth=3,
                color='red',
                alpha=0.4,
                label='P(w;x=L)')
        #        ax.fill_betweenx(eps, 0, a_x, facecolor='orange', alpha=0.2)
        ax.set_xlabel('Strain [-]')
        ax.set_ylabel('Position [mm]')
        if self.ax_sig:
            self.ax_sig.clear()
        else:
            self.ax_sig = ax.twiny()
        self.ax_sig.set_xlabel('Stress [MPa]')
        self.ax_sig.plot(sig, a_x, linewidth=2, color='blue')
        self.ax_sig.fill_betweenx(a_x, sig, facecolor='blue', alpha=0.2)
        align_xaxis_np(ax, self.ax_sig)
        if self.show_legend:
            ax.legend(loc=4)

    traits_view = View(
        Item('name', style='readonly'),
        Item('show_legend'),
    )
Beispiel #6
0
class config(BaseWorkflowConfig):
    uuid = traits.Str(desc="UUID")

    # Directories
    base_dir = Directory(
        os.path.abspath('.'),
        mandatory=True,
        desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(mandatory=True,
                         desc="Location where the BIP will store the results")
    surf_dir = Directory(
        desc="freesurfer directory. subject id's should be the same")
    save_script_only = traits.Bool(False)

    # DataGrabber
    datagrabber = traits.Instance(Data, ())

    # segstats
    use_reg = traits.Bool(True)
    inverse_reg = traits.Bool(True)
    use_standard_label = traits.Bool(
        False, desc="use same label file for all subjects")
    label_file = traits.File()
    use_annotation = traits.Bool(
        False,
        desc=
        "use same annotation file for all subjects (will warp to subject space"
    )
    use_subject_annotation = traits.Bool(
        False,
        desc="you need to change datragrabber to\
                                           have outputs lh_annotation and rh_annotation"
    )
    annot_space = traits.String("fsaverage5",
                                desc="subject space of annot file")
    lh_annotation = traits.File()
    rh_annotation = traits.File()
    color_table_file = traits.Enum("Default", "Color_Table", "GCA_color_table",
                                   "None")
    color_file = traits.File()
    proj = traits.BaseTuple(("frac", 0, 1, 0.1), traits.Enum("abs", "frac"),
                            traits.Float(), traits.Float(), traits.Float())
    statname = traits.Str('segstats1', desc="description of the segstat")
class SpikesRemoval(SpanSelectorInSpectrum):
    interpolator_kind = t.Enum(
        'Linear',
        'Spline',
        default='Linear')
    threshold = t.Float()
    show_derivative_histogram = t.Button()
    spline_order = t.Range(1, 10, 3)
    interpolator = None
    default_spike_width = t.Int(5)
    index = t.Int(0)
    add_noise = t.Bool(True,
                       desc="Add noise to the healed portion of the "
                       "spectrum. Use the noise properties "
                       "defined in metadata if present, otherwise "
                       "it defaults to shot noise.")
    view = tu.View(tu.Group(
        tu.Group(
            tu.Item('show_derivative_histogram', show_label=False),
            'threshold',
            show_border=True,),
        tu.Group(
            'add_noise',
            'interpolator_kind',
            'default_spike_width',
            tu.Group(
                'spline_order',
                visible_when='interpolator_kind == \'Spline\''),
            show_border=True,
            label='Advanced settings'),
    ),
        buttons=[OKButton,
                 OurPreviousButton,
                 OurFindButton,
                 OurApplyButton, ],
        handler=SpikesRemovalHandler,
        title='Spikes removal tool')

    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 Signal
        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, Signal):
                    self.noise_type = "heteroscedastic"
                else:
                    self.noise_type = "white"
        else:
            self.noise_type = "shot noise"

    def _threshold_changed(self, old, new):
        self.index = 0
        self.update_plot()

    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):
        self.span_selector_changed()

    def _ss_right_value_changed(self, old, new):
        self.span_selector_changed()

    def create_interpolation_line(self):
        self.interpolated_line = drawing.spectrum.SpectrumLine()
        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 self.ss_left_value == 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.update_spectrum_line()
        self.interpolated_line.close()
        self.interpolated_line = None
        self.reset_span_selector()
        self.find()
Beispiel #8
0
class MATS1D5DPCum(MATSEval):

    node_name = 'Cumulative damage plasticity model'

    E_N = tr.Float(100,
                   label='E_N',
                   desc='Normal stiffness of the interface',
                   MAT=True,
                   enter_set=True,
                   auto_set=False)

    E_T = tr.Float(100,
                   label='E_T',
                   desc='Shear modulus of the interface',
                   MAT=True,
                   enter_set=True,
                   auto_set=False)

    gamma = tr.Float(40.0,
                     label='gamma',
                     desc='Kinematic Hardening Modulus',
                     MAT=True,
                     enter_set=True,
                     auto_set=False)

    K = tr.Float(1,
                 label='K',
                 desc='Isotropic hardening modulus',
                 MAT=True,
                 enter_set=True,
                 auto_set=False)

    c = tr.Float(1,
                 Label='c',
                 desc='Damage accumulation parameter',
                 MAT=True,
                 enter_set=True,
                 auto_set=False)

    tau_bar = tr.Float(1,
                       label='tau_bar',
                       desc='Reversibility limit',
                       MAT=True,
                       enter_set=True,
                       auto_set=False)

    state_var_shapes = dict(s_p=(), alpha=(), z=(), omega=(), kappa=())

    uncoupled_dp = tr.Bool(False, MAT=True, label='Uncoupled d-p')

    s_0 = tr.Float(MAT=True, desc='Elastic strain/displacement limit')

    def __init__(self, *args, **kw):
        super(MATS1D5DPCum, self).__init__(*args, **kw)
        self._update_s0()

    @on_trait_change('tau_bar,E_T')
    def _update_s0(self):
        if not self.uncoupled_dp:
            if self.E_T == 0:
                self.s_0 = 0
            else:
                self.s_0 = self.tau_bar / self.E_T
            self.omega_fn.s_0 = self.s_0

    omega_fn_type = tr.Trait(
        'FRP',
        dict(li=LiDamageFn,
             jirasek=JirasekDamageFn,
             abaqus=AbaqusDamageFn,
             FRP=FRPDamageFn,
             multilinear=MultilinearDamageFn),
        MAT=True,
    )

    @on_trait_change('omega_fn_type')
    def _reset_omega_fn(self):
        print('resetting')
        self.omega_fn = self.omega_fn_type_(s_0=self.s_0)

    omega_fn = tr.Instance(IDamageFn, report=True)

    def _omega_fn_default(self):
        return MultilinearDamageFn()

    def omega(self, k):
        return self.omega_fn(k)

    def omega_derivative(self, k):
        return self.omega_fn.diff(k)

    def init(self, s_pi, alpha, z, omega, kappa):
        r'''
        Initialize the state variables.
        '''
        s_pi[...] = 0
        alpha[...] = 0
        z[...] = 0
        omega[...] = 0
        kappa[...] = 0

    algorithmic = tr.Bool(True)

    def get_corr_pred(self, u_r, t_n, s_p, alpha, z, omega, kappa):

        s = u_r[..., 0]
        w = u_r[..., 1]
        # For normal
        H_w_N = np.array(w <= 0.0, dtype=np.float_)
        E_alg_N = H_w_N * self.E_N
        sig_N = E_alg_N * w
        sig_pi_trial = self.E_T * (s - s_p)
        Z = self.K * z
        # for handling the negative values of isotropic hardening
        h_1 = self.tau_bar + Z
        pos_iso = h_1 > 1e-6

        X = self.gamma * alpha

        # for handling the negative values of kinematic hardening (not yet)
        # h_2 = h * np.sign(sig_pi_trial - X) * \
        #    np.sign(sig_pi_trial) + X * np.sign(sig_pi_trial)
        #pos_kin = h_2 > 1e-6

        f = np.fabs(sig_pi_trial - X) - h_1 * pos_iso

        I = f > 1e-6
        # Return mapping
        delta_lamda_I = f[I] / (self.E_T + self.gamma + np.fabs(self.K))
        # update all the state variables
        s_p[I] += delta_lamda_I * np.sign(sig_pi_trial[I] - X[I])
        z[I] += delta_lamda_I
        alpha[I] += delta_lamda_I * np.sign(sig_pi_trial[I] - X[I])
        kappa[...] = np.max(np.array([kappa, np.fabs(s)]), axis=0)
        omega[...] = self.omega(kappa)
        tau = (1 - omega) * self.E_T * (s - s_p)

        E_alg_T = (1 - omega) * self.E_T

        domega_ds = self.omega_derivative(kappa)
        # Consistent tangent operator
        E_alg_T[I] = -self.E_T / (self.E_T + self.K + self.gamma) \
            * domega_ds[I] * self.E_T * (s[I] - s_p[I]) \
            + (1 - omega[I]) * self.E_T * (self.K + self.gamma) / \
            (self.E_T + self.K + self.gamma)

        sig = np.zeros_like(u_r)
        sig[..., 0] = tau
        sig[..., 1] = sig_N
        E_TN = np.einsum(
            'abEm->Emab',
            np.array([[E_alg_T, np.zeros_like(E_alg_T)],
                      [np.zeros_like(E_alg_N), E_alg_N]]))
        return sig, E_TN
class ImagePlotInspector(traits.HasTraits):
    #Traits view definitions:

    settingsGroup = traitsui.VGroup(
        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("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))
    mainPlotGroup = traitsui.HSplit(plotGroup, label="Image")

    traits_view = traitsui.View(settingsGroup,
                                plotGroup,
                                handler=EagleHandler,
                                resizable=True)

    model = CameraImage()
    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)

    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()
        #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 update(self, model):
        print "updating"
        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)
        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]]))
        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)
Beispiel #10
0
class MATS1D5DP2D(MATSEval):

    node_name = 'Pressure sensitive cumulative damage plasticity'

    E_N = tr.Float(30000, label='E_N',
                   desc='Normal stiffness of the interface',
                   MAT=True,
                   enter_set=True, auto_set=False)

    E_T = tr.Float(12900, label='E_T',
                   desc='Shear modulus of the interface',
                   MAT=True,
                   enter_set=True, auto_set=False)

    gamma = tr.Float(55.0, label='gamma',
                     desc='Kinematic Hardening Modulus',
                     MAT=True,
                     enter_set=True, auto_set=False)

    K = tr.Float(11, label='K',
                 desc='Isotropic hardening modulus',
                 MAT=True,
                 enter_set=True, auto_set=False)

    S_T = tr.Float(0.005, label='S_T',
                 desc='Damage accumulation parameter',
                 MAT=True,
                 enter_set=True, auto_set=False)
    
    S_N = tr.Float(0.005, label='S_N',
                 desc='Damage accumulation parameter',
                 MAT=True,
                 enter_set=True, auto_set=False)

    c_N = tr.Float(1, Label='c_N',
                 desc='Damage accumulation parameter',
                 MAT=True,
                 enter_set=True, auto_set=False)
    
    c_T = tr.Float(1, Label='c_T',
                 desc='Damage accumulation parameter',
                 MAT=True,
                 enter_set=True, auto_set=False)
    
    m = tr.Float(0.3, label='m',
                 desc='Lateral Pressure Coefficient',
                 MAT=True,
                 enter_set=True, auto_set=False)

    sigma_o = tr.Float(4.2, label='sigma_o',
                       desc='Reversibility limit',
                       MAT=True,
                       enter_set=True, auto_set=False)
    
    sig_t = tr.Float(5.0, label='sig_t',
                     MAT=True,
                     enter_set=True, auto_set=False)
    
    b = tr.Float(0.2, label='b',
                 MAT=True,
                 enter_set=True, auto_set=False)

    state_var_shapes = dict(ep_p_N=(),
                            ep_pi_T=(),
                            alpha=(),
                            z=(),
                            omega_T=(),
                            omega_N=())

    D_rs = tr.Property(depends_on='E_N,E_T')

    @tr.cached_property
    def _get_D_rs(self):
        print('recalculating D_rs')
        return np.array([[self.E_T, 0],
                         [0, self.E_N]], dtype=np.float_)

    def init(self, ep_p_N, ep_pi_T, alpha, z, omega_T, omega_N):
        r'''
        Initialize the state variables.
        '''
        ep_p_N[...] = 0
        ep_pi_T[...] = 0
        alpha[...] = 0
        z[...] = 0
        omega_T[...] = 0
        omega_N[...] = 0

    algorithmic = tr.Bool(True)

    def get_corr_pred(self, u_r, t_n, ep_p_N, ep_pi_T, alpha, z, omega_T, omega_N):

        ep_T = u_r[..., 0]
        ep_N = u_r[..., 1]
        print(ep_N)
        # eps_N_i = eps_N_arr[i]
        # eps_T_i = eps_T_arr[i]
        
        sig_N_i_eff_trial = self.E_N * (ep_N - ep_p_N)
        sig_T_i_eff_trial = self.E_T * (ep_T - ep_pi_T)
        #=======================================================================
        # sig_N = (1 - omega_N) * self.E_N * (ep_N - ep_p_N)
        # H_sig_eff_N = np.array(sig_eff_N >= 0.0, dtype=np.float_)
        #=======================================================================
        # sig_T = (1 - omega_T) * self.E_T * (ep_T - ep_pi_T) 
        # '''CHECK PLEASE sig_T'''
        # For tangential
        # Y = 0.5 * self.E_T * (u_T - s_pi)**2
        # sig_pi_trial = self.E_T * (ep_T - ep_pi_T)
        Z = self.K * z
        X = self.gamma * alpha
        f_trial = np.fabs(sig_T_i_eff_trial - self.gamma * alpha) - \
         (self.sigma_o + self.K * z - self.m * sig_N_i_eff_trial) * (1.0 - np.heaviside((sig_N_i_eff_trial), 1) * ((sig_N_i_eff_trial) ** 2 / (self.sig_t) ** 2))
        # Identify inelastic material points
        # @todo: consider the usage of np.where()
        # I = f > 1e-8
        delta_lamda = np.zeros_like(ep_T)
        sig_N_eff = np.zeros_like(ep_T)
        if np.any(f_trial) > 1e-8: 
            
            def f(vars):
                delta_lamda , sig_N_eff = vars
                N = (self.m + np.heaviside((sig_N_eff), 1) * ((-self.m * sig_N_eff ** 2) / (self.sig_t) ** 2 + \
                                                                       (self.sigma_o + self.K * (z + delta_lamda) - self.m * sig_N_eff) * (2 * sig_N_eff / (self.sig_t) ** 2))) / (1. - omega_N)
                
                f1 = self.sigma_o + self.K * (z + delta_lamda) - self.m * sig_N_eff
                
                ft = 1.0 - np.heaviside(sig_N_eff, 1) * (sig_N_eff ** 2 / (self.sig_t) ** 2)
                
                f_lamda = np.fabs(sig_T_i_eff_trial - self.gamma * alpha) - delta_lamda * (self.E_T / (1. - omega_T) + self.gamma) - f1 * ft
                f_N = sig_N_eff - sig_N_i_eff_trial + delta_lamda * self.E_N * N

                return [f_lamda, f_N]
           
            #===================================================================
            # for i in range(np.size(vars)):
            #     sol = root[i](lambda vars: self.f(vars), method='lm', tol=1e-6)
            #     x = sol.vars
            #     print (x)
            #===================================================================
            x0 = np.zeros_like(ep_T)
            
            def get_delta_lambda_sig_N_eff():
                sol = root(lambda vars : f, x0 = x0 ,method='lm', tol=1e-6)
                return sol.x
            
            print (get_delta_lambda_sig_N_eff)
            
            # delta_lamda, sig_N_eff = vars
            ep_p_N += delta_lamda * (self.m - np.heaviside((sig_N_eff), 1) * ((self.m * sig_N_eff ** 2) / (self.sig_t) ** 2 - (self.sigma_o - self.m * sig_N_eff) * (2 * sig_N_eff / (self.sig_t) ** 2)))
            ep_pi_T += delta_lamda * np.sign(sig_T_i_eff_trial - self.gamma * alpha) / (1.0 - omega_T)
            
            z += delta_lamda
            alpha += delta_lamda * np.sign(sig_T_i_eff_trial - self.gamma * alpha)
            
            Y_N = 0.5 * self.E_N * (ep_N - ep_p_N) ** 2.0
            Y_T = 0.5 * self.E_T * (ep_T - ep_pi_T) ** 2.0
            
            omega_N += delta_lamda * (1 - omega_N) ** self.c_N * (Y_N / self.S_N + self.b * Y_T / self.S_T) * np.heaviside(ep_N, 1)
            omega_T += delta_lamda * (1 - omega_T) ** self.c_T * (Y_T / self.S_T + self.b * Y_N / self.S_N)
            
            sig_N_i = (1.0 - omega_N) * sig_N_eff
            
            sig_T_i = (1.0 - omega_T) * self.E_T * (ep_T - ep_pi_T) 
            
            f = np.fabs(sig_T_i / (1 - omega_T) - self.gamma * alpha) - \
            (self.sigma_o + self.K * z - self.m * sig_N_i / (1 - omega_N)) * (1.0 - np.heaviside((sig_N_i / (1 - omega_N)), 1) * ((sig_N_i / (1 - omega_N)) ** 2 / (self.sig_t) ** 2))   
            
        else: 
                
            sig_N_i = (1 - omega_N) * sig_N_i_eff_trial 
            
            sig_T_i = (1 - omega_T) * sig_T_i_eff_trial 
        
            f = f_trial
        # Return mapping
        #=======================================================================
        # delta_lambda_I = (
        #     f[I] / (self.E_T / (1 - omega[I]) + self.gamma + self.K)
        # )
        # # Update all state variables
        # s_pi[I] += (delta_lambda_I * 
        #             np.sign(tau_pi_trial[I] - X[I]) / (1 - omega[I]))
        # Y = 0.5 * self.E_T * (s - s_pi) ** 2
        # omega[I] += (
        #     delta_lambda_I * 
        #     (1 - omega[I]) ** self.c * (Y[I] / self.S) ** self.r * (self.tau_bar / (self.tau_bar - self.m * sig_N[I]))
        # )
        # sig_T[I] = (1 - omega[I]) * self.E_T * (s[I] - s_pi[I])
        # alpha[I] += delta_lambda_I * np.sign(tau_pi_trial[I] - X[I])
        # z[I] += delta_lambda_I
        #=======================================================================
        # Unloading stiffness
        E_alg_T = (1 - omega_T) * self.E_T
        E_alg_N = (1 - omega_N) * self.E_N
        # Consistent tangent operator
#===============================================================================
#         if False:
#             E_alg_T = (
#                 (1 - omega) * self.E_T - 
#                 (1 - omega) * self.E_T ** 2 / 
#                 (self.E_T + (self.gamma + self.K) * (1 - omega)) - 
#                 ((1 - omega) ** self.c * (self.E_T ** 2) * ((Y / self.S) ** self.r)
#                  * np.sign(tau_pi_trial - X) * (s - s_pi)) / 
#                 ((self.E_T / (1 - omega)) + self.gamma + self.K)
#             )
# 
#         # if False:
#             # print('DONT COME HERE')
#         E_alg_T = (
#                 (1 - omega) * self.E_T - 
#                 ((self.E_T ** 2 * (1 - omega)) / 
#                  (self.E_T + (self.gamma + self.K) * (1 - omega)))
#                 -
#                 ((1 - omega) ** self.c * 
#                  (Y / self.S) ** self.r * 
#                     self.E_T ** 2 * (s - s_pi) * self.tau_bar / 
#                     (self.tau_bar - self.m * sig_N) * np.sign(tau_pi_trial - X)) / 
#                 (self.E_T / (1 - omega) + self.gamma + self.K)
#             )
#===============================================================================

        ep = np.zeros_like(u_r)
        ep[..., 0] = ep_T
        ep[..., 1] = ep_N
        E_TN = np.einsum('abEm->Emab',
                         np.array(
                             [
                                 [E_alg_T, np.zeros_like(E_alg_T)],
                                 [np.zeros_like(E_alg_N), E_alg_N]
                             ])
                         )
        print('omega-T', omega_T)
        #print('omega-N', omega_N)
        # abc = open('sigNm0lp-100tan.txt', 'a+', newline='\n')
        # for e in range(len(sig_N)):
        #    abc.write('%f ' % sig_N[e][0])
        # abc.write('\n')
        # abc.close()
        # print('s_pi=', s_pi)
        return ep, E_TN

    def _get_var_dict(self):
        var_dict = super(MATS1D5DP2D, self)._get_var_dict()
        var_dict.update(
            slip=self.get_slip,
            s_el=self.get_s_el,
            shear=self.get_shear,
            omega_T=self.get_omega_T,
            omega_N=self.get_omega_N,
            ep_pi_T=self.get_ep_pi_T,
            alpha=self.get_alpha,
            z=self.get_z
        )
        return var_dict

    def get_slip(self, u_r, tn1, **state):
        return self.get_eps(u_r, tn1)[..., 0]

    def get_shear(self, u_r, tn1, **state):
        return self.get_sig(u_r, tn1, **state)[..., 0]

    def get_omega_T(self, u_r, tn1, ep_pi_T, alpha, z, omega_T):
        return omega_T

    def get_omega_N(self, u_r, tn1, ep_p_N, omega_N):
        return omega_N

    def get_ep_pi_T(self, u_r, tn1, ep_pi_T, alpha, z, omega_T):
        return ep_pi_T

    def get_alpha(self, u_r, tn1, ep_pi_T, alpha, z, omega_T):
        return alpha

    def get_z(self, u_r, tn1, ep_pi_T, alpha, z, omega_T):
        return z

    def get_s_el(self, u_r, tn1, **state):
        ep_T = self.get_slip(u_r, tn1, **state)
        ep_pi_T = self.get_ep_pi_T(u_r, tn1, **state)
        ep_e_T = ep_T - ep_pi_T
        return ep_e_T

#     def get_sig_N(self, u_r, tn1, **state):
#         return self.get_sig(u_r, tn1, **state)[..., 1]

    tree_view = ui.View(
        ui.Item('E_N'),
        ui.Item('E_T'),
        ui.Item('gamma'),
        ui.Item('K'),
        ui.Item('S_T'),
        ui.Item('S_N'),
        ui.Item('c_T'),
        ui.Item('c_N'),
        ui.Item('m'),
        ui.Item('sigma_o'),
        ui.Item('sig_t'),
        ui.Item('b'),
        ui.Item('D_rs', style='readonly')
    )

    traits_view = tree_view
Beispiel #11
0
class ADCChannel(traits.HasTraits):

    voltage = traits.Float(desc="The voltage of the channel")
    channelName = traits.Str(desc="Human defined name of channel")
    channelNumber = traits.Int(
        desc="channel number on box Can be integer from 0 to 7")
    channelMessage = traits.Str(desc="message to denote status of channel")
    criticalValue = traits.Float(
        desc="the value at which message will change and alarm will sound")
    plotScale = traits.Float(
        desc="scale factor to multiply voltage by on plot")
    logBool = traits.Bool(desc="if true data logged to a file")
    channelMessageHigh = "high"
    channelMessageLow = "low"
    statusHigh = traits.Bool(False)
    connection = None  #It must be passed a connection in initialisation
    checkValueBool = traits.Bool(True)
    highIsGood = traits.Bool(True)
    highSoundFile = None
    lowSoundFile = None

    currentLocalTime = time.localtime()
    currentYear = currentLocalTime.tm_year
    currentMonth = currentLocalTime.tm_mon

    def _voltage_get(self):
        """Uses PyHWI connection to ADC server to return voltage """
        #print "latest=%s" %  self.connection.latestResults
        if self.channelNumber in self.connection.latestResults:
            return self.connection.latestResults[self.channelNumber]
        else:
            return -999

    def check_status(self):
        """check if voltage is higher than critical value and change message """
        if self.voltage > self.criticalValue and not self.statusHigh:  #just went high
            self.statusHigh = True
            self.channelMessage = self.channelMessageHigh
            if ss is not None:
                if self.highSoundFile is not None:  #specific high soundfile
                    ss.playFile(os.path.join("sounds", self.highSoundFile), 1,
                                60.0)
                elif self.highIsGood:
                    winsound.MessageBeep(
                        winsound.MB_ICONASTERISK
                    )  #high is good and we just went high so nice sound
                else:
                    winsound.MessageBeep(
                        winsound.MB_ICONHAND
                    )  #high is bad and we just went high so bad sound

        elif self.voltage < self.criticalValue and self.statusHigh:  #just went low
            self.statusHigh = False
            self.channelMessage = self.channelMessageLow
            if ss is not None:
                if self.lowSoundFile is not None:  #specific high soundfile
                    ss.playFile(os.path.join("sounds", self.lowSoundFile), 1,
                                60.0)
                if not self.highIsGood:
                    winsound.MessageBeep(
                        winsound.MB_ICONASTERISK
                    )  #high is bad and we just went low so good sound
                else:
                    winsound.MessageBeep(
                        winsound.MB_ICONHAND
                    )  #high is good and we just went low so bad sound

    def _voltage_changed(self):
        """whenever voltage is changed automatically update the status """
        if self.checkValueBool:
            self.check_status()

    def _voltage_update(self):
        self.voltage = self._voltage_get()

    def format_function_voltage(value):
        """Format function for voltage """
        if value == -999:
            return "Not in Use"
        else:
            return "%0.3f V" % (value)

    channelGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item('channelNumber',
                          label="Channel Number",
                          style="readonly",
                          editor=traitsui.EnumEditor()),
            traitsui.Item('checkValueBool', label="Check Value")),
        traitsui.Item('channelName', label="Channel Name", style="readonly"),
        traitsui.Item('channelMessage',
                      show_label=False,
                      style="readonly",
                      style_sheet='* { font-size: 16px;  }'),
        traitsui.Item('voltage',
                      show_label=False,
                      style="readonly",
                      format_func=format_function_voltage,
                      style_sheet='* { font-size: 18px;  }'),
        traitsui.Item('criticalValue',
                      label="Critical Voltage",
                      show_label=True,
                      style_sheet='* { font-size: 8px;  }'),
        traitsui.Item('plotScale',
                      label="Plot Scale Factor",
                      show_label=True,
                      style_sheet='* { font-size: 8px;  }'),
        show_border=True)

    def __init__(self, channelNumber, connection, **traitsDict):
        super(ADCChannel, self).__init__(**traitsDict)
        self.connection = connection
        self.channelNumber = channelNumber
        if self.channelName is "":
            self.channelName = "Channel %s" % channelNumber

    traits_view = traitsui.View(channelGroup)
class FlowOpFrame(ta.HasTraits):
    # key_list = range(1,21)
    # this_key = ta.Enum(key_list)
    output_file = ta.Str('')
    this_flow_time = ta.Str('t_f6.01')
    this_t_sum = ta.Str('ts63')
    this_parameter = ta.Str('A')
    do_chi = ta.Bool(True)
    do_chi_err = ta.Bool(True)
    Load = ta.Button()
    Show = ta.Button()
    Show_latex = ta.Button()
    Apply = ta.Button()
    #
    view = tua.View(tua.Item('output_file'),
                    tua.Item('this_flow_time'),
                    tua.Item('this_t_sum'),
                    tua.Item('this_parameter'),
                    tua.Item('do_chi'),
                    tua.Item('do_chi_err', enabled_when='do_chi'),
                    tua.Item('Load', show_label=False),
                    tua.Item('Show', show_label=False),
                    tua.Item('Show_latex', show_label=False),
                    tua.Item('Apply', show_label=False),
                    buttons=['OK'],
                    resizable=True)

    #
    def _Load_fired(self):
        global xml_data
        if xml_data is None:
            raise EnvironmentError('plot data has not been loaded')
        # self.key_list = xml_data.plot_data.keys()
        self.output_file = xml_data['Results']['save_file']

    def _Show_fired(self):
        global xml_data
        print(unparse(xml_data, pretty=True))

    def _Show_latex_fired(self):
        global latex_data
        if latex_data is None:
            print('latex data not generated yet')
        else:
            print(latex_data)

    def _Apply_fired(self):
        global xml_data, latex_data
        this_data = xml_data['Results']
        vall, ilist, chil, slist1, slist2 = [], [], [], [], []
        if 'Chi_boot' not in list(this_data.keys()):
            print('Integrated FlowOp result not in keys')
        else:
            this_data = this_data['Chi_boot']
            if self.this_flow_time not in list(this_data.keys()):
                print(self.this_flow_time, ' not in flow time keys ')
                print(list(this_data.keys()))
                return
            this_data = this_data[self.this_flow_time]
            if isinstance(this_data, dict) or isinstance(
                    this_data, OrderedDict):
                vall.append(
                    MakeValAndErr(this_data['Avg'],
                                  this_data['Std'],
                                  latex=True))
            else:
                vall.append(this_data)
            chil.append('N.A.')
            ilist.append('chiint')

        this_data = xml_data['Results']
        if 'Prop_Fit' not in list(this_data.keys()):
            print('Fits not in keys')
            print(list(this_data.keys()))
            return
        this_data = this_data['Prop_Fit']
        if self.this_flow_time not in list(this_data.keys()):
            print(self.this_flow_time, ' not in flow time keys ')
            print(list(this_data.keys()))
            return
        this_data = this_data[self.this_flow_time]
        if self.this_t_sum not in list(this_data.keys()):
            print(self.this_t_sum, ' not in sum source time keys ')
            print(list(this_data.keys()))
            return
        this_data = this_data[self.this_t_sum]
        for ikey, idata in this_data.items():
            this_p = self.this_parameter
            if this_p in list(idata.keys()):
                if isinstance(idata[this_p], dict) or isinstance(
                        idata[this_p], OrderedDict):
                    vall.append(
                        MakeValAndErr(idata[this_p]['Avg'],
                                      idata[this_p]['Std'],
                                      latex=True))
                else:
                    vall.append(idata[this_p])
                if 'Chi_pow_2_pdf' in list(idata.keys()):
                    if isinstance(idata['Chi_pow_2_pdf'], dict) or isinstance(
                            idata['Chi_pow_2_pdf'], OrderedDict):
                        chil.append(
                            MakeValAndErr(idata['Chi_pow_2_pdf']['Avg'],
                                          idata['Chi_pow_2_pdf']['Std'],
                                          latex=True))
                    else:
                        chil.append(idata['Chi_pow_2_pdf'])
                ilist.append(ikey)
                leftval, rightval = list(
                    map(float,
                        ikey.replace('fitr', '').split('-')))
                slist1.append(1 / rightval)
                slist2.append(leftval)
        dump, dump2, ilisttemp, valltemp, chiltemp = (list(x) for x in zip(
            *sorted(zip(slist1, slist2, ilist[1:], vall[1:], chil[1:]))))
        ilist = [ilist[0]] + ilisttemp
        vall = [vall[0]] + valltemp
        chil = [chil[0]] + chiltemp
        latex_data = pa.DataFrame(index=ilist)
        latex_data.loc[:,
                       self.this_parameter + ' Avg'] = pa.Series(vall,
                                                                 index=ilist)
        if len(vall) == len(chil) and self.do_chi:
            latex_data.loc[:, self.this_parameter + ' chi2pdf'] = pa.Series(
                chil, index=ilist)
        with open(xml_data['Results']['save_file'], 'w') as f:
            format_output = FormatLatex(latex_data.to_latex(escape=False))
            f.write(format_output)
Beispiel #13
0
class GCS(t.HasTraits):
    """
    This is the ground control station GUI class. 
    
    For usage, for example if telemetry radio is on COM8 and the GCS Pixhawk is
    on COM7:
    >>> gcs = GCS()
    >>> gcs.setup_uav_link("COM8")
    >>> gcs.poll_uav()
    >>> gcs.setup_gcs_link("COM7")
    >>> gcs.poll_gcs()
    >>> gcs.configure_traits()
    >>> gcs.close()
    """
    # Connections
    dialect = t.Str("gcs_pixhawk")
    show_errors = t.Bool(True)

    # ON GCS: Outgoing
    mission_message = t.Enum(set_mission_mode.keys(), label="Mission Type")
    sweep_angle = t.Float(label="Angle (degrees)")
    sweep_alt_start = t.Float(label="Start Altitude (m)")
    sweep_alt_end = t.Float(label="End Altitude (m)")
    sweep_alt_step = t.Float(label="Number of Altitude Steps")

    mavlink_message = t.Enum(mavlink_msgs, label="Mavlink Message")
    mavlink_message_filt = t.Enum(mavlink_msgs_filt, label="Mavlink Message")
    mavlink_message_params = t.Str(label="params")
    mavlink_message_args = t.Str(', '.join(
        mavlink_msgs_attr[mavlink_msgs_filt[0]]['args'][1:]),
                                 label="Arguments")

    # ON GCS: Incoming
    # Tether
    tether_length = t.Float(t.Undefined, label='Length (m)')
    tether_tension = t.Float(t.Undefined, label='Tension (N)')
    tether_velocity = t.Float(t.Undefined, label="Velocity")

    # ON GCS: Incoming
    # GCS Pixhawk
    gcs_eph = t.Float(t.Undefined)
    gcs_epv = t.Float(t.Undefined)
    gcs_satellites_visible = t.Int(t.Undefined)
    gcs_fix_type = t.Int(t.Undefined)

    gcs_airspeed = t.Float(t.Undefined)
    gcs_groundspeed = t.Float(t.Undefined)
    gcs_heading = t.Float(t.Undefined)
    gcs_velocity = t.Array(shape=(3, ))

    # Location inputs
    gcs_alt = t.Float(t.Undefined)
    gcs_lat = t.Float(t.Undefined)
    gcs_lon = t.Float(t.Undefined)

    # Attitude inputs
    gcs_pitch = t.Float(t.Undefined)
    gcs_roll = t.Float(t.Undefined)
    gcs_yaw = t.Float(t.Undefined)
    gcs_pitchspeed = t.Float(t.Undefined)
    gcs_yawspeed = t.Float(t.Undefined)
    gcs_rollspeed = t.Float(t.Undefined)

    # Battery Inputs
    gcs_current = t.Float(t.Undefined)
    gcs_level = t.Float(t.Undefined)
    gcs_voltage = t.Float(t.Undefined)

    # GCS connectinos
    gcs = t.Any(t.Undefined)
    gcs_polling = t.Bool(False)
    gcs_msg_thread = t.Instance(threading.Thread)
    gcs_error = t.Int(0)
    gcs_port = t.Str(t.Undefined)
    gcs_baud = t.Int(t.Undefined)

    # ON DRONE: Incoming
    # Mission Status
    mission_status = t.Enum(mission_status.keys())

    # Probe
    probe_u = t.Float(t.Undefined, label="u (m/s)")
    probe_v = t.Float(t.Undefined, label="v (m/s)")
    probe_w = t.Float(t.Undefined, label="w (m/s)")

    # Vehicle inputs
    uav_modename = t.Str(t.Undefined)
    uav_armed = t.Bool(t.Undefined)
    uav_eph = t.Float(t.Undefined)
    uav_epv = t.Float(t.Undefined)
    uav_satellites_visible = t.Int(t.Undefined)
    uav_fix_type = t.Int(t.Undefined)

    uav_airspeed = t.Float(t.Undefined)
    uav_groundspeed = t.Float(t.Undefined)
    uav_heading = t.Float(t.Undefined)
    uav_velocity = t.Array(shape=(3, ))

    # Location inputs
    uav_alt = t.Float(t.Undefined)
    uav_lat = t.Float(t.Undefined)
    uav_lon = t.Float(t.Undefined)

    # Attitude inputs
    uav_pitch = t.Float(t.Undefined)
    uav_roll = t.Float(t.Undefined)
    uav_yaw = t.Float(t.Undefined)
    uav_pitchspeed = t.Float(t.Undefined)
    uav_yawspeed = t.Float(t.Undefined)
    uav_rollspeed = t.Float(t.Undefined)

    # Battery Inputs
    uav_current = t.Float(t.Undefined)
    uav_level = t.Float(t.Undefined)
    uav_voltage = t.Float(t.Undefined)

    # Vehicle Connections
    uav = t.Any(t.Undefined)
    uav_polling = t.Bool(False)
    uav_msg_thread = t.Instance(threading.Thread)
    uav_error = t.Int(0)
    uav_port = t.Str(t.Undefined)
    uav_baud = t.Int(t.Undefined)

    # GCS connectinos
    gcs = t.Any(t.Undefined)
    gcs_polling = t.Bool(False)
    gcs_msg_thread = t.Instance(threading.Thread)
    gcs_error = t.Int(0)
    gcs_port = t.Str(t.Undefined)
    gcs_baud = t.Int(t.Undefined)

    # ui Buttons and display groups
    update_mission = t.Button("Update")
    send_mavlink_message = t.Button("Send")
    filtered = t.Bool(True)

    group_input = tui.Group(
        tui.Item(name="mission_status", enabled_when='False'),
        tui.Item(name="mission_message"),
        tui.Item(name="sweep_angle",
                 visible_when='mission_message=="SCHEDULE_SWEEP"'),
        tui.Item(name="sweep_alt_start",
                 visible_when='mission_message=="SCHEDULE_SWEEP"'),
        tui.Item(name="sweep_alt_end",
                 visible_when='mission_message=="SCHEDULE_SWEEP"'),
        tui.Item(name="sweep_alt_step",
                 visible_when='mission_message=="SCHEDULE_SWEEP"'),
        tui.Item(name="update_mission"),
        tui.Item("_"),
        tui.Item("filtered"),
        tui.Item("mavlink_message", visible_when='filtered==False'),
        tui.Item("mavlink_message_filt", visible_when='filtered'),
        tui.Item("mavlink_message_args",
                 enabled_when='False',
                 editor=tui.TextEditor(),
                 height=-40),
        tui.Item("mavlink_message_params"),
        tui.Item("send_mavlink_message"),
        tui.Item("_"),
        tui.Item(name="tether_tension", enabled_when='False'),
        tui.Item(name="tether_length", enabled_when='False'),
        tui.Item(name="tether_velocity", enabled_when='False'),
        tui.Item("_"),
        orientation="vertical",
        show_border=True,
        label="On GCS")
    group_uav = tui.Group(tui.Item(name="uav_modename", enabled_when='False'),
                          tui.Item(name="uav_airspeed", enabled_when='False'),
                          tui.Item(name="uav_groundspeed",
                                   enabled_when='False'),
                          tui.Item(name='uav_armed', enabled_when='False'),
                          tui.Item(name='uav_alt', enabled_when='False'),
                          tui.Item(name='uav_lat', enabled_when='False'),
                          tui.Item(name='uav_lon', enabled_when='False'),
                          tui.Item(name='uav_velocity', enabled_when='False'),
                          tui.Item(name='uav_pitch', enabled_when='False'),
                          tui.Item(name='uav_roll', enabled_when='False'),
                          tui.Item(name='uav_yaw', enabled_when='False'),
                          tui.Item(name='uav_current', enabled_when='False'),
                          tui.Item(name='uav_level', enabled_when='False'),
                          tui.Item(name='uav_voltage', enabled_when='False'),
                          tui.Item("_"),
                          tui.Item(name='probe_u', enabled_when='False'),
                          tui.Item(name='probe_v', enabled_when='False'),
                          tui.Item(name='probe_w', enabled_when='False'),
                          orientation='vertical',
                          show_border=True,
                          label="Incoming")
    group_gcs = tui.Group(tui.Item(name="gcs_airspeed", enabled_when='False'),
                          tui.Item(name="gcs_groundspeed",
                                   enabled_when='False'),
                          tui.Item(name='gcs_alt', enabled_when='False'),
                          tui.Item(name='gcs_lat', enabled_when='False'),
                          tui.Item(name='gcs_lon', enabled_when='False'),
                          tui.Item(name='gcs_velocity', enabled_when='False'),
                          tui.Item(name='gcs_pitch', enabled_when='False'),
                          tui.Item(name='gcs_roll', enabled_when='False'),
                          tui.Item(name='gcs_yaw', enabled_when='False'),
                          tui.Item(name='gcs_current', enabled_when='False'),
                          tui.Item(name='gcs_level', enabled_when='False'),
                          tui.Item(name='gcs_voltage', enabled_when='False'),
                          orientation='vertical',
                          show_border=True,
                          label="GCS")
    traits_view = tui.View(tui.Group(group_input,
                                     group_uav,
                                     group_gcs,
                                     orientation='horizontal'),
                           resizable=True)

    def _update_mission_fired(self):
        """ This will fire when the update_mission button is clicked
        
        In that case we send one of our custom MAVLINK messages, either
        set_mission_mode or schedule_sweep
        
        """
        mode = set_mission_mode[self.mission_message]
        if mode >= 0:
            self.uav.mav.set_mission_mode_send(mode)
        else:
            self.uav.mav.schedule_sweep_send(self.sweep_angle,
                                             self.sweep_alt_start,
                                             self.sweep_alt_end,
                                             self.sweep_alt_step)

    def _mavlink_message_changed(self):
        """ This will fire when the dropdown is changed
        """
        self.mavlink_message_args = ', '.join(
            mavlink_msgs_attr[self.mavlink_message]['args'][1:])

    def _mavlink_message_filt_changed(self):
        """ This will fire when the filtered dropdown is changed
        """
        self.mavlink_message_args = ', '.join(
            mavlink_msgs_attr[self.mavlink_message_filt]['args'][1:])

    def _send_mavlink_message_fired(self):
        """ This will fire when the send_mavlink_message button is clicked
        
        In that case we pass on the mavlink message that the user is trying
        to send. 
        """
        func = mavlink_msgs_attr[self.mavlink_message]['name']
        args = [float(m) for m in self.mavlink_message_params.split(',')]
        getattr(self.uav.mav, func)(*args)

    def setup_uav_link(self, uav_port, uav_baud=56700):
        """
        This sets up the connection to the UAV. 
        
        Parameters
        -----------
        uav_port : str
            Serial port where UAV is connected (via telemetry radio)
        uav_baud: int, optional
            The baud rate. Default is 56700
        """
        mavutil.set_dialect(self.dialect)
        self.uav = mavutil.mavlink_connection(uav_port, uav_baud)
        self.uav_port = uav_port
        self.uav_baud = uav_baud

    def setup_gcs_link(self, gcs_port, gcs_baud=115200):
        """
        This sets up the connection to the GCS Pixhawk. 
        
        Parameters
        -----------
        uav_port : str
            Serial port where GCS Pixhawk is connected (via usb cable)
        uav_baud: int, optional
            The baud rate. Default is 115200
        """
        mavutil.set_dialect(self.dialect)
        self.gcs = mavutil.mavlink_connection(gcs_port, gcs_baud)
        self.gcs_port = gcs_port
        self.gcs_baud = gcs_baud

    def poll_uav(self):
        """
        This runs a new thread that listens for messages from the UAV and
        parses them for the GCS
        """
        self.uav_polling = True

        def worker():
            # Make sure we are connected
            m = self.uav
            m.mav.heartbeat_send(mavutil.mavlink.MAV_TYPE_GCS,
                                 mavutil.mavlink.MAV_AUTOPILOT_INVALID, 0, 0,
                                 0)
            print("Waiting for heartbeat from %s" % m.address)
            self.uav.wait_heartbeat()
            print "Found Heardbeat, continuing"

            i = 0
            while self.uav_polling:
                #                print "uav_polling round", i
                i += 1
                try:
                    s = m.recv(16 * 1024)
                except Exception:
                    time.sleep(0.1)
                # prevent a dead serial port from causing the CPU to spin. The user hitting enter will
                # cause it to try and reconnect
                if len(s) == 0:
                    time.sleep(0.1)

                if 'windows' in platform.architecture()[-1].lower():
                    # strip nsh ansi codes
                    s = s.replace("\033[K", "")

                if m.first_byte:
                    m.auto_mavlink_version(s)
                msgs = m.mav.parse_buffer(s)
                if msgs:
                    for msg in msgs:
                        if getattr(m, '_timestamp', None) is None:
                            m.post_message(msg)
                        if msg.get_type() == "BAD_DATA":
                            if self.show_errors:
                                print "MAV error: %s" % msg
                            self.uav_error += 1
                        else:
                            self.parse_uav_msg(msg)
            print "uav_polling Stopped"
            self.uav_polling = False

        self.uav_msg_thread = threading.Thread(target=worker)
        self.uav_msg_thread.start()

    def poll_gcs(self):
        """
        This runs a new thread that listens for messages from the GCS Pixhawk
        and parses them for the GCS, it also forwards relevant messages to the
        UAV
        """
        self.gcs_polling = True

        def worker():
            # Make sure we are connected
            m = self.gcs
            m.mav.heartbeat_send(mavutil.mavlink.MAV_TYPE_GCS,
                                 mavutil.mavlink.MAV_AUTOPILOT_INVALID, 0, 0,
                                 0)
            print("Waiting for heartbeat from %s" % m.address)
            self.gcs.wait_heartbeat()
            print "Found Heardbeat, continuing"
            i = 0
            while self.gcs_polling:
                #                print "gcs_polling round", i
                i += 1
                try:
                    s = m.recv(16 * 1024)
                except Exception:
                    time.sleep(0.1)
                # prevent a dead serial port from causing the CPU to spin. The user hitting enter will
                # cause it to try and reconnect
                if len(s) == 0:
                    time.sleep(0.1)

                if 'windows' in platform.architecture()[-1].lower():
                    # strip nsh ansi codes
                    s = s.replace("\033[K", "")

                if m.first_byte:
                    m.auto_mavlink_version(s)
                msgs = m.mav.parse_buffer(s)
                if msgs:
                    for msg in msgs:
                        if getattr(m, '_timestamp', None) is None:
                            m.post_message(msg)
                        if msg.get_type() == "BAD_DATA":
                            if self.show_errors:
                                print "MAV error: %s" % msg
                            self.gcs_error += 1
                        else:
                            self.parsefwd_gcs_msg(msg)
            print "gcs_polling Stopped"
            self.gcs_polling = False

        self.gcs_msg_thread = threading.Thread(target=worker)
        self.gcs_msg_thread.start()

    def parse_uav_msg(self, m):
        """
        This parses a message received from the UAV and stores the values
        in the class attributes so that the GUI will update
        """
        #        print "Parsing Message"
        typ = m.get_type()
        if typ == 'GLOBAL_POSITION_INT':
            (self.uav_lat, self.uav_lon) = (m.lat / 1.0e7, m.lon / 1.0e7)
            self.uav_velocity = (m.vx / 100.0, m.vy / 100.0, m.vz / 100.0)
        elif typ == 'GPS_RAW':
            pass  # better to just use global position int
            # (self.lat, self.lon) = (m.lat, m.lon)
            # self.__on_change('location')
        elif typ == 'GPS_RAW_INT':
            # (self.lat, self.lon) = (m.lat / 1.0e7, m.lon / 1.0e7)
            self.uav_eph = m.eph
            self.uav_epv = m.epv
            self.uav_satellites_visible = m.satellites_visible
            self.uav_fix_type = m.fix_type
        elif typ == "VFR_HUD":
            self.uav_heading = m.heading
            self.uav_alt = m.alt
            self.uav_airspeed = m.airspeed
            self.uav_groundspeed = m.groundspeed
        elif typ == "ATTITUDE":
            self.uav_pitch = m.pitch
            self.uav_yaw = m.yaw
            self.uav_roll = m.roll
            self.uav_pitchspeed = m.pitchspeed
            self.uav_yawspeed = m.yawspeed
            self.uav_rollspeed = m.rollspeed
        elif typ == "SYS_STATUS":
            self.uav_voltage = m.voltage_battery
            self.uav_current = m.current_battery
            self.uav_level = m.battery_remaining
        elif typ == "HEARTBEAT":
            pass
#        print "Parsing Message DONE"

    def fwd_msg_to_uav(self, m):
        """This forwards messages from the GCS Pixhawk to the UAV if there is
        a UAV connected"""
        if self.uav is not t.Undefined:
            self.uav.write(m.get_msgbuf())

    def parsefwd_gcs_msg(self, m):
        """
        This parses a message received from the GCS Pixhawk, stores the values
        in the class attributes so that the GUI will update, and forwards 
        relevant messages to the UAV
        """
        #        print "Parsing Message"
        typ = m.get_type()
        if typ == 'GLOBAL_POSITION_INT':
            (self.gcs_lat, self.gcs_lon) = (m.lat / 1.0e7, m.lon / 1.0e7)
            self.gcs_velocity = (m.vx / 100.0, m.vy / 100.0, m.vz / 100.0)
            # Forward message
            self.fwd_msg_to_uav(m)
        elif typ == 'GPS_RAW':
            # better to just use global position int
            # (self.lat, self.lon) = (m.lat, m.lon)
            # self.__on_change('location')
            # Forward message
            self.fwd_msg_to_uav(m)
        elif typ == 'GPS_RAW_INT':
            # (self.lat, self.lon) = (m.lat / 1.0e7, m.lon / 1.0e7)
            self.gcs_eph = m.eph
            self.gcs_epv = m.epv
            self.gcs_satellites_visible = m.satellites_visible
            self.gcs_fix_type = m.fix_type
            # Forward message
            self.fwd_msg_to_uav(m)
        elif typ == "VFR_HUD":
            self.gcs_heading = m.heading
            self.gcs_alt = m.alt
            self.gcs_airspeed = m.airspeed
            self.gcs_groundspeed = m.groundspeed
            # Forward message
            self.fwd_msg_to_uav(m)
        elif typ == "ATTITUDE":
            self.gcs_pitch = m.pitch
            self.gcs_yaw = m.yaw
            self.gcs_roll = m.roll
            self.gcs_pitchspeed = m.pitchspeed
            self.gcs_yawspeed = m.yawspeed
            self.gcs_rollspeed = m.rollspeed
            # Forward message
            self.fwd_msg_to_uav(m)
        elif typ == "SYS_STATUS":
            self.gcs_voltage = m.voltage_battery
            self.gcs_current = m.current_battery
            self.gcs_level = m.battery_remaining
        elif typ == "HEARTBEAT":
            # Forward message
            self.fwd_msg_to_uav(m)


#        print "Parsing Message DONE"

    def close(self, *args, **kwargs):
        """
        This closes down the serial connections and stop the GUI polling
        """
        print 'Closing down connection'
        try:
            self.uav_polling = False
            self.uav.close()
        except:
            pass
        try:
            self.gcs_polling = False
            self.gcs.close()
        except:
            pass
Beispiel #14
0
class Parameter(traits.HasTraits):
    """represents a lmfit variable in a fit. E.g. the standard deviation in a gaussian
    fit"""
    parameter = traits.Instance(lmfit.Parameter)
    name = traits.Str

    initialValue = traits.Float
    calculatedValue = traits.Float
    vary = traits.Bool(True)

    minimumEnable = traits.Bool(False)
    minimum = traits.Float

    maximumEnable = traits.Bool(False)
    maximum = traits.Float

    stdevError = traits.Float

    def __init__(self, **traitsDict):
        super(Parameter, self).__init__(**traitsDict)
        self.parameter = lmfit.Parameter(name=self.name)

    def _initialValue_changed(self):
        self.parameter.set(value=self.initialValue)

    def _vary_changed(self):
        self.parameter.set(vary=self.vary)

    def _minimum_changed(self):
        if self.minimumEnable:
            self.parameter.set(min=self.minimum)

    def _maximum_changed(self):
        if self.maximumEnable:
            self.parameter.set(max=self.maximum)

    traits_view = traitsui.View(traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("vary", label="vary?", resizable=True),
            traitsui.Item("name",
                          show_label=False,
                          style="readonly",
                          width=0.2,
                          resizable=True),
            traitsui.Item("initialValue",
                          label="initial",
                          show_label=True,
                          resizable=True),
            traitsui.Item("calculatedValue",
                          label="calculated",
                          show_label=True,
                          format_str="%G",
                          style="readonly",
                          width=0.2,
                          resizable=True),
            traitsui.Item("stdevError",
                          show_label=False,
                          format_str=u"\u00B1%G",
                          style="readonly",
                          resizable=True)),
        traitsui.HGroup(
            traitsui.Item("minimumEnable", label="min?", resizable=True),
            traitsui.Item("minimum",
                          label="min",
                          resizable=True,
                          visible_when="minimumEnable"),
            traitsui.Item("maximumEnable", label="max?", resizable=True),
            traitsui.Item("maximum",
                          label="max",
                          resizable=True,
                          visible_when="maximumEnable"))),
                                kind="subpanel")
Beispiel #15
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()
Beispiel #16
0
class ComponentFit(SpanSelectorInSignal1D):
    only_current = t.Bool(True)
    iterpath = t.Enum(
        'flyback',
        'serpentine',
        default='serpentine',
        desc='Define the iterating pattern over the navigation space.')

    def __init__(self,
                 model,
                 component,
                 signal_range=None,
                 estimate_parameters=True,
                 fit_independent=False,
                 only_current=True,
                 iterpath='flyback',
                 **kwargs):
        if model.signal.axes_manager.signal_dimension != 1:
            raise SignalDimensionError(
                model.signal.axes_manager.signal_dimension, 1)

        self.signal = model.signal
        self.axis = self.signal.axes_manager.signal_axes[0]
        self.span_selector = None
        self.model = model
        self.component = component
        self.signal_range = signal_range
        self.estimate_parameters = estimate_parameters
        self.fit_independent = fit_independent
        self.fit_kwargs = kwargs
        self.only_current = only_current
        self.iterpath = iterpath
        if signal_range == "interactive":
            if (not hasattr(self.model, '_plot') or self.model._plot is None
                    or not self.model._plot.is_active):
                self.model.plot()
            self.span_selector_switch(on=True)

    def _fit_fired(self):
        if (self.signal_range != "interactive"
                and self.signal_range is not None):
            self.model.set_signal_range(*self.signal_range)
        elif self.signal_range == "interactive":
            self.model.set_signal_range(self.ss_left_value,
                                        self.ss_right_value)

        # Backup "free state" of the parameters and fix all but those
        # of the chosen component
        if self.fit_independent:
            active_state = []
            for component_ in self.model:
                active_state.append(component_.active)
                if component_ is not self.component:
                    component_.active = False
                else:
                    component_.active = True
        else:
            free_state = []
            for component_ in self.model:
                for parameter in component_.parameters:
                    free_state.append(parameter.free)
                    if component_ is not self.component:
                        parameter.free = False

        # Setting reasonable initial value for parameters through
        # the components estimate_parameters function (if it has one)
        only_current = self.only_current
        if self.estimate_parameters:
            if hasattr(self.component, 'estimate_parameters'):
                if self.signal_range == "interactive":
                    self.component.estimate_parameters(
                        self.signal,
                        self.ss_left_value,
                        self.ss_right_value,
                        only_current=only_current)
                elif self.signal_range is not None:
                    self.component.estimate_parameters(
                        self.signal,
                        self.signal_range[0],
                        self.signal_range[1],
                        only_current=only_current)

        if only_current:
            self.model.fit(**self.fit_kwargs)
        else:
            self.model.multifit(iterpath=self.iterpath, **self.fit_kwargs)

        # Restore the signal range
        if self.signal_range is not None:
            self.model.channel_switches = (
                self.model.backup_channel_switches.copy())

        self.model.update_plot()

        if self.fit_independent:
            for component_ in self.model:
                component_.active = active_state.pop(0)
        else:
            # Restore the "free state" of the components
            for component_ in self.model:
                for parameter in component_.parameters:
                    parameter.free = free_state.pop(0)

    def apply(self):
        self._fit_fired()
Beispiel #17
0
class Pca(Model):
    """Represent the PCA model of a data set."""
    ds = DataSet()
    settings = _traits.WeakRef()
    # List of variable names with zero variance in the data vector
    zero_variance = _traits.List()

    #checkbox bool for standardised results
    standardise = _traits.Bool(False)
    calc_n_pc = _traits.Int()
    min_pc = 2
    # max_pc = _traits.Property()
    max_pc = 10
    min_std = _traits.Float(0.001)


    def _get_res(self):
        '''Does the PCA calculation and gets the results

        This return an results object that holds copies of the
        various result data. Each result set i an DataSet containing
        all metadata necessary for presenting the result.
        '''
        if self.settings.standardise:
            std_ds = True
        else:
            std_ds = False
        if std_ds and self._have_zero_std_var():
            raise InComputeable('Matrix have variables with zero variance',
                                self.zero_variance)
        pca = PCA(self.ds.values,
                  numComp=self.settings.calc_n_pc, Xstand=std_ds, cvType=["loo"])

        return self._pack_res(pca)


    def _have_zero_std_var(self):
        sv = self.ds.values.std(axis=0)
        dm = sv < self.min_std
        if _np.any(dm):
            vv = _np.array(self.ds.var_n)
            self.zero_variance = list(vv[_np.nonzero(dm)])
            return True
        else:
            self.zero_variance = []
            return False


    def _get_max_pc(self):
        return max((min(self.ds.n_objs, self.ds.n_vars, 12) - 2), self.min_pc)


    def _calc_n_pc_default(self):
        return self.max_pc


    def _pack_res(self, pca_obj):
        res = Result('PCA {0}'.format(self.ds.display_name))

        # Scores
        mT = pca_obj.X_scores()
        res.scores = DataSet(
            mat=_pd.DataFrame(
                data=mT,
                index=self.ds.obj_n,
                columns=["PC-{0}".format(i+1) for i in range(mT.shape[1])],
                ),
            subs=self.ds.subs,
            display_name='Scores')

        # Loadings
        mP = pca_obj.X_loadings()
        res.loadings = DataSet(
            mat=_pd.DataFrame(
                data=mP,
                index=self.ds.var_n,
                columns=["PC-{0}".format(i+1) for i in range(mP.shape[1])],
                ),
            subs=self.ds.rsubs,
            display_name='Loadings')

        # Correlation loadings
        mCL = pca_obj.X_corrLoadings()
        res.corr_loadings = DataSet(
            mat=_pd.DataFrame(
                data=mCL,
                index=self.ds.var_n,
                columns=["PC-{0}".format(i+1) for i in range(mCL.shape[1])],
                ),
            display_name='Correlation loadings')

        # Explained variance
        cal = pca_obj.X_calExplVar()
        cum_cal = pca_obj.X_cumCalExplVar()[1:]
        val = pca_obj.X_valExplVar()
        cum_val = pca_obj.X_cumValExplVar()[1:]
        res.expl_var = DataSet(
            mat=_pd.DataFrame(
                data=[cal, cum_cal, val, cum_val],
                index=['calibrated', 'cumulative calibrated', 'validated', 'cumulative validated'],
                columns=["PC-{0}".format(i+1) for i in range(len(cal))],
                ),
            display_name='Explained variance')

        # Residuals E after each computed PC
        # Return a dictionary with arrays
        # I can put this into a Pandas Panel 3D structure
        resids = pca_obj.X_residuals()

        # predicted matrices Xhat from calibration after each computed PC.
        # FIXME: Is this X_predCal()
        # cal_pred_x = pca_obj.calPredX()

        #validated matrices Xhat from calibration after each computed PC.
        # val_pred_x = pca_obj.valPredX()

        # MSEE from cross validation after each computed PC.
        msee = pca_obj.X_MSEE()

        # MSEE from cross validation after each computed PC for each variable.
        ind_var_msee = pca_obj.X_MSEE_indVar()

        # MSECV from cross validation after each computed PC.
        msecv = pca_obj.X_MSECV()

        # MSECV from cross validation after each computed PC for each variable.
        ind_var_msecv = pca_obj.X_MSECV_indVar()

        return res
Beispiel #18
0
class DataAxis(t.HasTraits):
    name = t.Str()
    units = t.Str()
    scale = t.Float()
    offset = t.Float()
    size = t.CInt()
    low_value = t.Float()
    high_value = t.Float()
    value = t.Range('low_value', 'high_value')
    low_index = t.Int(0)
    high_index = t.Int()
    slice = t.Instance(slice)
    navigate = t.Bool(t.Undefined)
    index = t.Range('low_index', 'high_index')
    axis = t.Array()
    continuous_value = t.Bool(False)

    def __init__(self,
                 size,
                 index_in_array=None,
                 name=t.Undefined,
                 scale=1.,
                 offset=0.,
                 units=t.Undefined,
                 navigate=t.Undefined):
        super(DataAxis, self).__init__()
        self.name = name
        self.units = units
        self.scale = scale
        self.offset = offset
        self.size = size
        self.high_index = self.size - 1
        self.low_index = 0
        self.index = 0
        self.update_axis()
        self.navigate = navigate
        self.axes_manager = None
        self.on_trait_change(self.update_axis,
                             ['scale', 'offset', 'size'])
        self.on_trait_change(self.update_value, 'index')
        self.on_trait_change(self.set_index_from_value, 'value')
        self.on_trait_change(self._update_slice, 'navigate')
        self.on_trait_change(self.update_index_bounds, 'size')
        # The slice must be updated even if the default value did not
        # change to correctly set its value.
        self._update_slice(self.navigate)

    @property
    def index_in_array(self):
        if self.axes_manager is not None:
            return self.axes_manager._axes.index(self)
        else:
            raise AttributeError(
                "This DataAxis does not belong to an AxesManager"
                " and therefore its index_in_array attribute "
                " is not defined")

    @property
    def index_in_axes_manager(self):
        if self.axes_manager is not None:
            return self.axes_manager._get_axes_in_natural_order().\
                index(self)
        else:
            raise AttributeError(
                "This DataAxis does not belong to an AxesManager"
                " and therefore its index_in_array attribute "
                " is not defined")

    def _get_positive_index(self, index):
        if index < 0:
            index = self.size + index
            if index < 0:
                raise IndexError("index out of bounds")
        return index

    def _get_index(self, value):
        if isfloat(value):
            return self.value2index(value)
        else:
            return value

    def _get_array_slices(self, slice_):
        """Returns a slice to slice the corresponding data axis without
        changing the offset and scale of the DataAxis.

        Parameters
        ----------
        slice_ : {float, int, slice}

        Returns
        -------
        my_slice : slice

        """
        v2i = self.value2index

        if isinstance(slice_, slice):
            start = slice_.start
            stop = slice_.stop
            step = slice_.step
        else:
            if isfloat(slice_):
                start = v2i(slice_)
            else:
                start = self._get_positive_index(slice_)
            stop = start + 1
            step = None

        if isfloat(step):
            step = int(round(step / self.scale))
        if isfloat(start):
            try:
                start = v2i(start)
            except ValueError:
                # The value is below the axis limits
                # we slice from the start.
                start = None
        if isfloat(stop):
            try:
                stop = v2i(stop)
            except ValueError:
                # The value is above the axes limits
                # we slice up to the end.
                stop = None

        if step == 0:
            raise ValueError("slice step cannot be zero")

        return slice(start, stop, step)

    def _slice_me(self, slice_):
        """Returns a slice to slice the corresponding data axis and
        change the offset and scale of the DataAxis acordingly.

        Parameters
        ----------
        slice_ : {float, int, slice}

        Returns
        -------
        my_slice : slice

        """
        i2v = self.index2value

        my_slice = self._get_array_slices(slice_)

        start, stop, step = my_slice.start, my_slice.stop, my_slice.step

        if start is None:
            if step > 0 or step is None:
                start = 0
            else:
                start = self.size - 1
        self.offset = i2v(start)
        if step is not None:
            self.scale *= step

        return my_slice

    def _get_name(self):
        if self.name is t.Undefined:
            if self.axes_manager is None:
                name = "Unnamed"
            else:
                name = "Unnamed " + ordinal(self.index_in_axes_manager)
        else:
            name = self.name
        return name

    def __repr__(self):
        text = '<%s axis, size: %i' % (self._get_name(),
                                       self.size,)
        if self.navigate is True:
            text += ", index: %i" % self.index
        text += ">"
        return text.encode('utf8')

    def __str__(self):
        return self._get_name() + " axis"

    def connect(self, f, trait='value'):
        self.on_trait_change(f, trait)

    def disconnect(self, f, trait='value'):
        self.on_trait_change(f, trait, remove=True)

    def update_index_bounds(self):
        self.high_index = self.size - 1

    def update_axis(self):
        self.axis = generate_axis(self.offset, self.scale, self.size)
        if len(self.axis) != 0:
            self.low_value, self.high_value = (
                self.axis.min(), self.axis.max())

    def _update_slice(self, value):
        if value is False:
            self.slice = slice(None)
        else:
            self.slice = None

    def get_axis_dictionary(self):
        adict = {
            'name': self.name,
            'scale': self.scale,
            'offset': self.offset,
            'size': self.size,
            'units': self.units,
            'navigate': self.navigate
        }
        return adict

    def copy(self):
        return DataAxis(**self.get_axis_dictionary())

    def __copy__(self):
        return self.copy()

    def __deepcopy__(self, memo):
        cp = self.copy()
        return cp

    def update_value(self):
        self.value = self.axis[self.index]

    def value2index(self, value, rounding=round):
        """Return the closest index to the given value if between the limit.

        Parameters
        ----------
        value : number or numpy array

        Returns
        -------
        index : integer or numpy array

        Raises
        ------
        ValueError if any value is out of the axis limits.

        """
        if value is None:
            return None

        if isinstance(value, np.ndarray):
            if rounding is round:
                rounding = np.round
            elif rounding is math.ceil:
                rounding = np.ceil
            elif rounding is math.floor:
                rounding = np.floor

        index = rounding((value - self.offset) / self.scale)

        if isinstance(value, np.ndarray):
            index = index.astype(int)
            if np.all(self.size > index) and np.all(index >= 0):
                return index
            else:
                raise ValueError("A value is out of the axis limits")
        else:
            index = int(index)
            if self.size > index >= 0:
                return index
            else:
                raise ValueError("The value is out of the axis limits")

    def index2value(self, index):
        if isinstance(index, np.ndarray):
            return self.axis[index.ravel()].reshape(index.shape)
        else:
            return self.axis[index]

    def set_index_from_value(self, value):
        self.index = self.value2index(value)
        # If the value is above the limits we must correct the value
        if self.continuous_value is False:
            self.value = self.index2value(self.index)

    def calibrate(self, value_tuple, index_tuple, modify_calibration=True):
        scale = (value_tuple[1] - value_tuple[0]) /\
            (index_tuple[1] - index_tuple[0])
        offset = value_tuple[0] - scale * index_tuple[0]
        if modify_calibration is True:
            self.offset = offset
            self.scale = scale
        else:
            return offset, scale

    def value_range_to_indices(self, v1, v2):
        """Convert the given range to index range.

        When an out of the axis limits, the endpoint is used instead.

        Parameters
        ----------
        v1, v2 : float
            The end points of the interval in the axis units. v2 must be
            greater than v1.

        """
        if v1 > v2:
            raise ValueError("v2 must be greater than v1.")

        if v1 is not None and v1 > self.low_value and v1 <= self.high_value:
            i1 = self.value2index(v1)
        else:
            i1 = 0
        if v2 is not None and v2 < self.high_value and v2 >= self.low_value:
            i2 = self.value2index(v2)
        else:
            i2 = self.size - 1
        return i1, i2
Beispiel #19
0
class config(HasTraits):
    uuid = traits.Str(desc="UUID")

    # Directories
    working_dir = Directory(mandatory=True, desc="Location of the Nipype working directory")
    base_dir = Directory(os.path.abspath('.'),exists=True, desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(mandatory=True, desc="Location where the BIP will store the results")
    crash_dir = Directory(mandatory=False, desc="Location to store crash files")
    surf_dir = Directory(os.path.abspath('.'),mandatory=True, desc="Freesurfer subjects directory")

    # Execution
    run_using_plugin = Bool(False, usedefault=True, desc="True to run pipeline with plugin, False to run serially")
    plugin = traits.Enum("PBS", "MultiProc", "SGE", "Condor",
        usedefault=True,
        desc="plugin to use, if run_using_plugin=True")
    plugin_args = traits.Dict({"qsub_args": "-q many"},
        usedefault=True, desc='Plugin arguments.')
    test_mode = Bool(False, mandatory=False, usedefault=True,
        desc='Affects whether where and if the workflow keeps its \
                            intermediary files. True to keep intermediary files. ')
    # Subjects
    datagrabber = traits.Instance(Data, ())
    subjects = traits.List(traits.Str, mandatory=True, usedefault=True,
        desc="Subject id's. Note: These MUST match the subject id's in the \
                                Freesurfer directory. For simplicity, the subject id's should \
                                also match with the location of individual functional files.")
    func_template = traits.String('%s/cleaned_resting.nii.gz')
    reg_template = traits.String('%s/cleaned_resting_reg.dat')
    ref_template = traits.String('%s/cleaned_resting_ref.nii.gz')
    combine_surfaces = traits.Bool() 

    # Target surface
    target_surf = traits.Enum('fsaverage4', 'fsaverage3', 'fsaverage5',
                              'fsaverage6', 'fsaverage', 'subject',
                              desc='which average surface to map to')
    surface_fwhm = traits.List([5], traits.Float(), mandatory=True,
        usedefault=True,
        desc="How much to smooth on target surface")
    projection_stem = traits.Str('-projfrac-avg 0 1 0.1',
                                 desc='how to project data onto the surface')
    combine_surfaces = traits.Bool(desc=('compute correlation matrix across'
                                         'both left and right surfaces'))

    # Saving output
    out_type = traits.Enum('mat', 'hdf5', desc='mat or hdf5')
    hdf5_package = traits.Enum('h5py', 'pytables',
        desc='which hdf5 package to use')
    # Advanced Options
    use_advanced_options = traits.Bool()
    advanced_script = traits.Code()

    # Atlas mapping
    surface_atlas = traits.Str('None',
                               desc='Name of parcellation atlas')

    # Buttons
    check_func_datagrabber = Button("Check")

    def _check_func_datagrabber_fired(self):
        subs = self.subjects
        for s in subs:
            for template in [self.func_template, self.ref_template,
                             self.reg_template]:
                check_path(os.path.join(self.base_dir, template % s))
            check_path(os.path.join(self.surf_dir, s))
Beispiel #20
0
class TimeLoop(tr.HasStrictTraits):

    tline = tr.Instance(TLine)
    '''Time line object specifying the start, end, time step and current time
    '''
    def _tline_default(self):
        return TLine(min=0.0, max=1.0, step=1.0)

    ts = tr.Instance(ITStepperEval)
    '''State object delivering the predictor and corrector
    '''

    bc_mngr = tr.Instance(BCondMngr, ())
    '''Boundary condition manager.
    '''

    bc_list = tr.List([])
    '''List of boundary conditions.
    '''

    def _bc_list_changed(self):
        self.bc_mngr.bcond_list = self.bc_list

    step_tolerance = tr.Float(1e-8)
    '''Time step tolerance.
    '''

    k_max = tr.Int(300)
    '''Maximum number of iterations.
    '''

    tolerance = tr.Float(1e-3)
    '''Tolerance of the residuum norm. 
    '''

    t_n1 = tr.Float(0, input=True)
    '''Target time for the next increment.
    '''

    t_n = tr.Float(0, input=True)
    '''Time of the last equilibrium state. 
    '''

    d_t = tr.Float(0, input=True)
    '''Current time increment size.
    '''

    paused = tr.Bool(False)
    restart = tr.Bool(True)
    stop = tr.Bool(False)

    def init(self):
        self.stop = False
        if self.paused:
            self.paused = False
            return
        if self.restart:
            self.tline.val = 0
            # self.setup()
            self.restart = False
        self.bc_mngr.setup(None)
        for rt in self.response_traces:
            rt.setup(self)

    algorithmic = tr.Bool(True)

    def eval(self):
        update_state = False
        K = SysMtxAssembly()
        self.bc_mngr.apply_essential(K)
        U_n = np.zeros((self.ts.mesh.n_dofs, ), dtype=np.float_)
        dU = np.copy(U_n)
        U_k = np.copy(U_n)
        F_ext = np.zeros_like(U_n)
        algorithmic = self.algorithmic
        pos_def = True

        while (self.t_n1 - self.tline.max) <= self.step_tolerance:

            print('current time %f' % self.t_n1, end=' ')
            self.d_t = self.tline.step
            k = 0
            step_flag = 'predictor'

            while k < self.k_max:

                if self.stop:
                    return U_n

                K.reset_mtx()
                K_arr, F_int, n_F_int = self.ts.get_corr_pred(
                    U_k, dU, self.t_n, self.t_n1, update_state, algorithmic)
                if update_state:
                    update_state = False

                K.sys_mtx_arrays.append(K_arr)

                F_ext[:] = 0.0
                self.bc_mngr.apply(step_flag, None, K, F_ext, self.t_n,
                                   self.t_n1)
                R = F_ext - F_int
                K.apply_constraints(R)
                if n_F_int == 0.0:
                    n_F_int = 1.0
                norm = np.linalg.norm(R, ord=None)  # / n_F_int
                if norm < self.tolerance:
                    print('converged in %d iterations' % (k + 1))
                    update_state = True
                    self.record_response(U_k, F_int, self.t_n1)
                    break
                dU, pos_def = K.solve(check_pos_def=algorithmic)
                if algorithmic and not pos_def:
                    algorithmic = False
                    print('switched to secant')
                    continue
                U_k += dU
                k += 1
                step_flag = 'corrector'

            U_n = np.copy(U_k)
            self.t_n = self.t_n1
            self.t_n1 = self.t_n + self.d_t
            self.tline.val = min(self.t_n, self.tline.max)

        return U_n

    write_dir = tr.Directory
    F_int_record = tr.List(tr.Array(np.float_))
    U_record = tr.List(tr.Array(np.float_))
    F_ext_record = tr.List(tr.Array(np.float_))
    t_record = tr.List

    response_traces = tr.List()

    def record_response(self, U_k, F_int, t):

        self.F_int_record.append(np.copy(F_int))
        self.U_record.append(np.copy(U_k))
        self.t_record.append(self.t_n1)

        for rt in self.response_traces:
            rt.update(U_k, t)
        return

    def get_time_idx_arr(self, vot):
        '''Get the index corresponding to visual time
        '''
        x = self.t_record
        idx = np.array(np.arange(len(x)), dtype=np.float_)
        t_idx = np.interp(vot, x, idx)
        return np.array(t_idx + 0.5, np.int_)

    def get_time_idx(self, vot):
        return int(self.get_time_idx_arr(vot))
class config(HasTraits):
    uuid = traits.Str(desc="UUID")

    # Directories
    working_dir = Directory(mandatory=True,
                            desc="Location of the Nipype working directory")
    base_dir = Directory(
        os.path.abspath('.'),
        mandatory=True,
        desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(mandatory=True,
                         desc="Location where the BIP will store the results")
    crash_dir = Directory(mandatory=False,
                          desc="Location to store crash files")

    # Execution
    run_using_plugin = Bool(
        False,
        usedefault=True,
        desc="True to run pipeline with plugin, False to run serially")
    plugin = traits.Enum("PBS",
                         "MultiProc",
                         "SGE",
                         "Condor",
                         usedefault=True,
                         desc="plugin to use, if run_using_plugin=True")
    plugin_args = traits.Dict({"qsub_args": "-q many"},
                              usedefault=True,
                              desc='Plugin arguments.')
    test_mode = Bool(
        False,
        mandatory=False,
        usedefault=True,
        desc='Affects whether where and if the workflow keeps its \
                            intermediary files. True to keep intermediary files. '
    )
    timeout = traits.Float(14.0)
    # Subjects
    """
    subjects = traits.List(traits.Str, mandatory=True, usedefault=True,
                          desc="Subject id's. Note: These MUST match the subject id's in the \
                                Freesurfer directory. For simplicity, the subject id's should \
                                also match with the location of individual functional files.")
    fwhm=traits.List(traits.Float())
    inputs_template = traits.String('%s/preproc/output/fwhm_%s/*.nii.gz')
    meanfunc_template = traits.String('%s/preproc/mean/*_mean.nii.gz')
    fsl_mat_template = traits.String('%s/preproc/bbreg/*.mat')
    unwarped_brain_template = traits.String('%s/smri/unwarped_brain/*.nii*')
    affine_transformation_template = traits.String('%s/smri/affine_transformation/*.nii*')
    warp_field_template = traits.String('%s/smri/warped_field/*.nii*')"""
    datagrabber = traits.Instance(Data, ())

    #Normalization
    norm_template = traits.File(mandatory=True, desc='Template to warp to')
    do_segment = traits.Bool(True)
    surf_dir = traits.Directory()
    # Advanced Options
    use_advanced_options = traits.Bool()
    advanced_script = traits.Code()

    # Buttons
    check_func_datagrabber = Button("Check")

    def _check_func_datagrabber_fired(self):
        subs = self.subjects
        template = [
            self.inputs_template, self.meanfunc_template,
            self.fsl_mat_template, self.unwarped_brain_template,
            self.affine_transformation_template, self.warp_field_template
        ]
        for s in subs:
            for t in template:
                try:
                    temp = glob(os.path.join(self.base_dir, t % s))
                except TypeError:
                    temp = []
                    for f in self.fwhm:
                        temp.append(
                            glob(os.path.join(self.base_dir, t % (s, f))))
                print temp
class config(HasTraits):
    uuid = traits.Str(desc="UUID")

    # Directories
    working_dir = Directory(mandatory=True,
                            desc="Location of the Nipype working directory")
    base_dir = Directory(
        os.path.abspath('.'),
        mandatory=True,
        desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(mandatory=True,
                         desc="Location where the BIP will store the results")
    crash_dir = Directory(mandatory=False,
                          desc="Location to store crash files")
    surf_dir = Directory(
        desc="freesurfer directory. subject id's should be the same")

    # Execution
    run_using_plugin = Bool(
        False,
        usedefault=True,
        desc="True to run pipeline with plugin, False to run serially")
    plugin = traits.Enum("PBS",
                         "MultiProc",
                         "SGE",
                         "Condor",
                         usedefault=True,
                         desc="plugin to use, if run_using_plugin=True")
    plugin_args = traits.Dict({"qsub_args": "-q many"},
                              usedefault=True,
                              desc='Plugin arguments.')
    test_mode = Bool(
        False,
        mandatory=False,
        usedefault=True,
        desc='Affects whether where and if the workflow keeps its \
                            intermediary files. True to keep intermediary files. '
    )
    # Data
    subject_id = traits.String()
    contrast = traits.File()
    mask_contrast = traits.File()
    use_contrast_mask = traits.Bool(True)
    reg_file = traits.File()
    mean_image = traits.File()
    background_thresh = traits.Float(0.5)
    roi = traits.List(
        ['superiortemporal', 'bankssts'],
        traits.Enum('superiortemporal', 'bankssts', 'caudalanteriorcingulate',
                    'caudalmiddlefrontal', 'corpuscallosum', 'cuneus',
                    'entorhinal', 'fusiform', 'inferiorparietal',
                    'inferiortemporal', 'isthmuscingulate', 'lateraloccipital',
                    'lateralorbitofrontal', 'lingual', 'medialorbitofrontal',
                    'middletemporal', 'parahippocampal', 'paracentral',
                    'parsopercularis', 'parsorbitalis', 'parstriangularis',
                    'pericalcarine', 'postcentral', 'posteriorcingulate',
                    'precentral', 'precuneus', 'rostralanteriorcingulate',
                    'rostralmiddlefrontal', 'superiorfrontal',
                    'superiorparietal', 'supramarginal', 'frontalpole',
                    'temporalpole', 'transversetemporal', 'insula'),
        usedefault=True)  #35 freesurfer regions,
    thresh = traits.Float(1.5)
class PlotFrame(ta.HasTraits):
    # key_list = range(1,21)
    # this_key = ta.Enum(key_list)
    output_file = ta.Str('')
    this_data_type = ta.Enum(['data', 'fit_parameters'])
    transpose_table = ta.Bool(False)
    include_chi = ta.Bool(True)
    fmt_latex = ta.Bool(True)
    Load = ta.Button()
    Show = ta.Button()
    Show_latex = ta.Button()
    Apply = ta.Button()
    #
    view = tua.View(tua.Item('output_file'),
                    tua.Item('this_data_type'),
                    tua.Item('transpose_table'),
                    tua.Item('include_chi'),
                    tua.Item('fmt_latex'),
                    tua.Item('Load', show_label=False),
                    tua.Item('Show', show_label=False),
                    tua.Item('Show_latex', show_label=False),
                    tua.Item('Apply', show_label=False),
                    buttons=['OK'],
                    resizable=True)

    #
    def _Load_fired(self):
        global xml_data
        if xml_data is None:
            raise EnvironmentError('plot data has not been loaded')
        # self.key_list = xml_data.plot_data.keys()
        self.output_file = xml_data['Results']['save_file']

    def _Show_fired(self):
        global xml_data
        print(unparse(xml_data, pretty=True))

    def _Show_latex_fired(self):
        global latex_data
        if latex_data is None:
            print('latex data not generated yet')
        else:
            print(latex_data.to_string())

    def _Apply_fired(self):
        global xml_data, latex_data
        this_data = xml_data['Results']
        table_data = pa.DataFrame()
        for cfg_key, cfg_data in this_data.items():
            if cfg_key in [
                    'window_size_x', 'window_size_y', 'Info', 'save_file'
            ]:
                continue
            this_data = pa.Series()
            if self.this_data_type in cfg_data.keys():
                if self.this_data_type == 'fit_parameters' and self.include_chi \
                and 'chi_pow_2_pdf' in cfg_data.keys():
                    this_data[r'$\chi^{2}_{pdf}$'] = '$' + MakeValAndErr(
                        cfg_data['chi_pow_2_pdf']['Avg'],
                        cfg_data['chi_pow_2_pdf']['Std'],
                        Dec=2,
                        latex=self.fmt_latex) + '$'
                for data_key, data_data in cfg_data[
                        self.this_data_type].items():
                    if isinstance(data_data, dict):
                        this_data[data_key] = '$' + MakeValAndErr(
                            data_data['Avg'],
                            data_data['Std'],
                            Dec=2,
                            latex=self.fmt_latex) + '$'
                    else:
                        if isinstance(data_data, (list, tuple, np.ndarray)):
                            if len(data_data) == 2:
                                this_data[data_key] = '$' + MakeValAndErr(
                                    data_data[0],
                                    data_data[1],
                                    Dec=2,
                                    latex=self.fmt_latex) + '$'
                            elif len(data_data) == 1:
                                this_data[data_key] = f'${data_data[0]:.3f}$'
                        else:
                            this_data[data_key] = f'${data_data[0]:.3f}$'
            if len(this_data) > 0:
                table_data[cfg_key] = this_data
        latex_data = table_data
        if self.transpose_table:
            latex_data = latex_data.transpose()
        with open(xml_data['Results']['save_file'], 'w') as f:
            format_output = FormatLatex(latex_data.to_latex(escape=False))
            f.write(format_output)
Beispiel #24
0
class CSVJoiner(tr.HasStrictTraits):
    open_csv_files = tr.Button
    csv_files = tr.List(CSVFile)
    num_of_first_lines_to_show = tr.Range(low=0,
                                          high=10**9,
                                          value=10,
                                          mode='spinner')
    num_of_last_lines_to_show = tr.Range(low=0,
                                         high=10**9,
                                         value=10,
                                         mode='spinner')
    selected = tr.Instance(CSVFile)
    join_csv_files = tr.Button
    accumulate_time = tr.Bool
    files_end_with_empty_line = tr.Bool(True)
    columns_headers = tr.List
    time_column = tr.Enum(values='columns_headers')
    progress = tr.Int

    def _join_csv_files_fired(self):
        output_file_path = self.get_output_file_path()
        with open(output_file_path, 'w') as outfile:
            for csv_file, i in zip(self.csv_files, range(len(self.csv_files))):
                current_line = 1
                num_of_first_lines_to_skip = csv_file.first_lines_to_skip
                num_of_last_lines_to_skip = csv_file.last_lines_to_skip
                last_line_to_write = csv_file.get_lines_number(
                ) - num_of_last_lines_to_skip
                progress_of_a_file = 1.0 / len(self.csv_files)
                initial_progress = i / len(self.csv_files)
                with open(csv_file.path) as opened_csv_file:
                    for line in opened_csv_file:
                        if current_line > num_of_first_lines_to_skip and current_line <= last_line_to_write:
                            outfile.write(line)
                            self.progress = int(
                                (initial_progress + progress_of_a_file *
                                 (current_line / last_line_to_write)) * 100)
                        current_line += 1
                if not self.files_end_with_empty_line:
                    outfile.write('\n')
        self.progress = 100
        dialog = MessageDialog(title='Finished!',
                               message='Files joined successfully, see "' +
                               output_file_path + '"')
        dialog.open()

    def get_output_file_path(self):
        file_path = self.csv_files[0].path
        file_path_without_ext = os.path.splitext(file_path)[0]
        file_ext = os.path.splitext(file_path)[1]
        return file_path_without_ext + '_joined' + file_ext

    def _accumulate_time_changed(self):
        pass

    #         if self.csv_files == []:
    #             return
    #         np.array(pd.read_csv(
    #                     self.file_csv, delimiter=self.delimiter, decimal=self.decimal,
    #                     nrows=1, header=None
    #                 )
    #             )[0]
    #         if self.accumulate_time:
    #             class TimeColumnChooser(tr.HasTraits):
    #                 time_column = tr.Enum(values = 'columns_headers')
    #             chooser = TimeColumnChooser()
    #             chooser.configure_traits(kind='modal')

    def _num_of_first_lines_to_show_changed(self):
        for file in self.csv_files:
            file.num_of_first_lines_to_show = self.num_of_first_lines_to_show

    def _num_of_last_lines_to_show_changed(self):
        for file in self.csv_files:
            file.num_of_last_lines_to_show = self.num_of_last_lines_to_show

    def _open_csv_files_fired(self):
        extensions = ['*.csv', '*.txt']  # handle only one extension...
        wildcard = ';'.join(extensions)
        dialog = pf.FileDialog(title='Select csv files',
                               action='open files',
                               wildcard=wildcard,
                               default_path=os.path.expanduser("~"))
        result = dialog.open()

        csv_files_paths = []
        # Test if the user opened a file to avoid throwing an exception
        # if he doesn't
        if result == pf.OK:
            csv_files_paths = dialog.paths
        else:
            return

        self.csv_files = []
        for file_path in csv_files_paths:
            csv_file = CSVFile(
                path=file_path,
                num_of_first_lines_to_show=self.num_of_first_lines_to_show,
                num_of_last_lines_to_show=self.num_of_last_lines_to_show,
            )
            self.csv_files.append(csv_file)

    # =========================================================================
    # Configuration of the view
    # =========================================================================
    traits_view = ui.View(
        ui.VGroup(
            ui.UItem('open_csv_files', width=150),
            ui.HGroup(ui.Item('num_of_first_lines_to_show'), ui.spring),
            ui.HGroup(ui.Item('num_of_last_lines_to_show'), ui.spring),
            ui.HGroup(
                ui.Item('files_end_with_empty_line'),
                # ui.Item('accumulate_time', enabled_when='False'),
                ui.spring),
            ui.VGroup(
                ui.Item('csv_files',
                        show_label=False,
                        style='custom',
                        editor=ui.ListEditor(use_notebook=True,
                                             deletable=False,
                                             selected='selected',
                                             export='DockWindowShell',
                                             page_name='.name'))),
            ui.HGroup(
                ui.UItem('join_csv_files', width=150),
                ui.UItem('progress', editor=ProgressEditor(min=0, max=100))),
            show_border=True),
        title='CSV files joiner',
        resizable=True,
        width=0.6,
        height=0.7)
Beispiel #25
0
class Fit(traits.HasTraits):

    name = traits.Str(desc="name of fit")
    function = traits.Str(desc="function we are fitting with all parameters")
    variablesList = traits.List(Parameter)
    calculatedParametersList = traits.List(CalculatedParameter)
    xs = None  # will be a scipy array
    ys = None  # will be a scipy array
    zs = None  # will be a scipy array
    performFitButton = traits.Button("Perform Fit")
    getInitialParametersButton = traits.Button("Guess Initial Values")
    usePreviousFitValuesButton = traits.Button("Use Previous Fit")
    drawRequestButton = traits.Button("Draw Fit")
    setSizeButton = traits.Button("Set Initial Size")
    chooseVariablesButtons = traits.Button("choose logged variables")
    logAllVariables = traits.Bool(True)
    logLibrarianButton = traits.Button("librarian")
    logLastFitButton = traits.Button("log current fit")
    removeLastFitButton = traits.Button("remove last fit")
    autoFitBool = traits.Bool(
        False,
        desc=
        "Automatically perform this Fit with current settings whenever a new image is loaded"
    )
    autoDrawBool = traits.Bool(
        True,
        desc=
        "Once a fit is complete update the drawing of the fit or draw the fit for the first time"
    )
    autoGuessBool = traits.Bool(False,
                                desc="Perform a new guess before fitting")
    autoSizeBool = traits.Bool(
        False,
        desc=
        "If TOF variable is read from latest XML and is equal to 0.11ms (or time set in Physics) then it will automatically update the physics sizex and sizey with the Sigma x and sigma y from the gaussian fit"
    )
    autoPreviousBool = traits.Bool(
        False,
        desc=
        "Whenever a fit is completed replace the guess values with the calculated values (useful for increasing speed of the next fit)"
    )
    logBool = traits.Bool(
        False, desc="Log the calculated and fitted values with a timestamp")
    logName = traits.String(
        desc="name of the scan - will be used in the folder name")
    logToNas = traits.Bool(
        True, desc="If true, log goes to Humphry-NAS instead of ursa")
    ##    logDirectory = os.path.join("\\\\ursa","AQOGroupFolder","Experiment Humphry","Data","eagleLogs")
    logDirectory = os.path.join("G:", os.sep, "Experiment Humphry", "Data",
                                "eagleLogs")
    logDirectoryNas = os.path.join("\\\\192.168.16.71", "Humphry", "Data",
                                   "eagleLogs")
    latestSequence = os.path.join("\\\\ursa", "AQOGroupFolder",
                                  "Experiment Humphry",
                                  "Experiment Control And Software",
                                  "currentSequence", "latestSequence.xml")
    conditionalFitBool = traits.Bool(
        False,
        desc=
        "If true, fit is only executed, if current sequence contains matching variable 'eagleID'"
    )
    conditionalFitID = traits.Int(0)

    logFile = traits.File(desc="file path of logFile")

    logAnalyserBool = traits.Bool(
        False, desc="only use log analyser script when True")
    logAnalysers = [
    ]  #list containing full paths to each logAnalyser file to run
    logAnalyserDisplayString = traits.String(
        desc=
        "comma separated read only string that is a list of all logAnalyser python scripts to run. Use button to choose files"
    )
    logAnalyserSelectButton = traits.Button("sel. analyser",
                                            image='@icons:function_node',
                                            style="toolbar")
    xmlLogVariables = []
    imageInspectorReference = None  #will be a reference to the image inspector
    fitting = traits.Bool(False)  #true when performing fit
    fitted = traits.Bool(
        False)  #true when current data displayed has been fitted
    fitSubSpace = traits.Bool(True)
    drawSubSpace = traits.Bool(True)
    startX = traits.Int(230)
    startY = traits.Int(230)
    endX = traits.Int(550)
    endY = traits.Int(430)
    fittingStatus = traits.Str()
    fitThread = None
    fitTimeLimit = traits.Float(
        10.0,
        desc=
        "Time limit in seconds for fitting function. Only has an effect when fitTimeLimitBool is True"
    )
    fitTimeLimitBool = traits.Bool(
        True,
        desc=
        "If True then fitting functions will be limited to time limit defined by fitTimeLimit "
    )
    physics = traits.Instance(
        physicsProperties.physicsProperties.PhysicsProperties)
    #status strings
    notFittedForCurrentStatus = "Not Fitted for Current Image"
    fittedForCurrentImageStatus = "Fit Complete for Current Image"
    currentlyFittingStatus = "Currently Fitting..."
    failedFitStatus = "Failed to finish fit. See logger"
    timeExceededStatus = "Fit exceeded user time limit"

    lmfitModel = traits.Instance(
        lmfit.Model
    )  #reference to the lmfit model  must be initialised in subclass
    mostRecentModelResult = None  # updated to the most recent ModelResult object from lmfit when a fit thread is performed

    fitSubSpaceGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("fitSubSpace", label="Fit Sub Space",
                          resizable=True), traitsui.Item("drawSubSpace")),
        traitsui.VGroup(traitsui.HGroup(
            traitsui.Item("startX", resizable=True),
            traitsui.Item("startY", resizable=True)),
                        traitsui.HGroup(traitsui.Item("endX", resizable=True),
                                        traitsui.Item("endY", resizable=True)),
                        visible_when="fitSubSpace"),
        label="Fit Sub Space",
        show_border=True)

    generalGroup = traitsui.VGroup(traitsui.Item("name",
                                                 label="Fit Name",
                                                 style="readonly",
                                                 resizable=True),
                                   traitsui.Item("function",
                                                 label="Fit Function",
                                                 style="readonly",
                                                 resizable=True),
                                   fitSubSpaceGroup,
                                   label="Fit",
                                   show_border=True)

    variablesGroup = traitsui.VGroup(traitsui.Item(
        "variablesList",
        editor=traitsui.ListEditor(style="custom"),
        show_label=False,
        resizable=True),
                                     show_border=True,
                                     label="parameters")

    derivedGroup = traitsui.VGroup(traitsui.Item(
        "calculatedParametersList",
        editor=traitsui.ListEditor(style="custom"),
        show_label=False,
        resizable=True),
                                   show_border=True,
                                   label="derived values")

    buttons = traitsui.HGroup(
        traitsui.VGroup(traitsui.HGroup(
            traitsui.Item("autoFitBool", label="Auto fit?", resizable=True),
            traitsui.Item("performFitButton", show_label=False,
                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("autoGuessBool",
                                          label="Auto guess?",
                                          resizable=True),
                            traitsui.Item("getInitialParametersButton",
                                          show_label=False,
                                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("autoPreviousBool",
                                          label="Auto previous?",
                                          resizable=True),
                            traitsui.Item("usePreviousFitValuesButton",
                                          show_label=False,
                                          resizable=True)),
                        show_border=True),
        traitsui.VGroup(traitsui.HGroup(
            traitsui.Item("autoDrawBool", label="Auto draw?", resizable=True),
            traitsui.Item("drawRequestButton",
                          show_label=False,
                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("autoSizeBool",
                                          label="Auto size?",
                                          resizable=True),
                            traitsui.Item("setSizeButton",
                                          show_label=False,
                                          resizable=True)),
                        traitsui.HGroup(
                            traitsui.Item("conditionalFitBool",
                                          label="Conditional Fit?",
                                          resizable=True),
                            traitsui.Item("conditionalFitID",
                                          label="Fit ID",
                                          resizable=True)),
                        show_border=True))

    logGroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.Item("logBool", resizable=True),
            traitsui.Item("logAllVariables", resizable=True),
            traitsui.Item("chooseVariablesButtons",
                          show_label=False,
                          resizable=True,
                          enabled_when="not logAllVariables")),
        traitsui.HGroup(traitsui.Item("logName", resizable=True)),
        traitsui.HGroup(traitsui.Item("logToNas", resizable=True)),  #changed
        traitsui.HGroup(
            traitsui.Item("removeLastFitButton",
                          show_label=False,
                          resizable=True),
            traitsui.Item("logLastFitButton", show_label=False,
                          resizable=True)),
        traitsui.HGroup(
            traitsui.Item("logAnalyserBool", label="analyser?",
                          resizable=True),
            traitsui.Item("logAnalyserDisplayString",
                          show_label=False,
                          style="readonly",
                          resizable=True),
            traitsui.Item("logAnalyserSelectButton",
                          show_label=False,
                          resizable=True)),
        label="Logging",
        show_border=True)

    actionsGroup = traitsui.VGroup(traitsui.Item("fittingStatus",
                                                 style="readonly",
                                                 resizable=True),
                                   logGroup,
                                   buttons,
                                   label="Fit Actions",
                                   show_border=True)
    traits_view = traitsui.View(traitsui.VGroup(generalGroup, variablesGroup,
                                                derivedGroup, actionsGroup),
                                kind="subpanel")

    def __init__(self, **traitsDict):
        super(Fit, self).__init__(**traitsDict)
        # self.startX = 0
        # self.startY = 0
        self.lmfitModel = lmfit.Model(self.fitFunc)

        # load config
        with open(configFile, 'r') as f:
            settings = json.load(f)
            if 'logAnalysers' in settings:
                self.logAnalysers = settings['logAnalysers']
                self.logAnalyserDisplayString = str(
                    [os.path.split(path)[1] for path in self.logAnalysers])
            if 'logAnalyserBool' in settings:
                self.logAnalyserBool = settings['logAnalyserBool']

    def _set_xs(self, xs):
        self.xs = xs

    def _set_ys(self, ys):
        self.ys = ys

    def _set_zs(self, zs):
        self.zs = zs

    def _fittingStatus_default(self):
        return self.notFittedForCurrentStatus

    def _getInitialValues(self):
        """returns ordered list of initial values from variables List """
        return [_.initialValue for _ in self.variablesList]

    def _getParameters(self):
        """creates an lmfit parameters object based on the user input in variablesList """
        return lmfit.Parameters(
            {_.name: _.parameter
             for _ in self.variablesList})

    def _getCalculatedValues(self):
        """returns ordered list of fitted values from variables List """
        return [_.calculatedValue for _ in self.variablesList]

    def _intelligentInitialValues(self):
        """If possible we can auto set the initial parameters to intelligent guesses user can always overwrite them """
        self._setInitialValues(self._getIntelligentInitialValues())

    def _get_subSpaceArrays(self):
        """returns the arrays of the selected sub space. If subspace is not
        activated then returns the full arrays"""
        if self.fitSubSpace:
            xs = self.xs[self.startX:self.endX]
            ys = self.ys[self.startY:self.endY]
            logger.info("xs array sliced length %s " % (xs.shape))
            logger.info("ys array sliced length %s  " % (ys.shape))
            zs = self.zs[self.startY:self.endY, self.startX:self.endX]
            logger.info("zs sub space array %s,%s " % (zs.shape))

            return xs, ys, zs
        else:
            return self.xs, self.ys, self.zs

    def _getIntelligentInitialValues(self):
        """If possible we can auto set the initial parameters to intelligent guesses user can always overwrite them """
        logger.warning("Dummy function should not be called directly")
        return
        #in python this should be a pass statement. I.e. user has to overwrite this

    def fitFunc(self, data, *p):
        """Function that we are trying to fit to. """
        logger.error("Dummy function should not be called directly")
        return
        #in python this should be a pass statement. I.e. user has to overwrite this

    def _setCalculatedValues(self, modelFitResult):
        """updates calculated values with calculated argument """
        parametersResult = modelFitResult.params
        for variable in self.variablesList:
            variable.calculatedValue = parametersResult[variable.name].value

    def _setCalculatedValuesErrors(self, modelFitResult):
        """given the covariance matrix returned by scipy optimize fit
        convert this into stdeviation errors for parameters list and updated
        the stdevError attribute of variables"""
        parametersResult = modelFitResult.params
        for variable in self.variablesList:
            variable.stdevError = parametersResult[variable.name].stderr

    def _setInitialValues(self, guesses):
        """updates calculated values with calculated argument """
        c = 0
        for variable in self.variablesList:
            variable.initialValue = guesses[c]
            c += 1

    def deriveCalculatedParameters(self):
        """Wrapper for subclass definition of deriving calculated parameters
        can put more general calls in here"""
        if self.fitted:
            self._deriveCalculatedParameters()

    def _deriveCalculatedParameters(self):
        """Should be implemented by subclass. should update all variables in calculate parameters list"""
        logger.error("Should only be called by subclass")
        return

    def _fit_routine(self):
        """This function performs the fit in an appropriate thread and 
        updates necessary values when the fit has been performed"""
        self.fitting = True
        if self.fitThread and self.fitThread.isAlive():
            logger.warning(
                "Fitting is already running. You should wait till this fit has timed out before a new thread is started...."
            )
            #logger.warning("I will start a new fitting thread but your previous thread may finish at some undetermined time. you probably had bad starting conditions :( !")
            return
        self.fitThread = FitThread()  #new fitting thread
        self.fitThread.fitReference = self
        self.fitThread.isCurrentFitThread = True  # user can create multiple fit threads on a particular fit but only the latest one will have an effect in the GUI
        self.fitThread.start()
        self.fittingStatus = self.currentlyFittingStatus

    def _perform_fit(self):
        """Perform the fit using scipy optimise curve fit.
        We must supply x and y as one argument and zs as anothger. in the form
        xs: 0 1 2 0 1 2 0 
        ys: 0 0 0 1 1 1 2
        zs: 1 5 6 1 9 8 2
        Hence the use of repeat and tile in  positions and unravel for zs
        initially xs,ys is a linspace array and zs is a 2d image array
        """
        if self.xs is None or self.ys is None or self.zs is None:
            logger.warning(
                "attempted to fit data but had no data inside the Fit object. set xs,ys,zs first"
            )
            return ([], [])
        params = self._getParameters()
        if self.fitSubSpace:  #fit only the sub space
            #create xs, ys and zs which are appropriate slices of the arrays
            xs, ys, zs = self._get_subSpaceArrays()
        else:  #fit the whole array of data (slower)
            xs, ys, zs = self.xs, self.ys, self.zs
        positions = scipy.array([
            scipy.tile(xs, len(ys)),
            scipy.repeat(ys, len(xs))
        ])  #for creating data necessary for gauss2D function
        if self.fitTimeLimitBool:
            modelFitResult = self.lmfitModel.fit(scipy.ravel(zs),
                                                 positions=positions,
                                                 params=params,
                                                 iter_cb=self.getFitCallback(
                                                     time.time()))
        else:  #no iter callback
            modelFitResult = self.lmfitModel.fit(scipy.ravel(zs),
                                                 positions=positions,
                                                 params=params)
        return modelFitResult

    def getFitCallback(self, startTime):
        """returns the callback function that is called at every iteration of fit to check if it 
        has been running too long"""
        def fitCallback(params, iter, resid, *args, **kws):
            """check the time and compare to start time """
            if time.time() - startTime > self.fitTimeLimit:
                raise FitException("Fit time exceeded user limit")

        return fitCallback

    def _performFitButton_fired(self):
        self._fit_routine()

    def _getInitialParametersButton_fired(self):
        self._intelligentInitialValues()

    def _drawRequestButton_fired(self):
        """tells the imageInspector to try and draw this fit as an overlay contour plot"""
        self.imageInspectorReference.addFitPlot(self)

    def _setSizeButton_fired(self):
        """use the sigmaX and sigmaY from the current fit to overwrite the 
        inTrapSizeX and inTrapSizeY parameters in the Physics Instance"""
        self.physics.inTrapSizeX = abs(self.sigmax.calculatedValue)
        self.physics.inTrapSizeY = abs(self.sigmay.calculatedValue)

    def _getFitFuncData(self):
        """if data has been fitted, this returns the zs data for the ideal
        fitted function using the calculated paramters"""
        positions = [
            scipy.tile(self.xs, len(self.ys)),
            scipy.repeat(self.ys, len(self.xs))
        ]  #for creating data necessary for gauss2D function
        zsravelled = self.fitFunc(positions, *self._getCalculatedValues())
        return zsravelled.reshape(self.zs.shape)

    def _logAnalyserSelectButton_fired(self):
        """open a fast file editor for selecting many files """
        fileDialog = FileDialog(action="open files")
        fileDialog.open()
        if fileDialog.return_code == pyface.constant.OK:
            self.logAnalysers = fileDialog.paths
            logger.info("selected log analysers: %s " % self.logAnalysers)
        self.logAnalyserDisplayString = str(
            [os.path.split(path)[1] for path in self.logAnalysers])

    def runSingleAnalyser(self, module):
        """runs the logAnalyser module calling the run function and returns the 
        columnNames and values as a list"""
        exec("import logAnalysers.%s as currentAnalyser" % module)
        reload(
            currentAnalyser
        )  #in case it has changed..#could make this only when user requests
        #now the array also contains the raw image as this may be different to zs if you are using a processor
        if hasattr(self.imageInspectorReference, "rawImage"):
            rawImage = self.imageInspectorReference.rawImage
        else:
            rawImage = None
        return currentAnalyser.run([self.xs, self.ys, self.zs, rawImage],
                                   self.physics.variables, self.variablesList,
                                   self.calculatedParametersList)

    def runAnalyser(self):
        """ if logAnalyserBool is true we perform runAnalyser at the end of _log_fit
        runAnalyser checks that logAnalyser exists and is a python script with a valid run()function
        it then performs the run method and passes to the run function:
        -the image data as a numpy array
        -the xml variables dictionary
        -the fitted paramaters
        -the derived values"""
        for logAnalyser in self.logAnalysers:
            if not os.path.isfile(logAnalyser):
                logger.error(
                    "attempted to runAnalyser but could not find the logAnalyser File: %s"
                    % logAnalyser)
                return
        #these will contain the final column names and values
        finalColumns = []
        finalValues = []
        #iterate over each selected logAnalyser get the column names and values and add them to the master lists
        for logAnalyser in self.logAnalysers:
            directory, module = os.path.split(logAnalyser)
            module, ext = os.path.splitext(module)
            if ext != ".py":
                logger.error("file was not a python module. %s" % logAnalyser)
            else:
                columns, values = self.runSingleAnalyser(module)
                finalColumns.extend(columns)
                finalValues.extend(values)
        return finalColumns, finalValues

    def mostRecentModelFitReport(self):
        """returns the lmfit fit report of the most recent 
        lmfit model results object"""
        if self.mostRecentModelResult is not None:
            return lmfit.fit_report(self.mostRecentModelResult) + "\n\n"
        else:
            return "No fit performed"

    def getCalculatedParameters(self):
        """useful for print returns tuple list of calculated parameter name and value """
        return [(_.name, _.value) for _ in self.calculatedParametersList]

    def _log_fit(self):

        if self.logName == "":
            logger.warning("no log file defined. Will not log")
            return
        #generate folders if they don't exist
        if self.logToNas is not True:
            logFolder = os.path.join(self.logDirectory, self.logName)
        else:
            logFolder = os.path.join(self.logDirectoryNas, self.logName)
        if not os.path.isdir(logFolder):
            logger.info("creating a new log folder %s" % logFolder)
            os.mkdir(logFolder)

        imagesFolder = os.path.join(logFolder, "images")
        if not os.path.isdir(imagesFolder):
            logger.info("creating a new images Folder %s" % imagesFolder)
            os.mkdir(imagesFolder)

        commentsFile = os.path.join(logFolder, "comments.txt")
        if not os.path.exists(commentsFile):
            logger.info("creating a comments file %s" % commentsFile)
            open(commentsFile,
                 "a+").close()  #create a comments file in every folder!

        firstSequenceCopy = os.path.join(logFolder,
                                         "copyOfInitialSequence.ctr")
        if not os.path.exists(firstSequenceCopy):
            logger.info("creating a copy of the first sequence %s -> %s" %
                        (self.latestSequence, firstSequenceCopy))
            shutil.copy(self.latestSequence, firstSequenceCopy)

        if self.imageInspectorReference.model.imageMode == "process raw image":  #if we are using a processor, save the details of the processor used to the log folder
            processorParamtersFile = os.path.join(logFolder,
                                                  "processorOptions.txt")
            processorPythonScript = os.path.join(logFolder,
                                                 "usedProcessor.py")  #TODO!
            if not os.path.exists(processorParamtersFile):
                with open(processorParamtersFile, "a+") as processorParamsFile:
                    string = str(self.imageInspectorReference.model.
                                 chosenProcessor) + "\n"
                    string += str(self.imageInspectorReference.model.processor.
                                  optionsDict)
                    processorParamsFile.write(string)

        logger.debug("finished all checks on log folder")
        #copy current image
        try:
            shutil.copy(self.imageInspectorReference.selectedFile,
                        imagesFolder)
            if self.imageInspectorReference.selectedFile.endswith("_X2.tif"):
                shutil.copy(
                    self.imageInspectorReference.selectedFile.replace(
                        "_X2.tif", "_X1.tif"), imagesFolder)
        except IOError as e:
            logger.error("Could not copy image. Got IOError: %s " % e.message)
        except Exception as e:
            logger.error("Could not copy image. Got %s: %s " %
                         (type(e), e.message))
            raise e
        logger.info("copying current image")
        self.logFile = os.path.join(logFolder, self.logName + ".csv")

        #analyser logic
        if self.logAnalyserBool:  #run the analyser script as requested
            logger.info(
                "log analyser bool enabled... will attempt to run analyser script"
            )
            analyserResult = self.runAnalyser()
            logger.info("analyser result = %s " % list(analyserResult))
            if analyserResult is None:
                analyserColumnNames = []
                analyserValues = []
                #analyser failed. continue as if nothing happened
            else:
                analyserColumnNames, analyserValues = analyserResult
        else:  #no analyser enabled
            analyserColumnNames = []
            analyserValues = []

        if not os.path.exists(self.logFile):
            variables = [_.name for _ in self.variablesList]
            calculated = [_.name for _ in self.calculatedParametersList]
            times = ["datetime", "epoch seconds"]
            info = ["img file name"]
            xmlVariables = self.getXmlVariables()
            columnNames = times + info + variables + calculated + xmlVariables + analyserColumnNames
            with open(
                    self.logFile, 'ab+'
            ) as logFile:  # note use of binary file so that windows doesn't write too many /r
                writer = csv.writer(logFile)
                writer.writerow(columnNames)
        #column names already exist so...
        logger.debug("copying current image")
        variables = [_.calculatedValue for _ in self.variablesList]
        calculated = [_.value for _ in self.calculatedParametersList]
        now = time.time()  #epoch seconds
        timeTuple = time.localtime(now)
        date = time.strftime("%Y-%m-%dT%H:%M:%S", timeTuple)
        times = [date, now]
        info = [self.imageInspectorReference.selectedFile]
        xmlVariables = [
            self.physics.variables[varName]
            for varName in self.getXmlVariables()
        ]
        data = times + info + variables + calculated + xmlVariables + analyserValues

        with open(self.logFile, 'ab+') as logFile:
            writer = csv.writer(logFile)
            writer.writerow(data)

    def _logLastFitButton_fired(self):
        """logs the fit. User can use this for non automated logging. i.e. log
        particular fits"""
        self._log_fit()

    def _removeLastFitButton_fired(self):
        """removes the last line in the log file """
        logFolder = os.path.join(self.logDirectory, self.logName)
        self.logFile = os.path.join(logFolder, self.logName + ".csv")
        if self.logFile == "":
            logger.warning("no log file defined. Will not log")
            return
        if not os.path.exists(self.logFile):
            logger.error(
                "cant remove a line from a log file that doesn't exist")
        with open(self.logFile, 'r') as logFile:
            lines = logFile.readlines()
        with open(self.logFile, 'wb') as logFile:
            logFile.writelines(lines[:-1])

    def saveLastFit(self):
        """saves result of last fit to a txt/csv file. This can be useful for live analysis
        or for generating sequences based on result of last fit"""
        try:
            with open(
                    self.imageInspectorReference.cameraModel + "-" +
                    self.physics.species + "-" + "lastFit.csv",
                    "wb") as lastFitFile:
                writer = csv.writer(lastFitFile)
                writer.writerow(["time", time.time()])
                for variable in self.variablesList:
                    writer.writerow([variable.name, variable.calculatedValue])
                for variable in self.calculatedParametersList:
                    writer.writerow([variable.name, variable.value])
        except Exception as e:
            logger.error("failed to save last fit to text file. message %s " %
                         e.message)

    def _chooseVariablesButtons_fired(self):
        self.xmlLogVariables = self.chooseVariables()

    def _usePreviousFitValuesButton_fired(self):
        """update the guess initial values with the value from the last fit """
        logger.info(
            "use previous fit values button fired. loading previous initial values"
        )
        self._setInitialValues(self._getCalculatedValues())

    def getXmlVariables(self):
        if self.logAllVariables:
            return sorted(self.physics.variables.keys())
        else:
            return self.xmlLogVariables

    def chooseVariables(self):
        """Opens a dialog asking user to select columns from a data File that has
        been selected. THese are then returned as a string suitable for Y cols input"""
        columns = self.physics.variables.keys()
        columns.sort()
        values = zip(range(0, len(columns)), columns)

        checklist_group = traitsui.Group(
            '10',  # insert vertical space
            traitsui.Label('Select the additional variables you wish to log'),
            traitsui.UItem('columns',
                           style='custom',
                           editor=traitsui.CheckListEditor(values=values,
                                                           cols=6)),
            traitsui.UItem('selectAllButton'))

        traits_view = traitsui.View(checklist_group,
                                    title='CheckListEditor',
                                    buttons=['OK'],
                                    resizable=True,
                                    kind='livemodal')

        col = ColumnEditor(numberOfColumns=len(columns))
        try:
            col.columns = [
                columns.index(varName) for varName in self.xmlLogVariables
            ]
        except Exception as e:
            logger.error(
                "couldn't selected correct variable names. Returning empty selection"
            )
            logger.error("%s " % e.message)
            col.columns = []
        col.edit_traits(view=traits_view)
        logger.debug("value of columns selected = %s ", col.columns)
        logger.debug("value of columns selected = %s ",
                     [columns[i] for i in col.columns])
        return [columns[i] for i in col.columns]

    def _logLibrarianButton_fired(self):
        """opens log librarian for current folder in logName box. """
        logFolder = os.path.join(self.logDirectory, self.logName)
        if not os.path.isdir(logFolder):
            logger.error(
                "cant open librarian on a log that doesn't exist.... Could not find %s"
                % logFolder)
            return
        librarian = plotObjects.logLibrarian.Librarian(logFolder=logFolder)
        librarian.edit_traits()

    def _drawSubSpace_changed(self):
        newVisibility = self.drawSubSpace and self.fitSubSpace
        self.imageInspectorReference.ROIPolyPlot.visible = newVisibility
        self._startX_changed()  # update ROI data for plot

    def _fitSubSpace_changed(self):
        self._drawSubSpace_changed()

    def _startX_changed(self):
        if self.imageInspectorReference is None:
            return  # not yet initialized yet
        self.imageInspectorReference.ROIPolyPlot.index = chaco.ArrayDataSource(
            [self.startX, self.endX, self.endX, self.startX])
        self.imageInspectorReference.ROIPolyPlot.value = chaco.ArrayDataSource(
            [self.startY, self.startY, self.endY, self.endY])

    _endX_changed = _startX_changed
    _startY_changed = _startX_changed
    _endY_changed = _startX_changed
class config(HasTraits):
    uuid = traits.Str(desc="UUID")
    desc = traits.Str(desc='Workflow description')
    # Directories
    working_dir = Directory(mandatory=True, desc="Location of the Nipype working directory")
    base_dir = Directory(os.path.abspath('.'),mandatory=True, desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(os.path.abspath('.'),mandatory=True, desc="Location where the BIP will store the results")
    field_dir = Directory(desc="Base directory of field-map data (Should be subject-independent) \
                                                 Set this value to None if you don't want fieldmap distortion correction")
    crash_dir = Directory(mandatory=False, desc="Location to store crash files")
    json_sink = Directory(mandatory=False, desc= "Location to store json_files")
    surf_dir = Directory(mandatory=True, desc= "Freesurfer subjects directory")

    # Execution

    run_using_plugin = Bool(False, usedefault=True, desc="True to run pipeline with plugin, False to run serially")
    plugin = traits.Enum("PBS", "PBSGraph","MultiProc", "SGE", "Condor",
        usedefault=True,
        desc="plugin to use, if run_using_plugin=True")
    plugin_args = traits.Dict({"qsub_args": "-q many"},
        usedefault=True, desc='Plugin arguments.')
    test_mode = Bool(False, mandatory=False, usedefault=True,
        desc='Affects whether where and if the workflow keeps its \
                            intermediary files. True to keep intermediary files. ')
    # Subjects

    subjects= traits.List(traits.Str, mandatory=True, usedefault=True,
        desc="Subject id's. Note: These MUST match the subject id's in the \
                                Freesurfer directory. For simplicity, the subject id's should \
                                also match with the location of individual functional files.")
    dwi_template = traits.String('%s/functional.nii.gz')
    bval_template = traits.String('%s/bval')
    bvec_template = traits.String('%s/fbvec')
    run_datagrabber_without_submitting = traits.Bool(desc="Run the datagrabber without \
    submitting to the cluster")
    timepoints_to_remove = traits.Int(0,usedefault=True)

    # Fieldmap

    use_fieldmap = Bool(False, mandatory=False, usedefault=True,
        desc='True to include fieldmap distortion correction. Note: field_dir \
                                     must be specified')
    magnitude_template = traits.String('%s/magnitude.nii.gz')
    phase_template = traits.String('%s/phase.nii.gz')
    TE_diff = traits.Float(desc='difference in B0 field map TEs')
    sigma = traits.Int(2, desc='2D spatial gaussing smoothing stdev (default = 2mm)')
    echospacing = traits.Float(desc="EPI echo spacing")

    # Bvecs
    do_rotate_bvecs = traits.Bool(True, usedefault=True)

    # Advanced Options
    use_advanced_options = traits.Bool()
    advanced_script = traits.Code()

    # Buttons
    check_func_datagrabber = Button("Check")
    check_field_datagrabber = Button("Check")

    def _check_func_datagrabber_fired(self):
        subs = self.subjects

        for s in subs:
            if not os.path.exists(os.path.join(self.base_dir,self.dwi_template % s)):
                print "ERROR", os.path.join(self.base_dir,self.dwi_template % s), "does NOT exist!"
                break
            else:
                print os.path.join(self.base_dir,self.dwi_template % s), "exists!"

    def _check_field_datagrabber_fired(self):
        subs = self.subjects

        for s in subs:
            if not os.path.exists(os.path.join(self.field_dir,self.magnitude_template % s)):
                print "ERROR:", os.path.join(self.field_dir,self.magnitude_template % s), "does NOT exist!"
                break
            else:
                print os.path.join(self.base_dir,self.magnitude_template % s), "exists!"
            if not os.path.exists(os.path.join(self.field_dir,self.phase_template % s)):
                print "ERROR:", os.path.join(self.field_dir,self.phase_template % s), "does NOT exist!"
                break
            else:
                print os.path.join(self.base_dir,self.phase_template % s), "exists!"
class config(HasTraits):
    uuid = traits.Str(desc="UUID")

    # Directories
    working_dir = Directory(mandatory=True,
                            desc="Location of the Nipype working directory")
    base_dir = Directory(
        os.path.abspath('.'),
        mandatory=True,
        desc='Base directory of data. (Should be subject-independent)')
    sink_dir = Directory(mandatory=True,
                         desc="Location where the BIP will store the results")
    crash_dir = Directory(mandatory=False,
                          desc="Location to store crash files")
    surf_dir = Directory(
        desc="freesurfer directory. subject id's should be the same")

    # Execution
    run_using_plugin = Bool(
        False,
        usedefault=True,
        desc="True to run pipeline with plugin, False to run serially")
    plugin = traits.Enum("PBS",
                         "MultiProc",
                         "SGE",
                         "Condor",
                         usedefault=True,
                         desc="plugin to use, if run_using_plugin=True")
    plugin_args = traits.Dict({"qsub_args": "-q many"},
                              usedefault=True,
                              desc='Plugin arguments.')
    test_mode = Bool(
        False,
        mandatory=False,
        usedefault=True,
        desc='Affects whether where and if the workflow keeps its \
                            intermediary files. True to keep intermediary files. '
    )
    timeout = traits.Float(30.0)
    # DataGrabber
    datagrabber = traits.Instance(Data, ())

    # segstats
    use_reg = traits.Bool(True)
    inverse_reg = traits.Bool(True)
    use_standard_label = traits.Bool(
        False, desc="use same label file for all subjects")
    label_file = traits.File()
    use_annotation = traits.Bool(
        False,
        desc=
        "use same annotation file for all subjects (will warp to subject space"
    )
    use_subject_annotation = traits.Bool(
        False,
        desc="you need to change datragrabber to\
                                           have outputs lh_annotation and rh_annotation"
    )
    annot_space = traits.String("fsaverage5",
                                desc="subject space of annot file")
    lh_annotation = traits.File()
    rh_annotation = traits.File()
    color_table_file = traits.Enum("Default", "Color_Table", "GCA_color_table",
                                   "None")
    color_file = traits.File()
    proj = traits.BaseTuple(("frac", 0, 1, 0.1), traits.Enum("abs", "frac"),
                            traits.Float(), traits.Float(), traits.Float())
    statname = traits.Str('segstats1', desc="description of the segstat")
class HCFT(tr.HasStrictTraits):
    """High-Cycle Fatigue Tool"""
    # =========================================================================
    # Traits definitions
    # =========================================================================
    # Assigning the view
    traits_view = hcft_window

    # CSV import
    decimal = tr.Enum(',', '.')
    delimiter = tr.Str(';')
    file_path = tr.File
    open_file_button = tr.Button('Open file')
    columns_headers = tr.List
    npy_folder_path = tr.Str
    file_name = tr.Str

    # CSV processing
    take_time_from_time_column = tr.Bool(True)
    records_per_second = tr.Float(100)
    time_column = tr.Enum(values='columns_headers')
    skip_first_rows = tr.Range(low=1, high=10**9, value=3, mode='spinner')
    add_columns_average = tr.Button
    columns_to_be_averaged = tr.List
    parse_csv_to_npy = tr.Button

    # Plotting
    x_axis = tr.Enum(values='columns_headers')
    y_axis = tr.Enum(values='columns_headers')
    x_axis_multiplier = tr.Enum(1, -1)
    y_axis_multiplier = tr.Enum(-1, 1)
    add_plot = tr.Button
    apply_filters = tr.Bool
    plot_settings_btn = tr.Button
    plot_settings = PlotSettings()
    plot_settings_active = tr.Bool
    normalize_cycles = tr.Bool
    smooth = tr.Bool
    plot_every_nth_point = tr.Range(low=1, high=1000000, mode='spinner')
    old_peak_force_before_cycles = tr.Float
    peak_force_before_cycles = tr.Float
    add_creep_plot = tr.Button(desc='Creep plot of X axis array')
    clear_plot = tr.Button

    force_column = tr.Enum(values='columns_headers')
    window_length = tr.Range(low=1, high=10**9 - 1, value=31, mode='spinner')
    polynomial_order = tr.Range(low=1, high=10**9, value=2, mode='spinner')
    activate_ascending_branch_smoothing = tr.Bool(False, label='Activate')

    generate_filtered_and_creep_npy = tr.Button
    force_max = tr.Float(100)
    force_min = tr.Float(40)
    min_cycle_force_range = tr.Float(50)
    cutting_method = tr.Enum('Define min cycle range(force difference)',
                             'Define Max, Min')

    log = tr.Str('')
    clear_log = tr.Button

    # =========================================================================
    # Assigning default values
    # =========================================================================
    ax = tr.Any
    figure = tr.Instance(mpl.figure.Figure)

    def _figure_default(self):
        figure = mpl.figure.Figure(facecolor='white')
        figure.set_tight_layout(True)
        self.create_axes(figure)
        return figure

    def create_axes(self, figure):
        self.ax = figure.add_subplot(1, 1, 1)

    # =========================================================================
    # File management
    # =========================================================================
    def _open_file_button_fired(self):
        try:
            self.reset()

            dialog = FileDialog(title='Select text file',
                                action='open',
                                default_path=self.file_path)
            result = dialog.open()

            # Test if the user opened a file to avoid throwing an exception if he doesn't
            if result == OK:
                self.file_path = dialog.path
            else:
                return

            # Populate headers list which fills the x-axis and y-axis with values automatically
            self.columns_headers = get_headers(self.file_path,
                                               decimal=self.decimal,
                                               delimiter=self.delimiter)

            # Saving file name and path and creating NPY folder
            dir_path = os.path.dirname(self.file_path)
            self.npy_folder_path = os.path.join(dir_path, 'NPY')
            if not os.path.exists(self.npy_folder_path):
                os.makedirs(self.npy_folder_path)

            self.file_name = os.path.splitext(os.path.basename(
                self.file_path))[0]

            self.import_data_json()

        except:
            self.log_exception()

    def _add_columns_average_fired(self):
        try:
            columns_average = ColumnsAverage()
            for name in self.columns_headers:
                columns_average.columns.append(Column(column_name=name))

            # kind='modal' pauses the implementation until the window is closed
            columns_average.configure_traits(kind='modal')

            columns_to_be_averaged_temp = []
            for i in columns_average.columns:
                if i.selected:
                    columns_to_be_averaged_temp.append(i.column_name)

            if columns_to_be_averaged_temp:  # If it's not empty
                self.columns_to_be_averaged.append(columns_to_be_averaged_temp)

                avg_file_suffix = self.get_suffix_for_columns_to_be_averaged(
                    columns_to_be_averaged_temp)
                self.columns_headers.append(avg_file_suffix)
        except:
            self.log_exception()

    def _parse_csv_to_npy_fired(self):
        # Run method on different thread so GUI doesn't freeze
        # thread = Thread(target = threaded_function, function_args = (10,))
        thread = Thread(target=self.parse_csv_to_npy_fired)
        thread.start()

    def parse_csv_to_npy_fired(self):
        try:
            self.print_custom('Parsing csv into npy files...')
            self.export_data_json()
            """ Exporting npy arrays of original columns """
            for i in range(
                    len(self.columns_headers) -
                    len(self.columns_to_be_averaged)):
                column_name = self.columns_headers[i]
                # One could provide the path directly to pd.read_csv but in this way we insure that this works also if the
                # path to the file include chars like ü,ä
                # (with) makes sure the file stream is closed after using it
                with open(self.file_path, encoding='utf-8') as file_stream:
                    column_array = np.array(
                        pd.read_csv(file_stream,
                                    delimiter=self.delimiter,
                                    decimal=self.decimal,
                                    skiprows=self.skip_first_rows,
                                    usecols=[i]))

                # TODO detect column name before loading completely to skip loading if the following condition applies
                if column_name == self.time_column and self.take_time_from_time_column is False:
                    column_array = np.arange(
                        start=0.0,
                        stop=len(column_array) / self.records_per_second,
                        step=1.0 / self.records_per_second)

                np.save(self.get_npy_file_path(column_name), column_array)
            """ Exporting npy arrays of averaged columns """
            for columns_names in self.columns_to_be_averaged:
                temp_array = np.zeros((1))
                for column_name in columns_names:
                    temp_array = temp_array + np.load(
                        self.get_npy_file_path(column_name)).flatten()
                avg = temp_array / len(columns_names)

                np.save(self.get_average_npy_file_path(columns_names), avg)

            self.print_custom('Finished parsing csv into npy files.')
        except:
            self.log_exception()

    def get_npy_file_path(self, column_name):
        return os.path.join(self.npy_folder_path,
                            self.file_name + '_' + column_name + '.npy')

    def get_filtered_npy_file_path(self, column_name):
        return os.path.join(
            self.npy_folder_path,
            self.file_name + '_' + column_name + '_filtered.npy')

    def get_max_npy_file_path(self, column_name):
        return os.path.join(self.npy_folder_path,
                            self.file_name + '_' + column_name + '_max.npy')

    def get_min_npy_file_path(self, column_name):
        return os.path.join(self.npy_folder_path,
                            self.file_name + '_' + column_name + '_min.npy')

    def get_average_npy_file_path(self, columns_names):
        avg_file_suffix = self.get_suffix_for_columns_to_be_averaged(
            columns_names)
        return os.path.join(self.npy_folder_path,
                            self.file_name + '_' + avg_file_suffix + '.npy')

    def get_suffix_for_columns_to_be_averaged(self, columns_names):
        suffix_for_saved_file_name = 'avg_' + '_'.join(columns_names)
        return suffix_for_saved_file_name

    def export_data_json(self):
        # Output data MUST have exactly similar keys and variable names
        output_data = {
            'take_time_from_time_column': self.take_time_from_time_column,
            'time_column': self.time_column,
            'records_per_second': self.records_per_second,
            'skip_first_rows': self.skip_first_rows,
            'columns_headers': self.columns_headers,
            'columns_to_be_averaged': self.columns_to_be_averaged,
            'x_axis': self.x_axis,
            'y_axis': self.y_axis,
            'x_axis_multiplier': self.x_axis_multiplier,
            'y_axis_multiplier': self.y_axis_multiplier,
            'force_column': self.force_column,
            'window_length': self.window_length,
            'polynomial_order': self.polynomial_order,
            'peak_force_before_cycles': self.peak_force_before_cycles,
            'cutting_method': self.cutting_method,
            'force_max': self.force_max,
            'force_min': self.force_min,
            'min_cycle_force_range': self.min_cycle_force_range
        }
        with open(self.get_json_file_path(), 'w') as outfile:
            json.dump(output_data, outfile, sort_keys=True, indent=4)
        self.print_custom('.json data file exported successfully.')

    def import_data_json(self):
        json_path = self.get_json_file_path()
        if not os.path.isfile(json_path):
            return
        # class_vars is a list with class variables names
        # vars(self) & self.__dict__.items() didn't include some Trait variables like force_column = tr.Enum(values=..
        class_vars = [
            attr for attr in dir(self)
            if not attr.startswith("_") and not attr.startswith("__")
        ]
        with open(json_path) as infile:
            data_in = json.load(infile)
        for key_data, value_data in data_in.items():
            for key_class in class_vars:
                if key_data == key_class:
                    # Equivalent to: self.key_class = value_data
                    setattr(self, key_class, value_data)
                    break
        self.print_custom('.json data file imported successfully.')

    def get_json_file_path(self):
        return os.path.join(self.npy_folder_path, self.file_name + '.json')

    def _generate_filtered_and_creep_npy_fired(self):
        # Run method on different thread so GUI doesn't freeze
        # thread = Thread(target = threaded_function, function_args = (10,))
        thread = Thread(target=self.generate_filtered_and_creep_npy_fired)
        thread.start()

    def generate_filtered_and_creep_npy_fired(self):
        try:
            self.export_data_json()
            if not self.npy_files_exist(
                    self.get_npy_file_path(self.force_column)):
                return
            self.print_custom('Generating filtered and creep files...')

            # 1- Export filtered force
            force = np.load(self.get_npy_file_path(
                self.force_column)).flatten()
            peak_force_before_cycles_index = np.where(
                abs((force)) > abs(self.peak_force_before_cycles))[0][0]
            force_ascending = force[0:peak_force_before_cycles_index]
            force_rest = force[peak_force_before_cycles_index:]

            force_max_indices, force_min_indices = self.get_array_max_and_min_indices(
                force_rest)

            force_max_min_indices = np.concatenate(
                (force_min_indices, force_max_indices))
            force_max_min_indices.sort()

            force_rest_filtered = force_rest[force_max_min_indices]
            force_filtered = np.concatenate(
                (force_ascending, force_rest_filtered))
            np.save(self.get_filtered_npy_file_path(self.force_column),
                    force_filtered)

            # 2- Export filtered displacements
            # Export displacements combining processed ascending branch and unprocessed min/max values
            self.export_filtered_displacements(force_max_min_indices,
                                               peak_force_before_cycles_index)

            # 3- Export creep for displacements
            # Cut unwanted max min values to get correct full cycles and remove false min/max values caused by noise
            self.export_displacements_creep(force_rest, force_max_indices,
                                            force_min_indices,
                                            peak_force_before_cycles_index)

            self.print_custom('Filtered and creep npy files are generated.')
        except:
            self.log_exception()

    def export_filtered_displacements(self, force_max_min_indices,
                                      peak_force_before_cycles_index):
        for i in range(len(self.columns_headers)):
            if self.columns_headers[
                    i] != self.force_column and self.columns_headers[
                        i] != self.time_column:

                disp = np.load(self.get_npy_file_path(
                    self.columns_headers[i])).flatten()
                disp_ascending = disp[0:peak_force_before_cycles_index]
                disp_rest = disp[peak_force_before_cycles_index:]

                if self.activate_ascending_branch_smoothing:
                    disp_ascending = savgol_filter(
                        disp_ascending,
                        window_length=self.window_length,
                        polyorder=self.polynomial_order)

                disp_rest_filtered = disp_rest[force_max_min_indices]
                filtered_disp = np.concatenate(
                    (disp_ascending, disp_rest_filtered))
                np.save(
                    self.get_filtered_npy_file_path(self.columns_headers[i]),
                    filtered_disp)

    def export_displacements_creep(self, force_rest, force_max_indices,
                                   force_min_indices,
                                   peak_force_before_cycles_index):
        if self.cutting_method == "Define Max, Min":
            force_max_indices_cut, force_min_indices_cut = self.cut_indices_of_min_max_range(
                force_rest, force_max_indices, force_min_indices,
                self.force_max, self.force_min)
        elif self.cutting_method == "Define min cycle range(force difference)":
            force_max_indices_cut, force_min_indices_cut = self.cut_indices_of_defined_range(
                force_rest, force_max_indices, force_min_indices,
                self.min_cycle_force_range)
        self.print_custom("Cycles number= ", len(force_min_indices))
        self.print_custom("Cycles number after cutting fake cycles = ",
                          len(force_min_indices_cut))

        for i in range(len(self.columns_headers)):
            if self.columns_headers[i] != self.time_column:
                array = np.load(self.get_npy_file_path(
                    self.columns_headers[i])).flatten()
                array_rest = array[peak_force_before_cycles_index:]
                array_rest_maxima = array_rest[force_max_indices_cut]
                array_rest_minima = array_rest[force_min_indices_cut]
                np.save(self.get_max_npy_file_path(self.columns_headers[i]),
                        array_rest_maxima)
                np.save(self.get_min_npy_file_path(self.columns_headers[i]),
                        array_rest_minima)

    def get_array_max_and_min_indices(self, input_array):
        # Checking dominant sign
        positive_values_count = np.sum(np.array(input_array) >= 0)
        negative_values_count = input_array.size - positive_values_count

        # Getting max and min indices
        if positive_values_count > negative_values_count:
            force_max_indices = self.get_max_indices(input_array)
            force_min_indices = self.get_min_indices(input_array)
        else:
            force_max_indices = self.get_min_indices(input_array)
            force_min_indices = self.get_max_indices(input_array)

        return force_max_indices, force_min_indices

    def get_max_indices(self, a):
        # TODO try to vectorize this
        # This method doesn't qualify first and last elements as max
        max_indices = []
        i = 1
        while i < a.size - 1:
            previous_element = a[i - 1]

            # Skip repeated elements and record previous element value
            first_repeated_element = True
            while a[i] == a[i + 1] and i < a.size - 1:
                if first_repeated_element:
                    previous_element = a[i - 1]
                    first_repeated_element = False
                if i < a.size - 2:
                    i += 1
                else:
                    break

            # Append value if it's a local max
            if a[i] > a[i + 1] and a[i] > previous_element:
                max_indices.append(i)
            i += 1
        return np.array(max_indices)

    def get_min_indices(self, a):
        # TODO try to vectorize this
        # This method doesn't qualify first and last elements as min
        min_indices = []
        i = 1
        while i < a.size - 1:
            previous_element = a[i - 1]

            # Skip repeated elements and record previous element value
            first_repeated_element = True
            while a[i] == a[i + 1]:
                if first_repeated_element:
                    previous_element = a[i - 1]
                    first_repeated_element = False
                if i < a.size - 2:
                    i += 1
                else:
                    break

            # Append value if it's a local min
            if a[i] < a[i + 1] and a[i] < previous_element:
                min_indices.append(i)
            i += 1
        return np.array(min_indices)

    def cut_indices_of_min_max_range(self, array, max_indices, min_indices,
                                     range_upper_value, range_lower_value):
        # TODO try to vectorize this
        cut_max_indices = []
        cut_min_indices = []

        for max_index in max_indices:
            if abs(array[max_index]) > abs(range_upper_value):
                cut_max_indices.append(max_index)
        for min_index in min_indices:
            if abs(array[min_index]) < abs(range_lower_value):
                cut_min_indices.append(min_index)
        return cut_max_indices, cut_min_indices

    def cut_indices_of_defined_range(self, array, max_indices, min_indices,
                                     range_):
        # TODO try to vectorize this
        cut_max_indices = []
        cut_min_indices = []

        for max_index, min_index in zip(max_indices, min_indices):
            if abs(array[max_index] - array[min_index]) > range_:
                cut_max_indices.append(max_index)
                cut_min_indices.append(min_index)

        if max_indices.size > min_indices.size:
            cut_max_indices.append(max_indices[-1])
        elif min_indices.size > max_indices.size:
            cut_min_indices.append(min_indices[-1])

        return cut_max_indices, cut_min_indices

    def _activate_changed(self):
        if not self.activate_ascending_branch_smoothing:
            self.old_peak_force_before_cycles = self.peak_force_before_cycles
            self.peak_force_before_cycles = 0
        else:
            self.peak_force_before_cycles = self.old_peak_force_before_cycles

    def _window_length_changed(self, new):
        if new <= self.polynomial_order:
            dialog = MessageDialog(
                title='Attention!',
                message='Window length must be bigger than polynomial order.')
            dialog.open()

        if new % 2 == 0 or new <= 0:
            dialog = MessageDialog(
                title='Attention!',
                message='Window length must be odd positive integer.')
            dialog.open()

    def _polynomial_order_changed(self, new):
        if new >= self.window_length:
            dialog = MessageDialog(
                title='Attention!',
                message='Polynomial order must be smaller than window length.')
            dialog.open()

    # =========================================================================
    # Plotting
    # =========================================================================
    data_changed = tr.Event

    def _plot_settings_btn_fired(self):
        try:
            self.plot_settings.configure_traits(kind='modal')
        except:
            self.log_exception()

    def npy_files_exist(self, path):
        if os.path.exists(path):
            return True
        else:
            self.print_custom(
                'Please parse csv file to generate npy files first!')
            return False

    def filtered_and_creep_npy_files_exist(self, path):
        if os.path.exists(path):
            return True
        else:
            self.print_custom(
                'Please generate filtered and creep npy files first!')
            return False

    def _add_plot_fired(self):
        # Run method on different thread so GUI doesn't freeze
        # thread = Thread(target = threaded_function, function_args = (10,))
        thread = Thread(target=self.add_plot_fired)
        thread.start()

    def add_plot_fired(self):
        try:
            if self.apply_filters:
                if not self.filtered_and_creep_npy_files_exist(
                        self.get_filtered_npy_file_path(self.x_axis)):
                    return
                # TODO link this _filtered to the path creation function
                x_axis_name = self.x_axis + '_filtered'
                y_axis_name = self.y_axis + '_filtered'
                self.print_custom('Loading npy files...')
                # when mmap_mode!=None, the array will be loaded as 'numpy.memmap'
                # object which doesn't load the array to memory until it's
                # indexed
                x_axis_array = np.load(self.get_filtered_npy_file_path(
                    self.x_axis),
                                       mmap_mode='r')
                y_axis_array = np.load(self.get_filtered_npy_file_path(
                    self.y_axis),
                                       mmap_mode='r')
            else:
                if not self.npy_files_exist(self.get_npy_file_path(
                        self.x_axis)):
                    return

                x_axis_name = self.x_axis
                y_axis_name = self.y_axis
                self.print_custom('Loading npy files...')
                # when mmap_mode!=None, the array will be loaded as 'numpy.memmap'
                # object which doesn't load the array to memory until it's
                # indexed
                x_axis_array = np.load(self.get_npy_file_path(self.x_axis),
                                       mmap_mode='r')
                y_axis_array = np.load(self.get_npy_file_path(self.y_axis),
                                       mmap_mode='r')

            if self.plot_settings_active:
                print(self.plot_settings.num_of_first_rows_to_take)
                print(
                    self.plot_settings.num_of_rows_to_skip_after_each_section)
                print(self.plot_settings.num_of_rows_in_each_section)
                print(np.size(x_axis_array))
                indices = self.get_indices_array(
                    np.size(x_axis_array),
                    self.plot_settings.num_of_first_rows_to_take,
                    self.plot_settings.num_of_rows_to_skip_after_each_section,
                    self.plot_settings.num_of_rows_in_each_section)
                x_axis_array = self.x_axis_multiplier * x_axis_array[indices]
                y_axis_array = self.y_axis_multiplier * y_axis_array[indices]
            else:
                x_axis_array = self.x_axis_multiplier * x_axis_array
                y_axis_array = self.y_axis_multiplier * y_axis_array

            self.print_custom('Adding Plot...')
            mpl.rcParams['agg.path.chunksize'] = 10000

            ax = self.ax

            ax.set_xlabel(x_axis_name)
            ax.set_ylabel(y_axis_name)
            ax.plot(x_axis_array,
                    y_axis_array,
                    linewidth=1.2,
                    color=np.random.rand(3),
                    label=self.file_name + ', ' + x_axis_name)
            ax.legend()

            self.data_changed = True
            self.print_custom('Finished adding plot.')

        except:
            self.log_exception()

    def _add_creep_plot_fired(self):
        # Run method on different thread so GUI doesn't freeze
        # thread = Thread(target = threaded_function, function_args = (10,))
        thread = Thread(target=self.add_creep_plot_fired)
        thread.start()

    def add_creep_plot_fired(self):
        try:
            if not self.filtered_and_creep_npy_files_exist(
                    self.get_max_npy_file_path(self.x_axis)):
                return

            self.print_custom('Loading npy files...')
            disp_max = self.x_axis_multiplier * np.load(
                self.get_max_npy_file_path(self.x_axis))
            disp_min = self.x_axis_multiplier * np.load(
                self.get_min_npy_file_path(self.x_axis))
            complete_cycles_number = disp_max.size

            self.print_custom('Adding creep-fatigue plot...')
            mpl.rcParams['agg.path.chunksize'] = 10000

            ax = self.ax

            ax.set_xlabel('Cycles number')
            ax.set_ylabel(self.x_axis)

            if self.plot_every_nth_point > 1:
                disp_max = disp_max[0::self.plot_every_nth_point]
                disp_min = disp_min[0::self.plot_every_nth_point]

            if self.smooth:
                # Keeping the first item of the array and filtering the rest
                disp_max = np.concatenate(
                    (np.array([disp_max[0]]),
                     savgol_filter(disp_max[1:],
                                   window_length=self.window_length,
                                   polyorder=self.polynomial_order)))
                disp_min = np.concatenate(
                    (np.array([disp_min[0]]),
                     savgol_filter(disp_min[1:],
                                   window_length=self.window_length,
                                   polyorder=self.polynomial_order)))

            if self.normalize_cycles:
                ax.plot(np.linspace(0, 1., disp_max.size),
                        disp_max,
                        'k',
                        linewidth=1.2,
                        color=np.random.rand(3),
                        label='Max' + ', ' + self.file_name + ', ' +
                        self.x_axis)
                ax.plot(np.linspace(0, 1., disp_min.size),
                        disp_min,
                        'k',
                        linewidth=1.2,
                        color=np.random.rand(3),
                        label='Min' + ', ' + self.file_name + ', ' +
                        self.x_axis)
            else:
                ax.plot(np.linspace(0, complete_cycles_number, disp_max.size),
                        disp_max,
                        'k',
                        linewidth=1.2,
                        color=np.random.rand(3),
                        label='Max' + ', ' + self.file_name + ', ' +
                        self.x_axis)
                ax.plot(np.linspace(0, complete_cycles_number, disp_min.size),
                        disp_min,
                        'k',
                        linewidth=1.2,
                        color=np.random.rand(3),
                        label='Min' + ', ' + self.file_name + ', ' +
                        self.x_axis)

            ax.legend()
            self.data_changed = True
            self.print_custom('Finished adding creep-fatigue plot.')

        except:
            self.log_exception()

    def get_indices_array(self, array_size, first_rows, distance,
                          num_of_rows_after_each_distance):
        result_1 = np.arange(first_rows)
        result_2 = np.arange(start=first_rows,
                             stop=array_size,
                             step=distance + num_of_rows_after_each_distance)
        result_2_updated = np.array([], dtype=np.int_)

        for result_2_value in result_2:
            data_slice = np.arange(
                result_2_value,
                result_2_value + num_of_rows_after_each_distance)
            result_2_updated = np.concatenate((result_2_updated, data_slice))

        result = np.concatenate((result_1, result_2_updated))
        return result

    def _clear_plot_fired(self):
        self.figure.clear()
        self.create_axes(self.figure)
        self.data_changed = True

    # =========================================================================
    # Logging
    # =========================================================================
    def print_custom(self, *input_args):
        print(*input_args)
        if self.log == '':
            self.log = ''.join(str(e) for e in list(input_args))
        else:
            self.log = self.log + '\n' + \
                       ''.join(str(e) for e in list(input_args))

    def log_exception(self):
        self.print_custom('SOMETHING WENT WRONG!')
        self.print_custom('--------- Error message: ---------')
        self.print_custom(traceback.format_exc())
        self.print_custom('----------------------------------')

    def _clear_log_fired(self):
        self.log = ''

    # =========================================================================
    # Other functions
    # =========================================================================
    def reset(self):
        self.columns_to_be_averaged = []
        self.log = ''
Beispiel #29
0
class BackgroundRemoval(SpanSelectorInSignal1D):
    background_type = t.Enum('Power Law',
                             'Gaussian',
                             'Offset',
                             'Polynomial',
                             default='Power Law')
    polynomial_order = t.Range(1, 10)
    fast = t.Bool(True,
                  desc=("Perform a fast (analytic, but possibly less accurate)"
                        " estimation of the background. Otherwise use "
                        "non-linear least squares."))
    background_estimator = t.Instance(Component)
    bg_line_range = t.Enum('from_left_range',
                           'full',
                           'ss_range',
                           default='full')
    hi = t.Int(0)
    view = tu.View(
        tu.Group(
            'background_type',
            'fast',
            tu.Group('polynomial_order',
                     visible_when='background_type == \'Polynomial\''),
        ),
        buttons=[OKButton, CancelButton],
        handler=SpanSelectorInSignal1DHandler,
        title='Background removal tool',
        resizable=True,
        width=300,
    )

    def __init__(self, signal):
        super(BackgroundRemoval, self).__init__(signal)
        self.set_background_estimator()
        self.bg_line = None

    def on_disabling_span_selector(self):
        if self.bg_line is not None:
            self.bg_line.close()
            self.bg_line = None

    def set_background_estimator(self):

        if self.background_type == 'Power Law':
            self.background_estimator = components1d.PowerLaw()
            self.bg_line_range = 'from_left_range'
        elif self.background_type == 'Gaussian':
            self.background_estimator = components1d.Gaussian()
            self.bg_line_range = 'full'
        elif self.background_type == 'Offset':
            self.background_estimator = components1d.Offset()
            self.bg_line_range = 'full'
        elif self.background_type == 'Polynomial':
            self.background_estimator = components1d.Polynomial(
                self.polynomial_order)
            self.bg_line_range = 'full'

    def _polynomial_order_changed(self, old, new):
        self.background_estimator = components1d.Polynomial(new)
        self.span_selector_changed()

    def _background_type_changed(self, old, new):
        self.set_background_estimator()
        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_background_line(self):
        self.bg_line = drawing.signal1d.Signal1DLine()
        self.bg_line.data_function = self.bg_to_plot
        self.bg_line.set_line_properties(color='blue',
                                         type='line',
                                         scaley=False)
        self.signal._plot.signal_plot.add_line(self.bg_line)
        self.bg_line.autoscale = False
        self.bg_line.plot()

    def bg_to_plot(self, axes_manager=None, fill_with=np.nan):
        # First try to update the estimation
        self.background_estimator.estimate_parameters(self.signal,
                                                      self.ss_left_value,
                                                      self.ss_right_value,
                                                      only_current=True)

        if self.bg_line_range == 'from_left_range':
            bg_array = np.zeros(self.axis.axis.shape)
            bg_array[:] = fill_with
            from_index = self.axis.value2index(self.ss_left_value)
            bg_array[from_index:] = self.background_estimator.function(
                self.axis.axis[from_index:])
            to_return = bg_array
        elif self.bg_line_range == 'full':
            to_return = self.background_estimator.function(self.axis.axis)
        elif self.bg_line_range == 'ss_range':
            bg_array = np.zeros(self.axis.axis.shape)
            bg_array[:] = fill_with
            from_index = self.axis.value2index(self.ss_left_value)
            to_index = self.axis.value2index(self.ss_right_value)
            bg_array[from_index:] = self.background_estimator.function(
                self.axis.axis[from_index:to_index])
            to_return = bg_array

        if self.signal.metadata.Signal.binned is True:
            to_return *= self.axis.scale
        return to_return

    def span_selector_changed(self):
        if self.ss_left_value is np.nan or self.ss_right_value is np.nan or\
                self.ss_right_value <= self.ss_left_value:
            return
        if self.background_estimator is None:
            return
        if self.bg_line is None and \
            self.background_estimator.estimate_parameters(
                self.signal, self.ss_left_value,
                self.ss_right_value,
                only_current=True) is True:
            self.create_background_line()
        else:
            self.bg_line.update()

    def apply(self):
        self.signal._plot.auto_update_plot = False
        new_spectra = self.signal._remove_background_cli(
            (self.ss_left_value, self.ss_right_value),
            self.background_estimator,
            fast=self.fast)
        self.signal.data = new_spectra.data
        self.signal._replot()
        self.signal._plot.auto_update_plot = True
Beispiel #30
0
class OdorControl(traited_plugin.HasTraits_FViewPlugin):
    enabled = traits.Bool(False)
    plugin_name = "Odor Control"
    last_update_time = traits.Float(-np.inf, transient=True)
    save_to_disk = traits.Bool(False, transient=True)
    log_filename_prefix = traits.String('odd_log_data_')
    log_filename = traits.File
    odd_filename = traits.File
    persistent_attr_names = traits.List(['odd_filename', 'log_filename'])
    deliver_odors = traits.Bool(False, transient=True)
    traits_view = View(Group(\
      Item(name="deliver_odors"),\
      Item(name='save_to_disk'),\
      Item(name="odd_filename", editor=FileEditor(dialog_style="open")),\
      Item(name="log_filename_prefix"),\
      Item(name="log_filename", style="readonly")))

    def __init__(self, *args, **kwargs):
        super(OdorControl, self).__init__(*args, **kwargs)
        print "Initialized odor control"
        self._list_of_timestamp_data = []
        self.odors = []
        self.last_trigger_timestamp = {}
        self.sending_odor = False
        self.total_delay = 0
        self.has_started = False
        self.log_file = None
        self.worker = None
        self.context = zmq.Context(1)
        self.client = self.context.socket(zmq.REQ)
        self.client.connect(SERVER_ENDPOINT)
        self.poll = zmq.Poller()
        self.poll.register(self.client, zmq.POLLIN)
        print "Socket initialized on port 5556..."

        self.has_started = True

        # variables for current odor
        self.odor_name = ""
        self.odor = 0
        self.stim = 0
        self.delay = 0

    def _save_to_disk_changed(self):
        print "Changing save to disk"
        if self.has_started:
            if self.save_to_disk:
                self.log_filename = self.log_filename_prefix + time.strftime(
                    '%Y%m%d_%H%M%S') + ".txt"
                self.log_file = open(self.log_filename, 'w')
                print "Saving ", repr(self.log_filename), " to disk..."
            else:
                print "Closed", repr(self.log_filename)
                self.log_file.close()
                self.log_file = None
                self.log_filename = ""

    def _odd_filename_changed(self):
        print "Changing ODD filename"
        try:
            print "Using ODD file ", self.odd_filename
            self.odors = read_odd_file(self.odd_filename.encode('ascii'))
        except IOError:
            print "Couldn't open ODD file ", self.odd_filename

    def quit(self):
        pass
        if self.save_to_disk:
            self.log_file.close()
        if self.has_started and self.worker is not None:
            self.worker.join()

    def camera_starting_notification(self,
                                     cam_id,
                                     pixel_format=None,
                                     max_width=None,
                                     max_height=None):
        self.has_started = True
        pass

    def process_frame(self, cam_id, buf, buf_offset, timestamp, framenumber):
        draw_points = []
        draw_linesegs = []
        now = time.time()
        if self.deliver_odors:
            if not self.sending_odor:
                self.odor_name, self.odor, self.stim, self.delay = self.odors.pop(
                )
                if self.save_to_disk:
                    loginfo = "S %s %d %d %d %d %d %d\n" % (
                        self.odor_name, self.odor, self.stim, self.delay,
                        framenumber, time.mktime(time.gmtime()), timestamp)
                    self.log_file.write(loginfo)
                self.total_delay = self.stim + self.delay
                print "Sending odor ", self.odor_name, " with total delay ", self.total_delay
                self.worker = ODDControlWorker(self.odor, self.stim,
                                               self.delay, self.client,
                                               self.poll)
                self.worker.daemon = True
                self.worker.start()
                self.sending_odor = True
                self.last_update_time = time.time()
            else:
                if (now - self.last_update_time) > self.total_delay:
                    print "Changing odor from ", self.odor_name
                    self.worker.join()
                    self.sending_odor = False
                    if self.save_to_disk:
                        loginfo = "R %s %d %d %d %d %d %d\n" % (
                            self.odor_name, self.odor, self.stim, self.delay,
                            framenumber, time.mktime(time.gmtime()), timestamp)
                        self.log_file.write(loginfo)
                    if len(self.odors) == 0:
                        self.deliver_odors = False
                        # reload odors
                        self.odors = read_odd_file(
                            self.odd_filename.encode('ascii'))
        return draw_points, draw_linesegs