Exemple #1
0
  def createDatasetForDisplay(self, display):
    plotData = PlotDataItem(name=display['label'])

    if 'color' in display:
      plotData.setPen(mkPen({'color': display['color']}))

    return {
      'plotData': plotData,
      'points': numpy.zeros((constants.NUMPY_ARRAY_SIZE, 2)),
    }
Exemple #2
0
 def __init__(self, name):
     CtrlNode.__init__(self, name, terminals={
         'x': {'io': 'in'},
         'y': {'io': 'in'},
         'plot': {'io': 'out'}
     })
     self.item = PlotDataItem()
Exemple #3
0
 def __init__(self, *args, **kwargs):
     super(MapViewWidget, self).__init__(*args, **kwargs)
     # self.scene.sigMouseMoved.connect(self.showSpectra)
     self.scene.sigMouseClicked.connect(self.showSpectra)
     self.view.invertY(True)
     # add arrow
     self.cross = PlotDataItem([0], [0],
                               symbolBrush=(200, 0, 0),
                               symbolPen=(200, 0, 0),
                               symbol='+',
                               symbolSize=16)
     self.view.addItem(self.cross)
     self.cross.hide()
     #add txt
     self.txt = TextItem('', anchor=(0, 0))
     self.addItem(self.txt)
Exemple #4
0
class PlotCurve(CtrlNode):
    """Generates a plot curve from x/y data"""

    nodeName = "PlotCurve"
    uiTemplate = [("color", "color")]

    def __init__(self, name):
        CtrlNode.__init__(self, name, terminals={"x": {"io": "in"}, "y": {"io": "in"}, "plot": {"io": "out"}})
        self.item = PlotDataItem()

    def process(self, x, y, display=True):
        # print "scatterplot process"
        if not display:
            return {"plot": None}

        self.item.setData(x, y, pen=self.ctrls["color"].color())
        return {"plot": self.item}
Exemple #5
0
    def make_plt(self):

        # Reset the plot (i.e., remove all plot elements).

        self.rset_plt()

        # Establish the ranges of its time and magnetic field values.
        # If the core contains no data or only a single datum,
        # improvise (for the purpose of later establishing axis limits).

        if (self.core.n_mfi >= 1):

            # Establish the domain of the plot.

            t_min = min(amin(self.core.mfi_s), 0.)
            t_max = max(amax(self.core.mfi_s), self.core.fc_spec['dur'])

            # Establish the range of the plot.  As part of this,
            # ensure that the range satisfies a minimum size and has
            # sufficient padding.

            ang_max = max(self.core.mfi_b_lon)
            ang_min = min(self.core.mfi_b_lon)

            ang_max = 5. + ang_max
            ang_min = -5. + ang_min

            d_t_0 = t_max - t_min

            d_t = max(1.5 + d_t_0, 3.)

            t_max = t_min + d_t

        else:

            t_min = 0.001
            t_max = 3.500

            ang_min = -360
            ang_max = 360

        # Set the range of the axis of each plot.

        self.plt.setXRange(t_min, t_max, padding=0.0)
        self.plt.setYRange(ang_min, ang_max, padding=0.0)

        # If the core contains no Wind/MFI magnetic field data, return.

        if (self.core.n_mfi <= 0):
            return

        # Generate and display each curve for the plot.

        self.crv_lon = PlotDataItem(self.core.mfi_s,
                                    self.core.mfi_b_lon,
                                    pen=self.pen_crv_lon)

        self.plt.addItem(self.crv_lon)
 def line(self,
          x: Optional[np.ndarray],
          y: np.ndarray,
          label: Optional[str] = None,
          line_style: LineStyle = LineStyle.Solid,
          **kwargs) -> None:
     x = Axes._create_x(y) if x is None else x
     kwargs = Axes._add_label_to_kwargs(label, kwargs)
     self._raw.addItem(PlotDataItem(x=x, y=y, **kwargs))
    def __init__(self, *args, **kwargs):
        PlotDataItem.__init__(self, *args, **kwargs)
        TaurusBaseComponent.__init__(self, 'TaurusBaseComponent')
        self._UImodifiable = False
        self._maxBufferSize = 65536  # (=2**16, i.e., 64K events))
        self._xBuffer = None
        self._yBuffer = None
        self._curveColors = LoopList(CURVE_COLORS)
        self._args = args
        self._kwargs = kwargs
        self._curves = []
        self._timer = Qt.QTimer()
        self._timer.timeout.connect(self._forceRead)
        self._legend = None

        # register config properties
        self.setModelInConfig(True)
        self.registerConfigProperty(self._getCurvesOpts, self._setCurvesOpts,
                                    'opts')
Exemple #8
0
    def __init__(self, *args, **kwargs):
        super(MapViewWidget, self).__init__(*args, **kwargs)
        # self.scene.sigMouseMoved.connect(self.showSpectra)
        self.scene.sigMouseClicked.connect(self.showSpectra)
        self.view.invertY(True)

        # add arrow
        # self.arrow = ArrowItem(angle=60, headLen=15, tipAngle=45, baseAngle=30, brush = (200, 80, 20))
        # self.arrow.setPos(0, 0)
        self.cross = PlotDataItem([0], [0],
                                  symbolBrush=(200, 0, 0),
                                  symbolPen=(200, 0, 0),
                                  symbol='+',
                                  symbolSize=16)

        self.view.addItem(self.cross)
        self.cross.hide()
        #add txt
        self.txt = TextItem('', anchor=(0, 0))
        self.addItem(self.txt)
    def _initCurves(self, ntrends):
        """ Initializes new curves """

        # self._removeFromLegend(self._legend)
        self._curves = []
        self._curveColors.setCurrentIndex(-1)

        a = self._args
        kw = self._kwargs.copy()

        base_name = (self.base_name()
                     or taurus.Attribute(self.getModel()).getSimpleName())

        for i in range(ntrends):
            subname = "%s[%i]" % (base_name, i)
            kw['name'] = subname
            curve = PlotDataItem(*a, **kw)
            if 'pen' not in kw:
                curve.setPen(next(self._curveColors).color())
            self._curves.append(curve)
        self._updateViewBox()
Exemple #10
0
class PlotCurve(CtrlNode):
    """Generates a plot curve from x/y data"""
    nodeName = 'PlotCurve'
    uiTemplate = [
        ('color', 'color'),
    ]
    
    def __init__(self, name):
        CtrlNode.__init__(self, name, terminals={
            'x': {'io': 'in'},
            'y': {'io': 'in'},
            'plot': {'io': 'out'}
        })
        self.item = PlotDataItem()
    
    def process(self, x, y, display=True):
        #print "scatterplot process"
        if not display:
            return {'plot': None}
        
        self.item.setData(x, y, pen=self.ctrls['color'].color())
        return {'plot': self.item}
    def set_experiment_view(self):
        self.ui.graphicsView.clear()
        plot = PlotDataItem(pen="k")

        duration = (self.ui.spinBoxExperimentDurationMinutes.value() *
                    60) + self.ui.spinBoxExperimentDurationSeconds.value()
        xs = np.linspace(0, duration, 2)
        ys = [1, 1]
        plot.setData(xs, ys)
        self.ui.graphicsView.addItem(plot)

        for ii in range(len(self.Stims.df)):
            start = self.Stims.df.time_on.iloc[ii]
            stop = self.Stims.df.time_off.iloc[ii]

            if self.Stims.df.message_on.iloc[ii].startswith("w"):
                box = LinearRegionItem(values=(start, stop),
                                       brush=(255, 255, 250, 230),
                                       movable=False)
                self.ui.graphicsView.addItem(box)
            elif self.Stims.df.message_on.iloc[ii].startswith("n"):
                on = self.Stims.df.message_on.iloc[ii][1:]
                r = int(on[:3])
                g = int(on[3:6])
                b = int(on[6:])
                box = LinearRegionItem(values=(start, stop),
                                       brush=(r, g, b, 50),
                                       movable=False)
                self.ui.graphicsView.addItem(box)
            elif self.Stims.df.message_on.iloc[ii].startswith("v"):
                box = LinearRegionItem(values=(start, stop),
                                       brush="k",
                                       movable=False)
                self.ui.graphicsView.addItem(box)

        self.ui.comboBoxSelectStimId.clear()
        for stim_id in set(self.Stims.df.id):
            self.ui.comboBoxSelectStimId.addItem(stim_id)
Exemple #12
0
    def visualize(self, larlite_io, larcv_io, rawdigit_io):
        event_imgs = larcv_io.get_data(larcv.kProductImage2D, self.producer)
        event_hits = larcv_io.get_data(larcv.kProductImage2D,
                                       self.hit_producer)

        lcv_imgs = event_imgs.Image2DArray()
        lcv_hits = event_hits.Image2DArray()

        pixel_vecs = []  # output container

        for iimg in xrange(0, lcv_imgs.size()):
            lcv_img = lcv_imgs.at(iimg)
            lcv_hit = lcv_hits.at(iimg)

            meta = lcv_img.meta()

            angimg = larcv.as_ndarray(lcv_img)
            hitpx = larcv.as_ndarray(lcv_hit)

            hits = np.argwhere(hitpx > 0.1)

            print "number of hits: ", len(hits)
            vec_data_x = np.zeros(2 *
                                  len(hits))  # we make pair of points for vec
            vec_data_y = np.zeros(2 *
                                  len(hits))  # we make pair of points for vec
            for i, hit in enumerate(hits):
                # set origin
                x = meta.pos_x(hit[0])
                y = meta.pos_y(hit[1])

                vec_data_x[2 * i] = x
                vec_data_y[2 * i] = y

                ang = angimg[hit[0], hit[1]]
                dx = np.cos(ang) * meta.pixel_width()
                dy = np.sin(ang) * meta.pixel_height()

                vec_data_x[2 * i + 1] = x + dx
                vec_data_y[2 * i +
                           1] = y - dy  # (-) because origin of y is top corner

            plot = PlotDataItem(x=vec_data_x,
                                y=vec_data_y,
                                pen=(255, 255, 255, 100),
                                connect='pairs')
            pixel_vecs.append(plot)

        return pixel_vecs
 def plot(self,
          x: Optional[np.ndarray],
          y: np.ndarray,
          label: Optional[str] = None,
          marker_style: MarkerStyle = MarkerStyle.Dot,
          **kwargs) -> None:
     x = Axes._create_x(y) if x is None else x
     kwargs = Axes._add_label_to_kwargs(label, kwargs)
     # self._raw.plot(x=x, y=y, pen=None, **marker_style_to_dict(marker_style), **kwargs)
     self._raw.addItem(
         PlotDataItem(x=x,
                      y=y,
                      pen=None,
                      **marker_style_to_dict(marker_style),
                      **kwargs))
    def __init__(self, *args, **kwargs):
        """
        Accepts same args and kwargs as PlotDataItem, plus:
        :param xModel: (str) Taurus model name for abscissas values.
                       Default=None
        :param yModel: (str) Taurus model name for ordinate values.
                       Default=None
        """
        xModel = kwargs.pop('xModel', None)
        yModel = kwargs.pop('yModel', None)
        PlotDataItem.__init__(self, *args, **kwargs)
        TaurusBaseComponent.__init__(self, 'TaurusBaseComponent')
        self._x = None
        self._y = None
        self.xModel = None
        if xModel is not None:
            self.setXModel(xModel)
        if yModel is not None:
            self.setModel(yModel)

        self.registerConfigProperty(self.getOpts, self.setOpts, 'opts')
        self.setModelInConfig(True)
        self.registerConfigProperty(self.getXModelName, self.setXModel,
                                    'XModel')
Exemple #15
0
 def __init__(self, name):
     Node.__init__(self,
                   name,
                   terminals={
                       'dataIn': {
                           'io': 'in'
                       },
                       'dataOut': {
                           'io': 'out'
                       },
                       'plotItems': {
                           'io': 'out'
                       }
                   })
     color = (220, 220, 25, 255)
     self.plotDataItem = PlotDataItem(stepMode=True,
                                      fillLevel=0,
                                      pen={
                                          'color': color,
                                          'width': 2
                                      })
     self.plotRegion = LinearRegionItem([0, 1], movable=True)
     self.plotRegion.sigRegionChangeFinished.connect(self.regionChanged)
     self.sigUpdatePlot.connect(self.updatePlot)
Exemple #16
0
    def stylingPlot(self):
        colorDefault = self.palette().color(QtGui.QPalette.Window)
        plot = self._ui.pnlPlot

        plot.setBackground(colorDefault)
        plot.setTitle(
            "Daily number of Cases and Deaths in Spain (14-day mean)",
            color=(57, 57, 58),
            size="18pt")

        styles = {'color': (57, 57, 58), 'font-size': '12px'}
        plot.setLabel('left', 'Infections', **styles)
        plot.setLabel('right', 'Deaths', **styles)
        plot.showGrid(x=False, y=True)
        plot2 = PlotDataItem([0, 1, 2, 8], [48, 57, 14, 3], antialias=True)
        plot.addItem(plot2)
 def histogram(self,
               data: np.ndarray,
               label: Optional[str] = None,
               bins: int = 10,
               data_range: Optional[Tuple[Optional[float],
                                          Optional[float]]] = None,
               line_style: LineStyle = LineStyle.Solid,
               orientation: Orientation = Orientation.Vertical,
               **kwargs) -> None:
     hist, bin_list = np.histogram(data,
                                   bins=bins,
                                   range=Axes._data_range(data_range, data))
     kwargs = Axes._add_label_to_kwargs(label, kwargs)
     if orientation == Orientation.Vertical:
         self._raw.addItem(
             PlotDataItem(x=bin_list, y=hist, stepMode=True, **kwargs))
     else:
         raise NotImplementedError
class ComponentPlotWidget(SpectraPlotWidget):
    def __init__(self, *args, **kwargs):
        super(ComponentPlotWidget, self).__init__(linePos=800,
                                                  txtPosRatio=0.35,
                                                  *args,
                                                  **kwargs)
        self.cross = PlotDataItem([800], [0],
                                  symbolBrush=(255, 255, 255),
                                  symbolPen=(255, 255, 255),
                                  symbol='+',
                                  symbolSize=25)
        self._x, self._y = None, None
        self.ymax, self.zmax = 0, 100

    def getEnergy(self):
        if self._y is not None:
            x_val = self.line.value()
            idx = val2ind(x_val, self._x)
            x_val = self._x[idx]
            y_val = self._y[idx]
            txt_html = f'<div style="text-align: center"><span style="color: #FFF; font-size: 12pt">\
                                                 X = {x_val: .2f}, Y = {y_val: .4f}</div>'

            self.txt.setHtml(txt_html)
            self.cross.setData([x_val], [y_val])

    def plot(self, x, y, *args, **kwargs):
        # set up infinity line and get its position
        plot_item = self.plotItem.plot(x, y, *args, **kwargs)
        self.addItem(self.line)
        self.addItem(self.cross)
        x_val = self.line.value()
        idx = val2ind(x_val, x)
        x_val = x[idx]
        y_val = y[idx]
        txt_html = f'<div style="text-align: center"><span style="color: #FFF; font-size: 12pt">\
                                     X = {x_val: .2f}, Y = {y_val: .4f}</div>'

        self.txt.setHtml(txt_html)
        self.txt.setZValue(self.zmax - 1)
        self.cross.setData([x_val], [y_val])
        self.cross.setZValue(self.zmax)
        ymax = max(y)
        if ymax > self.ymax:
            self.ymax = ymax
        self._x, self._y = x, y
        r = self.txtPosRatio
        self.txt.setPos(r * x[-1] + (1 - r) * x[0], self.ymax)
        self.addItem(self.txt)
        return plot_item
Exemple #19
0
 def add_plot_item(self, i, x, y, colour=Qt.red):
     """Add a plot item representing two already added data series.
     
     :param i: Id of the plot item. Should be ascending natural numbers 
         from 0 up.
     :type i: int
     :param x: Id of the data series holding the x values.
     :type x: int
     :param y: Id of the data series holding the y values.
     :type y: int
     :param colour: Colour of the plot item. The default is red.
     :type colour: str|QRgb|QColor|Qt.GlobalColor
     """
     self.items[i] = {"x": x, "y": y}
     self.data[x]["items"].append(i)
     self.data[y]["items"].append(i)
     self.items[i]["plot"] = PlotDataItem( \
             self.data[x]["data"], \
             self.data[y]["data"], \
             pen=QColor(colour))
     self.widget.addItem(self.items[i]["plot"])
Exemple #20
0
    def make_plt(self):

        # Reset the plot (i.e., remove all plot elements).

        self.rset_plt()

        # Establish the ranges of its time and magnetic field values.
        # If the core contains no data or only a single datum,
        # improvise (for the purpose of later establishing axis limits).

        if (self.core.n_mfi >= 1):

            # Establish the domain of the plot.

            t_min = min(amin(self.core.mfi_s), 0.)
            t_max = max(amax(self.core.mfi_s), self.core.fc_spec['dur'])

            # Establish the range of the plot.  As part of this,
            # ensure that the range satisfies a minimum size and has
            # sufficient padding.

            b_max = amax(self.core.mfi_b)
            b_min = -b_max

            d_t_0 = t_max - t_min
            d_b_0 = b_max - b_min

            d_t = max(1.5 + d_t_0, 3.)
            d_b = max(1.2 * d_b_0, 5.)

            t_max = t_min + d_t

            b_min = b_min - (d_b - d_b_0) / 2.
            b_max = b_max + (d_b - d_b_0) / 2.

        else:

            t_min = 0.001
            t_max = 3.500

            b_min = -2.5
            b_max = 2.5

        # Set the range of the axis of each plot.

        self.plt.setXRange(t_min, t_max, padding=0.0)
        self.plt.setYRange(b_min, b_max, padding=0.0)

        # Set the PESA-L pen with a width corresponding to one rotation
        # Note: For some reason, the lines are not wide enough unless 5
        #       is added to the scaled width of the rotation time

        rot = 3.05 * self.axs_x.width() / (t_max - t_min) + 5

        self.pen_pl = mkPen(color=(245, 245, 245), width=rot)

        # If the core contains no Wind/MFI magnetic field data, return.

        if (self.core.n_mfi <= 0):
            return

        # Generate and display each curve for the plot.

        self.crv_m = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b,
                                  pen=self.pen_crv_m)
        self.crv_n = PlotDataItem(self.core.mfi_s,
                                  [-b for b in self.core.mfi_b],
                                  pen=self.pen_crv_n)
        self.crv_x = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_x,
                                  pen=self.pen_crv_x)
        self.crv_y = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_y,
                                  pen=self.pen_crv_y)
        self.crv_z = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_z,
                                  pen=self.pen_crv_z)

        # If PESA-L spectra were loaded, add the vertical indicators
        # showing their time relative to the start of the FC spectrum

        for n in range(len(self.core.pl_spec_arr)):

            time = self.core.pl_spec_arr[n]['time'][0]

            t_0 = self.core.fc_spec['time']

            delta_t = (time - t_0).total_seconds()

            self.pl += [
                InfiniteLine(delta_t + self.core.fc_spec['rot'] / 2.,
                             pen=self.pen_pl)
            ]

        for i in range(len(self.pl)):

            self.plt.addItem(self.pl[i])

        self.plt.addItem(self.crv_m)
        self.plt.addItem(self.crv_n)
        self.plt.addItem(self.crv_x)
        self.plt.addItem(self.crv_y)
        self.plt.addItem(self.crv_z)
Exemple #21
0
class MapViewWidget(DynImageView):
    sigShowSpectra = Signal(int)

    def __init__(self, *args, **kwargs):
        super(MapViewWidget, self).__init__(*args, **kwargs)
        # self.scene.sigMouseMoved.connect(self.showSpectra)
        self.scene.sigMouseClicked.connect(self.showSpectra)
        self.view.invertY(True)

        # add arrow
        # self.arrow = ArrowItem(angle=60, headLen=15, tipAngle=45, baseAngle=30, brush = (200, 80, 20))
        # self.arrow.setPos(0, 0)
        self.cross = PlotDataItem([0], [0],
                                  symbolBrush=(200, 0, 0),
                                  symbolPen=(200, 0, 0),
                                  symbol='+',
                                  symbolSize=16)

        self.view.addItem(self.cross)
        self.cross.hide()
        #add txt
        self.txt = TextItem('', anchor=(0, 0))
        self.addItem(self.txt)

    def setEnergy(self, lineobject):
        E = lineobject.value()
        # map E to index
        i = val2ind(E, self.wavenumbers)
        # print('E:', E, 'wav:', self.wavenumbers[i])
        self.setCurrentIndex(i)

    def showSpectra(self, event):

        pos = event.pos()
        if self.view.sceneBoundingRect().contains(
                pos
        ):  # Note, when axes are added, you must get the view with self.view.getViewBox()
            mousePoint = self.view.mapSceneToView(pos)
            x, y = int(mousePoint.x()), int(mousePoint.y())
            y = self.row - y - 1
            try:
                ind = self.rc2ind[(y, x)]
                self.sigShowSpectra.emit(ind)
                # print(x, y, ind, x + y * self.n_col)

                #update arrow
                self.cross.setData([x + 0.5], [self.row - y - 0.5])
                self.cross.show()
                # update text
                self.txt.setHtml(
                    f'<div style="text-align: center"><span style="color: #FFF; font-size: 8pt">X: {x}</div>\
            <div style="text-align: center"><span style="color: #FFF; font-size: 8pt">Y: {y}</div>\
            <div style="text-align: center"><span style="color: #FFF; font-size: 8pt">Point: #{ind}</div>'
                )
            except Exception:
                self.cross.hide()

    def setHeader(self, header: NonDBHeader, field: str, *args, **kwargs):
        self.header = header
        self.field = field

        imageEvent = next(header.events(fields=['image']))
        self.rc2ind = imageEvent['rc_index']
        self.wavenumbers = imageEvent['wavenumbers']
        # make lazy array from document
        data = None
        try:
            data = header.meta_array(field)
            self.row = data.shape[1]
            self.col = data.shape[2]
            self.txt.setPos(self.col, 0)
        except IndexError:
            msg.logMessage(
                'Header object contained no frames with field '
                '{field}'
                '.', msg.ERROR)

        if data is not None:
            # kwargs['transform'] = QTransform(1, 0, 0, -1, 0, data.shape[-2])
            self.setImage(img=data, *args, **kwargs)
            self._data = data

    def updateImage(self, autoHistogramRange=True):
        super(MapViewWidget, self).updateImage(autoHistogramRange)
        self.ui.roiPlot.setVisible(False)

    def setImage(self, img, **kwargs):
        super(MapViewWidget, self).setImage(img, **kwargs)
        self.ui.roiPlot.setVisible(False)

    def makeMask(self, thresholds):
        peak1550 = val2ind(1550, self.wavenumbers)
        thr1550 = thresholds[0]
        mask = self._data[peak1550] > thr1550
        mask = mask.astype(np.int)
        return mask
    return Gematron_proc_obj.get_image(file_path).T


win.add_image_plot_with_axes('Gematron', 'Gematron', gematron_image,
                             [(0, 0), (2048, 2048)], [(0, 0), (2048, 2048)])

for f_rect in Gematron_proc_obj.filter_rects:
    # self.filter_rects.append([(minc, minr), maxc - minc, maxr - minr])
    # arguments for overlaying rectangle as below...
    # rect = mpatches.Rectangle(f_rect[0], f_rect[1], f_rect[2],
    #                         fill=False, edgecolor='red', linewidth=1, ls='--')
    minr, minc, maxr, maxc = f_rect
    xValues = [minc, minc, maxc, maxc, minc]
    yValues = [minr, maxr, maxr, minr, minr]
    win.docks['Gematron'].widgets[0].view.addItem(
        PlotDataItem(xValues, yValues, pen=dict(color='r', dash=[4, 4])))

win.add_scalar_history_plot('Gematron E_c', 'Gematron', HistoryShots,
                            get_E_crit)

win.add_scalar_history_plot('Gematron photons', 'Gematron', HistoryShots,
                            get_beam_N)

win.add_scalar_history_plot('Gematron mean counts', 'Gematron', HistoryShots,
                            get_mean_beam_counts)
server.diag_list.addItem('Gematron')

## dx420 plots


def basic_image(file_path):
    def __init__(self, name, plot_item_data_params, *args, **kwargs):
        """
        Constructor.

        Args:
            name (str): name of plot. Also show in the title section of the
                plot;
            plot_item_data_params (list): dictionary of ``DataBuffer`` and
                respective parameters;
            *args: positional arguments to be passed to ``PlotItem``
                class;
            **kwargs: dictionary to be passed to ``PlotItem`` class.

        """
        mkQApp()
        self.data_buffers = list()
        self._plot_drawing_params = list()
        self._curves_names = []
        self._refresh_activated = True

        self.name = name

        if len(plot_item_data_params) == 1 and (
                "pen" not in plot_item_data_params[0]):
            plot_item_data_params[0]["pen"] = mkPen(color='r')

        if len(plot_item_data_params) > 1:
            for single_params in plot_item_data_params:
                colors = self.get_n_colors(len(plot_item_data_params))
                if "pen" not in single_params:
                    color = colors[plot_item_data_params.index(single_params)]
                    color = list(color)
                    color.append(255)
                    single_params["pen"] = mkPen(color=mkColor(tuple(color)))
                if "name" not in single_params:
                    single_params["name"] = single_params["data_buffer"].name

        for single_params in plot_item_data_params:
            self.data_buffers.append(single_params["data_buffer"])
            self._curves_names.append(single_params["data_buffer"].name)
            single_params.pop("data_buffer", None)
            self._plot_drawing_params.append(single_params)

        kwargs['title'] = self.name

        super().__init__(*args, **kwargs)

        if not isinstance(self.data_buffers, list):
            self.data_buffers = [self.data_buffers]

        self.plot_data_items_list = list()
        if self._plot_drawing_params is not None:
            for data_buffer, plot_drawing_param in zip(
                    self.data_buffers, self._plot_drawing_params):
                self.plot_data_items_list.append(
                    PlotDataItem(data_buffer.get(), **plot_drawing_param))
        else:
            for data_buffer, plot_drawing_param in zip(
                    self.data_buffers, self._plot_drawing_params):
                self.plot_data_items_list.append(
                    PlotDataItem(data_buffer.get(), **plot_drawing_param))

        if self.len_curves > 1:
            self.addLegend()
	def make_crv( self ) :

		# If no "list" of "p" index-values has been provided by the
		# user, assume that the curves in all plots should be
		# (re-)rendered.

		if ( self.core.pl_spec_arr == [] ) :
			return

		# If the index of this P-L grid is outside the bounds of the P-L
		# spectrum currently loaded, abort.

		if ( self.n >= len( self.core.pl_spec_arr ) ) : return

		# Return the "nln_psd_gss_ion axes to their original order.

		if( self.core.nln_psd_gss_ion is not None ) :

			if( self.core.nln_psd_gss_ion != [ ] ) :

				nln_psd_gss_ion = [ [ [ [ [
				self.core.nln_psd_gss_ion[n][t][f][b][p]
				for b in range( self.core.pl_spec_arr[n]['n_bin'] ) ]
				for f in range( self.core.pl_spec_arr[n]['n_phi'] ) ]
				for t in range( self.core.pl_spec_arr[n]['n_the'] ) ]
				for n in range( len( self.core.pl_spec_arr      ) ) ]
				for p in range( self.core.nln_gss_n_pop           ) ]

		# Return the "nln_res_psd_ion axes to their original order.

		if( self.core.nln_res_psd_ion is not None ) :

			if( self.core.nln_res_psd_ion != [ ] ) :

				nln_res_psd_ion = [ [ [ [ [
				self.core.nln_res_psd_ion[n][t][f][b][p]
				for b in range( self.core.pl_spec_arr[n]['n_bin'] ) ]
				for f in range( self.core.pl_spec_arr[n]['n_phi'] ) ]
				for t in range( self.core.pl_spec_arr[n]['n_the'] ) ]
				for n in range( len( self.core.pl_spec_arr      ) ) ]
				for p in range( self.core.nln_gss_n_pop           ) ]

		# For each plot in the grid, generate and display a fit curve
		# based on the results of the analysis.

		vel_cen = self.core.pl_spec_arr[self.n]['vel_cen']

		for t in range( self.core.pl_spec_arr[self.n]['n_the'] ) :

			for p in range( self.core.pl_spec_arr[self.n]['n_phi'] ) :

				# If this plot does not exist, move onto the next grid
				# element.

				if ( self.plt[t,p] is None ) :
					continue

				# If any curves already exist for this plot, remove and
				# delete them.

				if ( self.crv[t,p] is not None ) :
					self.plt[t,p].removeItem( self.crv[t,p] )
					self.crv[t,p] = None

				for n in range( self.n_ion ) :
					if ( self.crv_ion[t,p,n] is not None ) :
						self.plt[t,p].removeItem(
						                   self.crv_ion[t,p,n] )
						self.crv_ion[t,p,n] = None

				# Create and add the curve of the indiviadual
				# contributions to the modeled psd to the plot.

				for n in range( ( 1 if self.core.dsp == 'mom' else self.core.nln_gss_n_pop ) ) :

					# Extract the points for this fit curve.

					x = array( vel_cen )

					if( self.core.dsp == 'mom' ) :

						y = array( self.core.pl_spec_arr[self.n]['psd_mom'][t][p] )

					elif( self.core.dsp == 'gsl' ) :

						y = array( nln_psd_gss_ion[n][self.n][t][p] )

					elif( self.core.dsp == 'nln' ) :

						y = array( nln_res_psd_ion[n][self.n][t][p] )

					# If any points are 0 or None, set them
					# to an arbitrary minimum value

					for tk in range(len(y)):
						if ( ( y[tk] == 0    ) or
						     ( y[tk] is None )    ) :
							y[tk] = 1e-20

					if ( self.log_x ) :
						ax = log10( x )
					else :
						ax = x

					if ( self.log_y ) :
						ay = array( [ log10( v )
						              for v in y ] )
					else :
						ay = y

					# Create, store, and add to the plot
					# this fit curve.

					self.crv_ion[t,p,n] = PlotDataItem(
					            ax, ay, pen=( self.pen_crv_b if self.core.dsp=='mom' else self.pen_crv_g ) )

					self.plt[t,p].addItem(
					                   self.crv_ion[t,p,n] )

				# If applicable, create and add the curve of the
				# total contributions to the modeled psd to the
				# plot

				if( self.core.dsp == 'gsl' ) :

					x = array( vel_cen )

					y = array( self.core.nln_psd_gss_tot[self.n][t][p] )

					# If any points are 0 or None, set them
					# to an arbitrary minimum value

					for tk in range(len(y)):
						if ( ( y[tk] == 0    ) or
						     ( y[tk] is None )    ) :
							y[tk] = 1e-20

					if ( self.log_x ) :
						ax = log10( x )
					else :
						ax = x

					if ( self.log_y ) :
						ay = array( [ log10( v )
						              for v in y ] )
					else :
						ay = y

					# Create, store, and add to the plot
					# this fit curve.

					self.crv[t,p] = PlotDataItem(
					            ax, ay, pen=( self.pen_crv_b ) )

					self.plt[t,p].addItem(
					                   self.crv[t,p] )

				# If applicable, create and add the curve of the
				# total contributions to the non-linear psd to
				# the plot

				if( ( self.core.dsp == 'nln' ) and
				    ( self.core.nln_res_psd_tot is not None ) ) :

					x = array( vel_cen )

					y = array( self.core.nln_res_psd_tot[self.n][t][p] )

					# If any points are 0 or None, set them
					# to an arbitrary minimum value

					for tk in range(len(y)):
						if ( ( y[tk] == 0    ) or
						     ( y[tk] is None )    ) :
							y[tk] = 1e-20

					if ( self.log_x ) :
						ax = log10( x )
					else :
						ax = x

					if ( self.log_y ) :
						ay = array( [ log10( v )
						              for v in y ] )
					else :
						ay = y

					# Create, store, and add to the plot
					# this fit curve.

					self.crv[t,p] = PlotDataItem(
					            ax, ay, pen=( self.pen_crv_b ) )

					self.plt[t,p].addItem(
					                   self.crv[t,p] )
Exemple #25
0
    def show_solution(self, task):
        """:param task: объект модели TaskModel"""
        self.plotter.plotItem.clear()
        self.plotter.plotItem.legend.clear()
        self.coefs = task.inequalities_coefs.split(',')
        self.consts = task.inequalities_consts.split(',')
        try:
            solver = Solver(task)
        except AttributeError:
            QMessageBox.warning(
                self, 'Ошибка!', 'Похоже, у задачи заполнены не все данные. '
                'Проверьте правильность входных данных.')
            return
        self.mark = '&ge;' if solver.lim == TaskModel.LIM_ZERO else '&le;'
        for i, constraint in enumerate(solver.get_constraints()[:, :, ::-1]):
            pen = self.plotter.pen()
            if constraint[0][1] == np.inf:
                self.plotter.addLine(constraint[1][0], angle=90, pen=pen)
                self.plotter.plotItem.legend.addItem(
                    PlotDataItem(pen=pen), name=self.render_constraint(i))

            elif constraint[1][0] == np.inf:
                self.plotter.addLine(constraint[0][1], angle=0, pen=pen)
                self.plotter.plotItem.legend.addItem(
                    PlotDataItem(pen=pen), name=self.render_constraint(i))

            else:
                self.plotter.plot(x=constraint[:, ::2].ravel(),
                                  y=constraint[:, 1::2].ravel(),
                                  name=self.render_constraint(i),
                                  pen=self.plotter.pen())
        bounds = solver.get_bounds(5, 0)
        self.plotter.plotItem.vb.setLimits(**bounds)
        try:
            point, opt_value = solver.solve()
        except NoSolutionError:
            QMessageBox.warning(
                self, 'Ошибка!',
                'Похоже, у задачи нет решения. Проверьте правильность входных данных.'
            )
            return
        except SolverException as e:
            QMessageBox.warning(
                self, 'Ошибка!',
                f'К сожалению, задачу решить не удалось.\nПричина: {e}')
            return
        except Exception as e:
            QMessageBox.warning(
                self, 'Непредвиденная ошибка!',
                f'В ходе решения произошла непредвиденная ошибка {e}')
            return
        if solver.lim == TaskModel.LIM_INF:
            p_points = solver.get_possible_points()
            if len(p_points) > 2:
                self.plotter.plot(x=tuple(p_points.keys()),
                                  y=tuple(p_points.values()),
                                  brush=QColor(0, 0, 255, 90),
                                  pen=None,
                                  fillLevel=bounds['xMin'] if solver.lim
                                  == TaskModel.LIM_INF else bounds['xMax'])
        self.plotter.plot(
            x=[0, opt_value / solver.coefs[0] * solver.lim],
            y=[opt_value / solver.coefs[1] * solver.lim, 0],
            pen=self.plotter.pen('r'),
            name=
            '<p style="font-size: 12pt; font-family:Georgia, \'Times New Roman\', '
            'Times, serif">Целевая функция, проходящая через точку '
            f'А({point[0]:.2g}, {point[1]:.2g})</p>')
        self.plotter.plot(
            x=[point[0]],
            y=[point[1]],
            symbol='+',
            symbolSize=20,
            symbolBrush='b',
            symbolPen=None,
            pen=None,
            name=
            '<p style="font-size: 12pt; font-family:Georgia, \'Times New Roman\', '
            f'Times, serif">Оптимальное значение ЦФ ({opt_value:.2g})</p>')
        super().show()
Exemple #26
0
    def make_crv(self, p_lst=None):

        # If no "list" of "p" index-values has been provided by the
        # user, assume that the curves in all plots should be
        # (re-)rendered.

        if (p_lst is None):
            p_lst = range(min(self.core.n_azm, self.n_plt))

        # If the results of the analysis are missing, abort; otherwise,
        # extract the current values to be plotted.

        if (self.core.dsp == 'mom'):
            cur = self.core.mom_cur
            cur_ion = None
        elif (self.core.dsp == 'gsl'):
            cur = self.core.nln_gss_cur_tot
            cur_ion = self.core.nln_gss_cur_ion
        elif (self.core.dsp == 'nln'):
            cur = self.core.nln_res_cur_tot
            cur_ion = self.core.nln_res_cur_ion
        else:
            cur = None
            cur_ion = None

        # For each plot in the grid, generate and display a fit curve
        # based on the results of the analysis.

        for p in p_lst:

            # Determine the location of this plot within the grid
            # layout.

            j = self.calc_ind_j(p)
            i = self.calc_ind_i(p)

            # If this plot does not exist, move onto the next grid
            # element.

            if (self.plt[j, i] is None):
                continue

            # If any curves already exist for this plot, remove and
            # delete them.

            if (self.crv[j, i] is not None):
                self.plt[j, i].removeItem(self.crv[j, i])
                self.crv[j, i] = None

            for n in range(self.n_ion):
                if (self.crv_ion[j, i, n] is not None):
                    self.plt[j, i].removeItem(self.crv_ion[j, i, n])
                    self.crv_ion[j, i, n] = None

            # Create and add the curve of the individual
            # contributions to the modeled current to the plot.

            if (cur_ion is not None):

                for n in range(len(cur_ion[self.t, p, 0, :])):

                    # Extract the points for this fit curve.

                    x = self.core.vel_cen
                    y = cur_ion[self.t, p, :, n]

                    # Select only those points for which
                    # the fit current is strictly positive.

                    tk = where(y > 0.)[0]

                    # If fewer than two curve points were
                    # selected, skip plotting this curve.

                    if (len(tk) < 2):
                        continue

                    # Generate the adjusted points for this
                    # curve.

                    if (self.log_x):
                        ax = log10(x[tk])
                    else:
                        ax = x[tk]

                    if (self.log_y):
                        ay = log10(y[tk])
                    else:
                        ay = y[tk]

                    # Create, store, and add to the plot
                    # this fit curve.

                    self.crv_ion[j, i, n] = PlotDataItem(ax,
                                                         ay,
                                                         pen=self.pen_crv_g)

                    self.plt[j, i].addItem(self.crv_ion[j, i, n])

            # Create, store, and add to the plot a curve for the
            # total fit current.

            if (cur is not None):

                # Extract the points of the fit curve.

                x = self.core.vel_cen
                y = cur[self.t, p, :]

                # Select only those points for which the fit
                # current is strictly positive.

                tk = where(y > 0.)[0]

                # If at least two points were selected, proceed
                # with plotting.

                if (len(tk) >= 2):

                    # Generate the adjusted points for this
                    # curve.

                    if (self.log_x):
                        ax = log10(x[tk])
                    else:
                        ax = x[tk]

                    if (self.log_y):
                        ay = log10(y[tk])
                    else:
                        ay = y[tk]

                    # Create, store, and add to the plot
                    # this fit curve.

                    self.crv[j, i] = PlotDataItem(ax, ay, pen=self.pen_crv_b)

                    self.plt[j, i].addItem(self.crv[j, i])
class makeTimeseriesCurveNode(NodeWithCtrlWidget):
    """Prepare Timeseries for plotting. Generate curve that can be viewed with node *TimeseriesPlot*
    and pd.Series with datetime stored in Index
    """
    nodeName = "Make Curve"
    uiTemplate = [
        {'name': 'Y:signal', 'type': 'list', 'value': None, 'default': None, 'values': [None], 'tip': 'Signal Data-Values (Y-axis)'},
        {'name': 'X:datetime', 'type': 'list', 'value': None, 'default': None, 'values': [None], 'tip': 'Datetime Values (X-axis)'},
        {'name': 'tz correct', 'type': 'float', 'value': 0, 'default': 0, 'suffix': ' hours', 'tip': '<float>\nONLY FOR CURVE!!!\nTimezone correction\nNumber of hours to add/substract from result. Due to missing\ntimezone settings it may be nessesary to use this parameter.\nCheck the results manually with *TimeseriesPlot* Node'},
        {'name': 'color', 'type': 'color', 'tip': 'Curve color'},
        {'name': 'Display Line', 'type': 'bool', 'value': True, 'tip': 'display line-curve between data points', 'children': [
            {'name': 'Style', 'type': 'list', 'tip': 'Style', 'values':
                {'solid': QtCore.Qt.SolidLine,
                 'dash': QtCore.Qt.DashLine,
                 'dash-dot': QtCore.Qt.DashDotLine,
                 'dot-dot': QtCore.Qt.DotLine,
                 'dash-dot-dot': QtCore.Qt.DashDotDotLine }},
            {'name': 'Linewidth', 'type': 'float', 'value': 1., 'limits': (0., 20.), 'step': 0.1,  'tip': 'Linewidth'},
        ]},
        {'name': 'Display Data Points', 'type': 'bool', 'value': False, 'tip': 'display data points as scatter', 'children': [
            {'name': 'Symbol', 'type': 'list', 'tip': 'Symbol for data points', 'value': 'o', 'values':
                {'circle': 'o',
                 'triangle': 't',
                 'square': 's',
                 'pentagon': 'p',
                 'hexagon': 'h',
                 'star': 'star',
                 'cross': '+',
                 'diamond': 'd'}},
            {'name': 'Size', 'type': 'int', 'value': 5, 'limits': (0, 1000), 'tip': 'Symbol size'},
        ]},
        ]

    def __init__(self, name, parent=None):
        super(makeTimeseriesCurveNode, self).__init__(name, parent=parent, terminals={'df': {'io': 'in'}, 'pd.Series': {'io': 'out'}, 'Curve': {'io': 'out'}}, color=(150, 150, 250, 150))
        self._plotRequired = False
        self.item = PlotDataItem(clipToView=False)
    
    def _createCtrlWidget(self, **kwargs):
        return makeTimeseriesCurveNodeCtrlWidget(**kwargs)
        
    def process(self, df):
        if df is None:
            del self.item
            self.item = None
            return {'Curve': None, 'pd.Series': None }
        if self.item is None:
            self.item = PlotDataItem(clipToView=False)

        colname = [col for col in df.columns if isNumpyNumeric(df[col].dtype)]
        self._ctrlWidget.param('Y:signal').setLimits(colname)
        colname = [col for col in df.columns if isNumpyDatetime(df[col].dtype)]
        self._ctrlWidget.param('X:datetime').setLimits(colname)

        with BusyCursor():
            kwargs = self.ctrlWidget().prepareInputArguments()
            
            #self.item = PlotDataItem(clipToView=False)
            t = df[kwargs['X:datetime']].values
            # part 1
            timeSeries = pd.DataFrame(data=df[kwargs['Y:signal']].values, index=t, columns=[kwargs['Y:signal']])

            # part 2
            #   convert time
            b = t.astype(np.dtype('datetime64[s]'))
            timeStamps = b.astype(np.int64)-kwargs['tz correct']*60*60+time.timezone
            #   now create curve
            pen = fn.mkPen(color=kwargs['color'], width=kwargs['width'], style=kwargs['style'])
            self.item.setData(timeStamps, df[kwargs['Y:signal']].values, pen=pen, name=kwargs['Y:signal'])
            
            self.item.setSymbol(kwargs['symbol'])
            if kwargs['symbol'] is not None:
                self.item.setSymbolPen(kwargs['color'])
                self.item.setSymbolBrush(kwargs['color'])
                self.item.setSymbolSize(kwargs['symbolSize'])
        return {'Curve': self.item, 'pd.Series': timeSeries }
Exemple #28
0
	def make_crv( self, d_lst=None ) :

		# If no "list" of "p" index-values has been provided by the
		# user, assume that the curves in all plots should be
		# (re-)rendered.

		if ( self.core.fc_spec is None ) :
			return

		if ( d_lst is None ) :
			d_lst = range( min( self.core.fc_spec['n_dir'],
			               self.n_plt                       ) )

		# If the results of the analysis are missing, abort; otherwise,
		# extract the current values to be plotted.

		if ( self.core.dsp == 'mom' ) :
			curr     = self.core.mom_curr
			curr_ion = None
		elif ( self.core.dsp == 'gsl' ) :
			curr     = self.core.nln_gss_curr_tot
			curr_ion = self.core.nln_gss_curr_ion
		elif ( self.core.dsp == 'nln' ) :
			curr     = self.core.nln_res_curr_tot
			curr_ion = self.core.nln_res_curr_ion
		else :
			curr     = None
			curr_ion = None

		# For each plot in the grid, generate and display a fit curve
		# based on the results of the analysis.

		vel_cen = self.core.fc_spec['vel_cen'][self.c]

		for d in d_lst :

			# Determine the location of this plot within the grid
			# layout.

			j = self.calc_ind_j( d )
			i = self.calc_ind_i( d )

			# If this plot does not exist, move onto the next grid
			# element.

			if ( self.plt[j,i] is None ) :
				continue

			# If any curves already exist for this plot, remove and
			# delete them.

			if ( self.crv[j,i] is not None ) :
				self.plt[j,i].removeItem( self.crv[j,i] )
				self.crv[j,i] = None

			for n in range( self.n_ion ) :
				if ( self.crv_ion[j,i,n] is not None ) :
					self.plt[j,i].removeItem(
					                   self.crv_ion[j,i,n] )
					self.crv_ion[j,i,n] = None

			# Create and add the curve of the individual
			# contributions to the modeled current to the plot.

			if ( curr_ion is not None ) :

				for n in range( len( curr_ion[self.c][d][0] ) ) :

					# Extract the points for this fit curve.

					x = array( vel_cen )
					y = array( [ curr_ion[self.c][d][b][n]
					      for b in range(
					        self.core.fc_spec['n_bin'] ) ] )

					# Select only those points for which
					# the fit current is strictly positive.

					tk = where( y > 0. )[0]

					# If fewer than two curve points were
					# selected, skip plotting this curve.

					if ( len( tk ) < 2 ) :
						continue

					# Generate the adjusted points for this
					# curve.

					if ( self.log_x ) :
						ax = log10( x[tk] )
					else :
						ax = x[tk]

					if ( self.log_y ) :
						ay = log10( y[tk] )
					else :
						ay = y[tk]

					# Create, store, and add to the plot
					# this fit curve.

					self.crv_ion[j,i,n] = PlotDataItem(
					            ax, ay, pen=self.pen_crv_g )

					self.plt[j,i].addItem(
					                   self.crv_ion[j,i,n] )

			# Create, store, and add to the plot a curve for the
			# total fit current.

			if ( curr is not None ) :

				# Extract the points of the fit curve.

				x = [ self.core.fc_spec.arr[self.c][0][b][
				                                    'vel_cen']
				      for b in range(
				                  self.core.fc_spec['n_bin'] ) ]

				y = curr[self.c][d]

				x = array( x )
				y = array( y )

				# Select only those points for which the fit
				# current is strictly positive.

				valid = [ yy > 0. for yy in y ]

				n_a = sum( valid )

				ax = [ xx for xx, vv in zip( x, valid ) if vv ]
				ay = [ yy for yy, vv in zip( y, valid ) if vv ]

				# If at least two points were selected, proceed
				# with plotting.

				if ( n_a >= 2 ) :

					# If needed, convert to a logarithmic
					# scale.

					if ( self.log_x ) :
						ax = [ log10( xx )
						       for xx in ax ]
					if ( self.log_y ) :
						ay = [ log10( yy )
					               for yy in ay ]

					# Create, store, and add to the plot
					# this fit curve.

					self.crv[j,i] = PlotDataItem(
					            ax, ay, pen=self.pen_crv_b )

					self.plt[j,i].addItem( self.crv[j,i] )
Exemple #29
0
 def __init__(self, name):
     CtrlNode.__init__(self, name, terminals={"x": {"io": "in"}, "y": {"io": "in"}, "plot": {"io": "out"}})
     self.item = PlotDataItem()
Exemple #30
0
class ScanPlot(PlotItem):
    # scan is the scan json object
    def __init__(self,parent,scan):
        # name of independent variable
        input = scan[INPUT]
        x_label = input.get(NAME,'input')
        x_units = input.get(UNITS,'arb')
        # name of dependent variable
        output = scan[OUTPUT]
        if type(output) is dict:
            y_label = output.get(NAME,'output')
            y_units = output.get(UNITS,'arb')       
        else:
            y_label = 'output'
            y_units = 'arb'
        # scan title
        title = scan.get(
            NAME,
            '%s vs. %s' % (y_label,x_label)
        )
        labels = {
            'bottom':'%s (%s)' % (x_label,x_units),
            'left':'%s (%s)' % (y_label,y_units)
        }
        # initialize pyqtgraph plot item with title and axis labels
        PlotItem.__init__(
            self,
            title = title,
            labels = labels
        )
        # are we setting input to optimal value of scan result?
        self.optimizing = scan.get(OPTIMIZE,False)
        # if we have multiple outputs and are optimizing, which output to optimize?
        self.checking_optimize = scan.get(CHECK_OPTIMIZE,False)
        self.click_deferred = None
        self.optimize_axis = scan.get(OPTIMIZE_AXIS,0)
        # are we saving scan data to datavault?
        self.saving = scan.get(SAVE,False)
        # are we returning to input's original position after scan?
        self.returning = scan.get(RETURN,False)
        self.scan = scan
        self.__parent = parent

    def mouseClickEvent(self,event):
        if self.click_deferred is not None:
            self.click_deferred.callback(self.getViewBox().mapSceneToView(event.scenePos()).x())
            event.accept()
            self.click_deferred = None
        else:
            PlotItem.mouseClickEvent(self,event)

    # performs set up for scan
    def start(self):
        return self.set_scan_items()
    
    @inlineCallbacks
    def set_scan_items(self):
        scan = self.scan
        outputs = scan[OUTPUT]
        if type(outputs) is dict:
            outputs = [outputs]
        if self.is_saving():
            # get labrad connection
            cxn = yield connectAsync()
            # get handle to data vault
            data_vault = cxn.data_vault
            # list of folders (trunk to leaf) for dataset directory
            save_dir = scan.get(SAVE_DIR,[])
            # go to scans dir in dv
            yield data_vault.cd(data_vault_dir+save_dir,True)
            independent_variables = [
                '%s [%s]' % (
                    scan[INPUT].get(NAME,'input'),
                    scan[INPUT].get(UNITS,'arb')
                )
            ]
            dependent_variables = [
                '%s [%s]' % (
                    output.get(NAME,'output'),
                    output.get(UNITS,'arb')
                ) for output in outputs
            ]
            save_name = scan.get(SAVE_NAME,None)
            default_name = text=scan.get(NAME,'')
            if save_name is None:
                save_name, result = QtGui.QInputDialog.getText(
                    self.__parent,
                    'enter dataset name',
                    'enter title for data vault dataset',
                    text = default_name
                )
                if not result:
                    save_name = default_name
            # create new dataset                
            yield data_vault.new(
                str(save_name),
                independent_variables,
                dependent_variables
            )
            # make note of dataset creation
            yield data_vault.add_parameter(
                'time',
                get_datetime()
            )
            self.data_vault = data_vault
        # instantiate scan input object
        self.input = INPUTS[
            scan[INPUT][CLASS]
        ](
            **mangle(scan[INPUT].get(ARGS,{}))
        )
        # note initial position if we are planning to return to it after scan
        if self.is_returning():
            self._return_input = yield self.input._get_input()
        # instantiate scan output object
        self.outputs = [
            OUTPUTS[
                output[CLASS]
            ](
                **mangle(output.get(ARGS,{}))
            ) for output in outputs
        ]
        # intialize x and y values
        self.x_data = []
        self.y_datas = []
        # clear any stuff that happens to be in plot (TODO: do we ever scan the same object twice?)
        for item in self.allChildItems():
            self.removeItem(item)            
        # if optimizing or have multiple sources, \
        # add legend to distinguish different sources
        if self.is_optimizing() or len(outputs) > 1:
            self.addLegend()
        if self.is_optimizing():
            # initialize fit curve
            self.fit_curve = PlotDataItem(
                name='fit (%s)' % outputs[
                    self.optimize_axis
                ].get(
                    NAME,
                    'output %d' % (self.optimize_axis+1)
                ),
                pen={'color':'BBB','width':2}
            )
        # initialize data curves
        self.curves = [
            self.plot(
                name=output.get(NAME,'output %d' % (index + 1)),
                pen=None,
                symbolSize=5,
                symbolPen=None,
                symbolBrush=('F55','5F5','55F','FF5','5FF','F5F')[index % 6]
            ) for index, output in enumerate(outputs)
        ]

    def show_fit(self):
        self.addItem(self.fit_curve)

    # put input back to initial position
    def return_input(self):
        return self.input.set_input(self._return_input)

    # called to increment scan by one step
    @inlineCallbacks
    def step(self):
        # ask input for next x value
        x = yield self.input.get_input()
        # check if scan input is done and err if so
        if x is None:
            returnValue(False)
        y = []
        output_deferreds = [
            output.get_output() for output in self.outputs
        ]
        for deferred in output_deferreds:
            y_value = yield deferred
            y.append(y_value)
        # add new values to data arrays
        self.x_data.append(x)
        self.y_datas.append(y)        
        # update dataset with new datapoint if saving
        if self.is_saving():
            yield self.data_vault.add([x]+y)
        for curve, y_data in zip(self.curves,zip(*self.y_datas)):
            # update data curve
            curve.setData(self.x_data,y_data)
        # indicate successful step
        returnValue(True)

    def is_optimizing(self):
        return self.optimizing

    def is_saving(self):
        return self.saving

    def is_returning(self):
        return self.returning    

    # fit data to gaussian to find input value that optimizes output and set input to that value
    @inlineCallbacks
    def optimize_input(self):        
        x_arr = np.array(self.x_data)
        y_arr = np.array(zip(*self.y_datas)[self.optimize_axis])
        params = self.estimate_gaussian_parameters(
            x_arr,y_arr
        )
        try:
            params, _ = curve_fit(
                self.gaussian,
                x_arr,
                y_arr,
                params
            )
        except RuntimeError:
            pass
        x_fit = np.linspace(x_arr.min(),x_arr.max(),FIT_POINTS)            
        self.fit_curve.setData(
            x_fit,
            self.gaussian(x_fit,*params)
        )
        if self.fit_curve not in self.listDataItems():
            self.show_fit()
            input = int(np.round(params[0]))
            if self.checking_optimize:                
                result = QtGui.QMessageBox.question(
                    self.__parent,
                    'check optimize',
                    'is optimize result of %d ok?' % input,
                    QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
                )
                if result == QtGui.QMessageBox.No:
                    message_box = QtGui.QMessageBox(self.__parent)
                    click_button = message_box.addButton('click',QtGui.QMessageBox.AcceptRole)
                    enter_button = message_box.addButton('enter',QtGui.QMessageBox.RejectRole)
                    message_box.setText('specify how to enter location')
                    message_box.setInformativeText('click location on graph or enter in value?')
                    message_box.exec_()
                    if message_box.clickedButton() == click_button:
                        self.click_deferred = Deferred()
                        input = yield self.click_deferred
                        input = int(np.round(input))
                    else:
                        new_input, result = QtGui.QInputDialog.getInt(
                            self.__parent,
                            'enter location',
                            'location',
                            input
                        )
            yield self.input.set_input(input)

    @staticmethod
    def gaussian(x,mean,std,amplitude,offset):
        return amplitude * np.exp(- 1. / 2. * np.square( ( x - mean ) / std) ) + offset

    @staticmethod
    def estimate_gaussian_parameters(x,y):
        min = y.min()
        max = y.max()
        offset = min
        amplitude = max - min
        mean_index = y.argmax()
        mean = x[mean_index]
        threshold = min + (max - min) / 2
        right_estimate = None
        index = mean_index
        while True:
            if index == len(y):
                break
            if y[index] < threshold:
                right_estimate = abs(x[index] - mean) / 2.355 * 2
            index += 1
        left_estimate = None
        index = mean_index
        while True:
            if index < 0:
                break
            if y[index] < threshold:
                left_estimate = abs(x[index] - mean) / 2.355 * 2
            index -= 1
        if right_estimate is None and left_estimate is None:
            std = abs(x[len(y)/2]-x[0])
        elif right_estimate is None:
            std = left_estimate
        elif left_estimate is None:
            std = right_estimate
        else:
            std = ( left_estimate + right_estimate ) / 2.
        return (mean,std,amplitude,offset)
Exemple #31
0
 def set_scan_items(self):
     scan = self.scan
     outputs = scan[OUTPUT]
     if type(outputs) is dict:
         outputs = [outputs]
     if self.is_saving():
         # get labrad connection
         cxn = yield connectAsync()
         # get handle to data vault
         data_vault = cxn.data_vault
         # list of folders (trunk to leaf) for dataset directory
         save_dir = scan.get(SAVE_DIR,[])
         # go to scans dir in dv
         yield data_vault.cd(data_vault_dir+save_dir,True)
         independent_variables = [
             '%s [%s]' % (
                 scan[INPUT].get(NAME,'input'),
                 scan[INPUT].get(UNITS,'arb')
             )
         ]
         dependent_variables = [
             '%s [%s]' % (
                 output.get(NAME,'output'),
                 output.get(UNITS,'arb')
             ) for output in outputs
         ]
         save_name = scan.get(SAVE_NAME,None)
         default_name = text=scan.get(NAME,'')
         if save_name is None:
             save_name, result = QtGui.QInputDialog.getText(
                 self.__parent,
                 'enter dataset name',
                 'enter title for data vault dataset',
                 text = default_name
             )
             if not result:
                 save_name = default_name
         # create new dataset                
         yield data_vault.new(
             str(save_name),
             independent_variables,
             dependent_variables
         )
         # make note of dataset creation
         yield data_vault.add_parameter(
             'time',
             get_datetime()
         )
         self.data_vault = data_vault
     # instantiate scan input object
     self.input = INPUTS[
         scan[INPUT][CLASS]
     ](
         **mangle(scan[INPUT].get(ARGS,{}))
     )
     # note initial position if we are planning to return to it after scan
     if self.is_returning():
         self._return_input = yield self.input._get_input()
     # instantiate scan output object
     self.outputs = [
         OUTPUTS[
             output[CLASS]
         ](
             **mangle(output.get(ARGS,{}))
         ) for output in outputs
     ]
     # intialize x and y values
     self.x_data = []
     self.y_datas = []
     # clear any stuff that happens to be in plot (TODO: do we ever scan the same object twice?)
     for item in self.allChildItems():
         self.removeItem(item)            
     # if optimizing or have multiple sources, \
     # add legend to distinguish different sources
     if self.is_optimizing() or len(outputs) > 1:
         self.addLegend()
     if self.is_optimizing():
         # initialize fit curve
         self.fit_curve = PlotDataItem(
             name='fit (%s)' % outputs[
                 self.optimize_axis
             ].get(
                 NAME,
                 'output %d' % (self.optimize_axis+1)
             ),
             pen={'color':'BBB','width':2}
         )
     # initialize data curves
     self.curves = [
         self.plot(
             name=output.get(NAME,'output %d' % (index + 1)),
             pen=None,
             symbolSize=5,
             symbolPen=None,
             symbolBrush=('F55','5F5','55F','FF5','5FF','F5F')[index % 6]
         ) for index, output in enumerate(outputs)
     ]
Exemple #32
0
	def make_hst( self, curr_min=0.69 ) :

		# If no spectrum has been loaded, clear any existing histograms
		# and abort.

		if ( self.core.fc_spec is None ) :

			self.rset_hst( )

			return

		# Use the spectral data to compute new axis-limits.

		self.make_lim( )

		# Generate a step function for each look direction associated
		# with this widget.

		self.stp = array( [ step(  self.core.fc_spec['vel_cen'][self.c] ,
					   self.core.fc_spec['vel_del'][self.c] ,
					   self.core.fc_spec['curr'][self.c][d])
						for d in range(self.core.fc_spec['n_dir']) ])

		stp_pnt = array( [ array( self.stp[d]\
		                              .calc_pnt( lev_min=curr_min ) )
		                for d in range( self.core.fc_spec['n_dir'] ) ] )

		self.stp_x = stp_pnt[:,0,:]
		self.stp_y = stp_pnt[:,1,:]

		self.asp_x = log10( self.stp_x ) if ( self.log_x ) else \
		                    self.stp_x
		self.asp_y = log10( self.stp_y ) if ( self.log_y ) else \
		                    self.stp_y

		# Adjust the individual axes to the new limits.

		for i in range( self.n_plt_x ) :
			self.axs_x[i].setRange( self.alm_x[0], self.alm_x[1] )

		for j in range( self.n_plt_y ) :
			self.axs_y[j].setRange( self.alm_y[0], self.alm_y[1] )

		# For each plot in the grid, adjust its limits, add a histogram,
		# and add a direction label.

		for d in range( min( self.core.fc_spec['n_dir'], self.n_plt ) ) :

			# Determine the location of this plot within the grid
			# layout.

			j = self.calc_ind_j( d )
			i = self.calc_ind_i( d )

			# If this plot does not exist, move onto the next one.

			if ( self.plt[j,i] is None ) :
				continue

			# If a histogram already exists for this plot, remove
			# and delete it.

			if ( self.hst[j,i] is not None ) :
				self.plt[j,i].removeItem( self.hst[j,i] )
				self.hst[j,i] = None

			# Clear this plot's label of text.

			self.lbl[j,i].setText( '' )

			# Adjust this plot's limits and then move it's label in
			# response.

			self.plt[j,i].setRange( xRange=self.alm_x,
			                        yRange=self.alm_y,
			                        padding=0.         )

			self.lbl[j,i].setPos( self.alm_x[1], self.alm_y[1] )

			# Update this plot's label with appropriate text
			# indicating the pointing direction.

			r_alt = round( self.core.fc_spec['elev'][self.c] )
			r_dir = round( self.core.fc_spec['azim'][self.c][d])

			txt = ( u'({0:+.0f}\N{DEGREE SIGN}, ' + 
			        u'{1:+.0f}\N{DEGREE SIGN})'     ).format(
			                                          r_alt, r_dir )

			self.lbl[j,i].setText( txt, color=(0,0,0) )
			#self.lbl[j,i].setFont( self.fnt           )

			# Generate the histogram for the data from this look
			# direction and display it in the plot.

			self.hst[j,i] = PlotDataItem( self.asp_x[d,:],
			                              self.asp_y[d,:],
			                              pen=self.pen_hst )

			self.plt[j,i].addItem( self.hst[j,i] )
	def chng_pnt( self, t, p, b, sel_bin, sel_alt=None ) :

		# If no spectrum has been loaded, abort.

		if ( self.core.pl_spec_arr == [] ) : return

		# If the index of this P-L grid is outside the bounds of the P-L
		# spectrum currently loaded, abort.

		if ( self.n >= len( self.core.pl_spec_arr ) ) : return

		# If this point already exists, remove it from its plot and
		# delete it.

		if ( self.pnt[t,p,b] is not None ) :
			self.plt[t,p].removeItem( self.pnt[t,p,b] )
			self.pnt[t,p,b] = None

		# If this point was not selected (based on both its primary and
		# secondary states), return (since there's nothing more to be
		# done).

		if ( not sel_bin or self.core.pl_spec_arr[self.n]['psd'][t][p][b] == 0) :
			return

		# Determine the "d" index corresponding to this look direction.

		d = p + ( t * self.n_plt_x )

		# Computed the adjusted point location in the "ViewBox".

		if ( self.log_x ) :
			ax = log10( self.core.pl_spec_arr[self.n]['vel_cen'][b] )
		else :
			ax = self.core.pl_spec_arr[self.n]['vel_cen'][b]
		if ( self.log_y ) :
			ay = log10( self.core.pl_spec_arr[self.n]['psd'][t][p][b] )
		else :
			ay = self.core.pl_spec_arr[self.n]['psd'][t][p][b]

		# Select the color for the point (i.e., the brush and pen used
		# to render it) based on whether or not this datum's look
		# direction has been selected and whether or not the primary and
		# secondary selection states match.

#		if ( sel_bin == sel_alt ) :
		pen   = self.pen_pnt_c
		brush = self.bsh_pnt_c
#		else :
#			pen   = self.pen_pnt_y
#			brush = self.bsh_pnt_y
#		else :
#			pen   = self.pen_pnt_r
#			brush = self.bsh_pnt_r

		# Select the symbol based on the values of the primary and
		# secondary selection states.

		# Note.  At this point in the code, at least one of these two
		#        states must be "True" since this -- when both states
		#        are "False", this function returns before it reaches
		#        this point.

		if ( sel_bin ) :
			symbol = 'o'
		else :
			symbol = 't'

		# Create, store, and add this selection point to the plot.

		if ( self.core.app.res_lo ) :
			size = 3
		else :
			size = 6

		self.pnt[t,p,b] = PlotDataItem( [ax], [ay],
		                                symbol=symbol,
		                                symbolSize=size,
		                                symbolPen=pen,
		                                symbolBrush=brush )

		self.plt[t,p].addItem( self.pnt[t,p,b] )
Exemple #34
0
	def chng_pnt( self, j, i, b, sel_bin,
	              sel_dir=True, sel_alt=None ) :

		# If this point already exists, remove it from its plot and
		# delete it.

		if ( self.pnt[j,i,b] is not None ) :
			self.plt[j,i].removeItem( self.pnt[j,i,b] )
			self.pnt[j,i,b] = None

		# If the user gave no alternative selection state for this
		# datum, use the primary state for the secondary state.

		sel_alt = sel_bin if ( sel_alt is None ) else sel_alt

		# If this point was not selected (based on both its primary and
		# secondary states), return (since there's nothing more to be
		# done).

		if ( ( not sel_bin ) and ( not sel_alt ) ) :
			return

		# Determine the "d" index corresponding to this look direction.

		d = self.calc_ind_d( j, i )

		# Computed the adjusted point location in the "ViewBox".

		if ( self.log_x ) :
			ax = log10( self.core.fc_spec['vel_cen'][self.c][b] )
		else :
			ax = self.core.fc_spec['vel_cen'][self.c][b]
		if ( self.log_y ) :
			ay = log10( self.core.fc_spec['curr'][self.c][d][b] )
		else :
			ay = self.core.fc_spec['curr'][self.c][d][b]

		# Select the color for the point (i.e., the brush and pen used
		# to render it) based on whether or not this datum's look
		# direction has been selected and whether or not the primary and
		# secondary selection states match.

		if ( sel_dir ) :
			if ( sel_bin == sel_alt ) :
				pen   = self.pen_pnt_c
				brush = self.bsh_pnt_c
			else :
				pen   = self.pen_pnt_y
				brush = self.bsh_pnt_y
		else :
			pen   = self.pen_pnt_r
			brush = self.bsh_pnt_r

		# Select the symbol based on the values of the primary and
		# secondary selection states.

		# Note.  At this point in the code, at least one of these two
		#        states must be "True" since this -- when both states
		#        are "False", this function returns before it reaches
		#        this point.

		if ( sel_bin ) :
			if ( sel_alt ) :
				symbol = 's'
			else :
				symbol = 'o'
		else :
			symbol = 't'

		# Create, store, and add this selection point to the plot.

		if ( self.core.app.res_lo ) :
			size = 3
		else :
			size = 6

		self.pnt[j,i,b] = PlotDataItem( [ax], [ay],
		                                symbol=symbol,
		                                symbolSize=size,
		                                symbolPen=pen,
		                                symbolBrush=brush )

		self.plt[j,i].addItem( self.pnt[j,i,b] )
class imMobilize(QtWidgets.QWidget):
    def __init__(self, parent=None, *args):

        # run the widget, get the form
        QtWidgets.QWidget.__init__(self, parent, *args)

        self.ui = Ui_Form()
        self.ui.setupUi(self)
        os.chdir("D:\\")
        self.working_directory_selected = False
        """
        ==============================================================
        Connecting the buttons and labels in the serial control group
        ==============================================================
        """

        self.arduino = Arduino()
        # populate serial available combobox
        self.update_serial_available()
        # connect scan button
        self.ui.buttonSerialScan.clicked.connect(self.update_serial_available)

        # connect connect/disconnect button
        self.ui.buttonSerialConnect.clicked.connect(
            self.serial_connect_disconnect)
        # try:
        #     self.serial_connect_disconnect()
        # except:
        #     QtWidgets.QMessageBox.warning(self, "No controller found", "Could not connect to a suitable controller \n Connect Manually.")

        self.ui.lineeditWriteToSerial.editingFinished.connect(
            self.write_to_serial)
        self.ui.buttonWriteToSerial.clicked.connect(self.write_to_serial)

        self.ui.checkBoxReadSerialLive.clicked.connect(self.listen_to_serial)

        self.logged_temperature = np.array([])
        self.temp_plot_xvals = np.array([])
        """
        =====================================================================
        Connecting the buttons and controls in the light stim controls group
        =====================================================================
        """

        # connect the save_stim button
        self.ui.buttonSaveStim.clicked.connect(self.save_lightstim)

        # Style the three sliders (color the handles)
        # self.ui.sliderRed.setStyleSheet("QSlider::handle:vertical {background-color: red; border: 1px outset; border-radius: 3px;}")
        # self.ui.sliderGreen.setStyleSheet("QSlider::handle:vertical {background-color: lime; border: 1px outset; border-radius: 3px;}")
        # self.ui.sliderBlue.setStyleSheet("QSlider::handle:vertical {background-color: cyan; border: 1px outset; border-radius: 3px;}")

        self.ui.toggleWhiteColor.valueChanged.connect(
            self.toggle_lightstim_type)
        self.toggle_lightstim_type()
        """
        ====================================================================
        Connecting buttons and controls in vibration stimuli group
        ====================================================================
        """

        self.ui.buttonSaveVibrationStim.clicked.connect(
            self.save_vibration_stim)
        """
        =====================================================================
        Connecting the buttons and controls in the stimuli manager group
        =====================================================================
        """

        self.Stims = StimuliManager(arduino=self.arduino)
        self.set_experiment_view()
        self.set_lightstim_name_lineedit()
        self.set_vibrationstim_name_lineedit()
        self.ui.buttonDeleteSelectedStim.clicked.connect(
            self.delete_selected_stim)
        self.ui.buttonDeleteAllStims.clicked.connect(self.delete_all_stims)
        self.ui.buttonLoadStimulusProfile.clicked.connect(self.load_stimuli)
        self.ui.buttonSaveStimulusProfile.clicked.connect(self.save_stimuli)
        """
        =====================================================================
        Connecting the buttons and controls in the MetaData entry group
        =====================================================================
        """
        self.ui.buttonSetWorkingDirectory.clicked.connect(
            self.set_working_directory)

        self.ui.labelMetaDataDrugName.setVisible(False)
        self.ui.lineeditMetaDataDrugName.setVisible(False)

        self.ui.labelMetaDataGenetics.setVisible(False)
        self.ui.lineeditMetaDataGenetics.setVisible(False)

        self.ui.spinBoxExperimentDurationMinutes.valueChanged.connect(
            self.set_experiment_view)
        self.ui.spinBoxExperimentDurationSeconds.valueChanged.connect(
            self.set_experiment_view)

        self.ui.checkBoxExperimentAutonaming.clicked.connect(
            self.set_experiment_autonaming)
        self.set_experiment_autonaming()

        self.experiment_live = False
        self.ui.buttonStartExperiment.clicked.connect(self.start_experiment)

        self.path = os.curdir
        self.experiment_name = self.ui.lineeditExperimentName.text()
        self.experiment_path = os.path.join(self.path,
                                            "Exp_" + self.experiment_name)
        """
        ======================================================================
        Connecting buttons and controls to the camera manager group
        ======================================================================
        """

        self.detect_cameras()
        self.ui.buttonCameraConnectDisconnect.clicked.connect(
            self.camera_connect_disconnect)
        self.ui.buttonCameraPreview.clicked.connect(self.toggle_preview)
        self.ui.buttonScanForCameras.clicked.connect(self.detect_cameras)

        self.ui.spinBoxFramerate.valueChanged.connect(
            self.set_camera_framerate)

        for x in range(-2, -12, -1):
            self.ui.comboboxCameraExposure.addItem(str(2**x))

        self.ui.comboboxCameraExposure.currentTextChanged.connect(
            self.set_camera_exposure)
        self.ui.sliderCameraBrightness.sliderMoved.connect(
            self.set_camera_brightness)
        self.ui.sliderCameraGamma.sliderMoved.connect(self.set_camera_gamma)

        self.ui.buttonCameraResetProperties.clicked.connect(
            self.reset_camera_properties)

        #This is for IR light, so actually belongs to arduino, but it is located here in the GUI.
        self.ui.sliderIRLight.sliderReleased.connect(self.set_IR_light)
        """
        ======================================================================
        Connecting buttons and controls to the video manager
        ======================================================================
        """

        self.set_autonaming(True)

        self.ui.buttonSetPath.clicked.connect(self.set_path)

        self.ui.checkboxAutoNaming.toggled.connect(self.set_autonaming)
        self.ui.buttonRecordVideo.clicked.connect(self.record_video)

    def detect_cameras(self):
        self.ui.comboBoxConnectedCameras.clear()
        for ii in range(3):
            cap = cv2.VideoCapture(ii)
            if not cap.isOpened():
                pass
            else:
                cam = "Camera " + str(ii + 1)
                self.ui.comboBoxConnectedCameras.addItem(cam)

    def camera_connect_disconnect(self):
        if not hasattr(self, "cam") or not self.cam.cap.isOpened():
            camera_number = int(self.ui.comboBoxConnectedCameras.currentText().
                                split(" ")[1]) - 1

            self.cam = Camera(camera=camera_number)
            if self.cam.cap.isOpened():
                self.ui.groupBoxCameraControls.setEnabled(True)
                self.ui.groupBoxVideoControls.setEnabled(True)
                self.ui.comboBoxConnectedCameras.setEnabled(False)

                self.ui.labelCameraConnectionStatus.setText(
                    "Connected to Camera " + str(camera_number + 1))
                self.ui.labelCameraConnectionStatus.setStyleSheet(
                    "color: green")
                self.ui.buttonCameraConnectDisconnect.setText("Disconnect")
                self.ui.buttonCameraConnectDisconnect.setStyleSheet(
                    "color: red")

                t = self.ui.comboboxCameraExposure.findText(
                    str(2**(self.cam.exposure)))
                self.ui.comboboxCameraExposure.setCurrentIndex(t)
                self.ui.sliderCameraBrightness.setValue(self.cam.brightness)
                self.ui.labelCameraBrighness.setNum(self.cam.brightness)
                self.ui.sliderCameraGamma.setValue(self.cam.gamma * 10)
                self.ui.labelCameraGamma.setNum(self.cam.gamma)
                self.ui.sliderCameraGamma.setEnabled(False)

        else:
            self.toggle_preview(False)
            self.cam.stop()
            self.cam.cap.release()
            self.ui.buttonCameraPreview.setChecked(False)
            self.ui.groupBoxCameraControls.setEnabled(False)
            self.ui.groupBoxVideoControls.setEnabled(False)
            self.ui.comboBoxConnectedCameras.setEnabled(True)

            self.ui.buttonCameraConnectDisconnect.setText("Connect")
            self.ui.buttonCameraConnectDisconnect.setStyleSheet("color: black")
            self.ui.labelCameraConnectionStatus.setText(
                "Status: Not Connected")
            self.ui.labelCameraConnectionStatus.setStyleSheet("color: black")

    def toggle_lightstim_type(self):
        val = self.ui.toggleWhiteColor.value()
        if val == 1:
            self.lightStimType = "White"
            self.ui.labelLightStimTypeLED.setEnabled(False)
            self.ui.labelLightStimTypeWhite.setEnabled(True)
            self.ui.widgetLEDSliders.setEnabled(False)

            self.ui.toggleWhiteColor.setStyleSheet(
                "QSlider::handle:horizontal {background-color: rgba(255,255,255,255); border: 2px outset; width: 10px; height: 10px; border-radius: 5px;}"
                "QSlider::groove:horizontal {height: 10px; width: 30px; background-color: rgba(255, 0,0, 100); border-radius: 5px; border: 1px solid;}"
            )

            self.ui.sliderRed.setStyleSheet(
                "QSlider::handle:vertical {background-color: grey; border: 1px outset; border-radius: 3px;}"
            )
            self.ui.sliderGreen.setStyleSheet(
                "QSlider::handle:vertical {background-color: grey; border: 1px outset; border-radius: 3px;}"
            )
            self.ui.sliderBlue.setStyleSheet(
                "QSlider::handle:vertical {background-color: grey; border: 1px outset; border-radius: 3px;}"
            )

        if val == 0:
            self.lightStimType = "LED"
            self.ui.labelLightStimTypeLED.setEnabled(True)
            self.ui.labelLightStimTypeWhite.setEnabled(False)
            self.ui.widgetLEDSliders.setEnabled(True)

            self.ui.toggleWhiteColor.setStyleSheet(
                "QSlider::handle:horizontal {background-color: rgba(255,100,0,100); border: 2px outset; width: 10px; height: 10px; border-radius: 5px;}"
                "QSlider::groove:horizontal {height: 10px; width: 30px; background-color: rgba(255, 255, 255,100); border-radius: 5px; border: 1px solid;}"
            )

            self.ui.sliderRed.setStyleSheet(
                "QSlider::handle:vertical {background-color: red; border: 1px outset; border-radius: 3px;}"
            )
            self.ui.sliderGreen.setStyleSheet(
                "QSlider::handle:vertical {background-color: lime; border: 1px outset; border-radius: 3px;}"
            )
            self.ui.sliderBlue.setStyleSheet(
                "QSlider::handle:vertical {background-color: cyan; border: 1px outset; border-radius: 3px;}"
            )

    def set_experiment_view(self):
        self.ui.graphicsView.clear()
        plot = PlotDataItem(pen="k")

        duration = (self.ui.spinBoxExperimentDurationMinutes.value() *
                    60) + self.ui.spinBoxExperimentDurationSeconds.value()
        xs = np.linspace(0, duration, 2)
        ys = [1, 1]
        plot.setData(xs, ys)
        self.ui.graphicsView.addItem(plot)

        for ii in range(len(self.Stims.df)):
            start = self.Stims.df.time_on.iloc[ii]
            stop = self.Stims.df.time_off.iloc[ii]

            if self.Stims.df.message_on.iloc[ii].startswith("w"):
                box = LinearRegionItem(values=(start, stop),
                                       brush=(255, 255, 250, 230),
                                       movable=False)
                self.ui.graphicsView.addItem(box)
            elif self.Stims.df.message_on.iloc[ii].startswith("n"):
                on = self.Stims.df.message_on.iloc[ii][1:]
                r = int(on[:3])
                g = int(on[3:6])
                b = int(on[6:])
                box = LinearRegionItem(values=(start, stop),
                                       brush=(r, g, b, 50),
                                       movable=False)
                self.ui.graphicsView.addItem(box)
            elif self.Stims.df.message_on.iloc[ii].startswith("v"):
                box = LinearRegionItem(values=(start, stop),
                                       brush="k",
                                       movable=False)
                self.ui.graphicsView.addItem(box)

        self.ui.comboBoxSelectStimId.clear()
        for stim_id in set(self.Stims.df.id):
            self.ui.comboBoxSelectStimId.addItem(stim_id)

    # def checkStimSafeguard(self):
    #     if self.ui.checkboxDirectStim.isChecked() is False:
    #         self.ui.listwidgetAllStims.itemDoubleClicked.disconnect(self.single_stim)
    #     elif self.ui.checkboxDirectStim.isChecked():
    #         self.ui.listwidgetAllStims.itemDoubleClicked.connect(self.single_stim)

    def update_serial_available(self):
        """Scans the available comports and updates the combobox with the resulst"""
        self.ui.comboboxSerialAvailable.clear()
        self.arduino.scan_comports()
        for port in list(self.arduino.port_dict.keys()):
            self.ui.comboboxSerialAvailable.addItem(port)

    def serial_connect_disconnect(self):
        """Connects to selected serial if disconnected and vice versa"""
        if self.ui.buttonSerialConnect.text().lower() == "connect":
            port = self.ui.comboboxSerialAvailable.currentText()
            self.arduino.connect(port)
            if self.arduino.ser.isOpen():
                self.ui.labelSerialConnected.setText("Connected: " +
                                                     self.arduino.port)
                self.ui.labelSerialConnected.setStyleSheet("color: green")
                self.ui.buttonSerialConnect.setText("Disconnect")
                self.ui.checkBoxReadSerialLive.setEnabled(True)
                self.ui.sliderIRLight.setEnabled(True)

        elif self.ui.buttonSerialConnect.text().lower() == "disconnect":
            self.ui.checkBoxReadSerialLive.setChecked(False)
            self.arduino.disconnect()
            if self.arduino.ser.isOpen() == False:
                self.ui.labelSerialConnected.setText("Status: Not connected")
                self.ui.labelSerialConnected.setStyleSheet("color: black")
                self.ui.buttonSerialConnect.setText("Connect")
                self.ui.checkBoxReadSerialLive.setEnabled(False)
                self.ui.checkBoxReadSerialLive.setChecked(False)
                self.ui.sliderIRLight.setEnabled(False)

    def listen_to_serial(self):
        """Starts a thread that listens on the self.Arduino.ser serial connection and updates the GUI with incoming messages"""
        if self.ui.checkBoxReadSerialLive.isChecked():
            self.ui.graphicsViewSerial.clear()
            self.temperature_plot = PlotDataItem(pen=(0, 153, 153))
            self.temperature_plot_2 = PlotDataItem(pen=(255, 128, 0))
            self.temperature_plot.setDownsampling(auto=True, method="mean")
            self.temperature_plot_2.setDownsampling(auto=True, method="mean")
            self.ui.graphicsViewSerial.addItem(self.temperature_plot)
            self.ui.graphicsViewSerial.addItem(self.temperature_plot_2)
            t = Thread(target=self.start_listening, args=())
            t.start()

    def start_listening(self):
        """To be started in separate thread: listens to Serial port and updates gui via separate method if new message comes in"""
        self.arduino.ser.flushInput()
        self.logged_temperature = np.array([])
        self.logged_temperature_2 = np.array([])
        self.logged_temperature_time = np.array([])
        start = time.time()
        while self.ui.checkBoxReadSerialLive.isChecked(
        ) and self.arduino.ser.isOpen():
            if self.arduino.ser.in_waiting > 0:
                message = self.arduino.ser.readline().decode()
                elapsed_time = time.time() - start
                self.update_serial_display(message, np.round(elapsed_time, 2))
            else:
                time.sleep(0.01)
        else:
            pass

    def update_serial_display(self, message, elapsed_time):
        temp1, temp2 = message.split(" ")
        self.ui.labelSerialLiveIncoming.setText(str(elapsed_time))
        self.ui.labelSerialLiveTemperature.setText(message)
        temp1 = float(temp1)
        temp2 = float(temp2)
        self.logged_temperature_time = np.hstack(
            [self.logged_temperature_time, elapsed_time])
        self.logged_temperature = np.hstack([self.logged_temperature, temp1])
        self.logged_temperature_2 = np.hstack(
            [self.logged_temperature_2, temp2])

        self.temperature_plot.setData(x=self.logged_temperature_time,
                                      y=self.logged_temperature)
        self.temperature_plot_2.setData(x=self.logged_temperature_time,
                                        y=self.logged_temperature_2)

    def write_to_serial(self):
        """Send message in the lineEdit widget to the serial port"""
        message = self.ui.lineeditWriteToSerial.text()
        self.arduino.write(message)
        self.ui.lineeditWriteToSerial.clear()

    def set_lightstim_name_lineedit(self):
        c = 1
        while "LightStim" + str(len(self.Stims.df) + c) in self.Stims.df.id:
            c += 1
        newname = "LightStim" + str(len(self.Stims.df) + c)
        self.ui.lineeditLightStimName.setText(newname)

    def save_lightstim(self):
        """Takes the current settings in the lightstim box and adds them to stim manager"""

        start_time = self.ui.spinboxStimStart.value()
        stop_time = self.ui.spinboxStimDuration.value() + start_time
        stim_id = self.ui.lineeditLightStimName.text()

        if self.lightStimType == "LED":
            start_message = "n"
            for slider in [
                    self.ui.sliderRed, self.ui.sliderGreen, self.ui.sliderBlue
            ]:
                start_message += str(slider.value()).zfill(3)
            stop_message = "nC"

        elif self.lightStimType == "White":
            start_message = "wS"
            stop_message = "wC"

        self.Stims.add_stimulus(start_time, stop_time, start_message,
                                stop_message, stim_id)
        self.set_lightstim_name_lineedit()

        self.ui.comboBoxSelectStimId.clear()
        stim_ids = list(set(self.Stims.df.id))
        stim_ids.sort()
        for stim_id in stim_ids:
            self.ui.comboBoxSelectStimId.addItem(stim_id)
        self.set_experiment_view()

    def set_vibrationstim_name_lineedit(self):
        c = 1
        while "VibrationStim" + str(len(self.Stims.df) +
                                    c) in self.Stims.df.id:
            c += 1
        newname = "VibrationStim" + str(len(self.Stims.df) + c)
        self.ui.lineeditVibrationStimName.setText(newname)

    def save_vibration_stim(self):
        """takes the current settings in the vibration stim box and adds it to the stim manager"""
        start_time = self.ui.spinBoxVibrationStart.value()
        duration = self.ui.spinBoxVibrationDuration.value()
        freq = self.ui.spinBoxVibrationFrequency.value()
        start_message = "v" + str(freq).zfill(3) + str(int(
            duration * 1000)).zfill(4)
        stop_message = ""
        stim_id = self.ui.lineeditVibrationStimName.text()
        self.Stims.add_stimulus(start_time, start_time + duration,
                                start_message, stop_message, stim_id)
        self.set_vibrationstim_name_lineedit()
        self.ui.comboBoxSelectStimId.clear()
        stim_ids = list(set(self.Stims.df.id))
        stim_ids.sort()
        for stim_id in stim_ids:
            self.ui.comboBoxSelectStimId.addItem(stim_id)
        self.set_experiment_view()

    def delete_selected_stim(self):
        stim_id = self.ui.comboBoxSelectStimId.currentText()

        self.Stims.delete_stimulus(stim_id)
        self.set_experiment_view()

    def delete_all_stims(self):
        self.Stims.delete_all_stims()
        self.set_experiment_view()

    def load_stimuli(self):
        file = QtWidgets.QFileDialog.getOpenFileName(self,
                                                     "Select a Stimuli File")
        file = file[0]
        if os.path.exists(file) and file.endswith(".txt"):
            df = pd.read_csv(file, delimiter="\t")
            self.Stims.df = df
            self.set_experiment_view()
        elif not file:
            pass
        else:
            QtWidgets.QMessageBox.warning(self, "Invalid Filename",
                                          "Invalid Stimulus File selected.")

    def save_stimuli(self):
        filename_selected = False
        while not filename_selected:
            filename = QtWidgets.QFileDialog.getSaveFileName(
                self, "Save Stimuli file as")[0]
            if not filename:
                break
            else:
                if not filename.endswith(".txt"):
                    filename += ".txt"
                self.Stims.df.to_csv(filename, sep="\t")
                filename_selected = True

    def toggle_preview(self, event):
        if event:
            self.cam.preview()
            self.ui.buttonCameraPreview.setText("Stop")
            self.ui.buttonCameraPreview.setStyleSheet("color: red")
        else:
            self.ui.buttonCameraPreview.setText("Preview")
            self.ui.buttonCameraPreview.setStyleSheet("color: Black")
            self.cam.stop()

    def set_autonaming(self, bool):
        if bool:
            self.ui.lineeditVideoName.setText(
                time.strftime("%Y%m%d_%H%M%S_video"))

    def set_experiment_autonaming(self):
        if self.ui.checkBoxExperimentAutonaming.isChecked():
            name = time.strftime("%Y%m%d_%H%M%S")
            name += "_"
            name += str(self.ui.spinboxCrowdsize.value())
            name += "_"
            name += str(self.ui.spinBoxExperimentDurationMinutes.value()) + "m"
            name += str(
                self.ui.spinBoxExperimentDurationSeconds.value()) + "s_"
            if self.ui.checkboxMetaDataDrugs.isChecked():
                name += self.ui.lineeditMetaDataDrugName.text() + "_"
            else:
                name += "None_"
            if self.ui.checkboxMetaDataGenetics.isChecked():
                name += self.ui.lineeditMetaDataGenetics.text() + "_"
            else:
                name += "None_"
            if len(self.Stims.df) > 0:
                name += "Light"
            else:
                name += "None"
            self.ui.lineeditExperimentName.setText(name)
        else:

            pass

    def set_camera_framerate(self, fps):
        self.cam.framerate = fps


#        if self.cam.do_gamma == False:
#            self.ui.sliderCameraGamma.setVisible(False)
#            self.ui.labelCameraGamma.setVisible(False)
#        else:
#            self.ui.sliderCameraGamma.setVisible(True)
#            self.ui.labelCameraGamma.setVisible(True)

    def set_camera_brightness(self, brightness):
        self.cam.brightness = brightness

    def set_camera_gamma(self, gamma):
        gamma = gamma / 10
        self.cam.gamma = gamma
        self.ui.labelCameraGamma.setNum(gamma)

    def set_camera_exposure(self, exp):
        # If set exposure is longer than framerate allows, then adjust framerate
        exp = float(exp)

        if exp > (1 / self.cam.framerate):
            print(
                "\n WARNING: Adjusting framerate to accomodate for exposure \n"
            )
            #            self.set_camera_framerate(1 / exp)
            self.ui.spinBoxFramerate.setValue(int(1 / exp))

        exp = np.log2(exp)
        self.cam.exposure = exp

    def set_IR_light(self):
        val = self.ui.sliderIRLight.value()
        self.arduino.write("i" + str(val).zfill(3))
        sys.stdout.write('\n IR Light set to {}. {}% of power'.format(
            val, (val / 255) * 100))

    def set_path(self):
        self.path = QtGui.QFileDialog.getExistingDirectory()
        print(self.path)

    def set_working_directory(self):
        self.working_directory_selected = False
        while not self.working_directory_selected:
            self.path = QtGui.QFileDialog.getExistingDirectory()
            if os.path.exists(self.path):
                os.chdir(self.path)
                self.working_directory_selected = True
            else:
                q = QtWidgets.QMessageBox.question(
                    self, "No path selected",
                    "Do you wish to not select a path? \n Path then defaults to D:\\"
                )
                if q == QtWidgets.QMessageBox.Yes:
                    self.path = "D:\\"
                    self.working_directory_selected = True

    def reset_camera_properties(self):
        self.cam.brightness = 0
        self.ui.sliderCameraBrightness.setValue(0)
        self.ui.labelCameraBrighness.setNum(0)

        self.cam.exposure = -5.0
        t = self.ui.comboboxCameraExposure.findText(str(2**-5))
        self.ui.comboboxCameraExposure.setCurrentIndex(t)

        self.cam.gamma = 1
        self.ui.sliderCameraGamma.setValue(10)
        self.ui.labelCameraGamma.setNum(1)

        self.cam.framerate = 30
        self.ui.spinBoxFramerate.setValue(30)

    def record_video(self, event):

        if event:
            self.ui.buttonRecordVideo.setText("Stop")
            self.ui.buttonRecordVideo.setStyleSheet("color:red")

            self.ui.groupBoxCameraControls.setEnabled(False)
            self.ui.groupBoxCameraConnection.setEnabled(False)

            if self.ui.checkboxAutoNaming.isChecked():
                self.ui.lineeditVideoName.setText(
                    time.strftime("%Y%m%d_%H%M" + "_experiment"))

            name = os.path.join(self.path, self.ui.lineeditVideoName.text())

            duration = self.ui.spinBoxVideoTimeMinutes.value() * 60
            duration += self.ui.spinBoxVideoTimeSeconds.value()
            preview = self.ui.checkBoxPreviewWhileRecording.isChecked()
            self.cam.video(name, duration, preview)

            t = Thread(target=self.wait_for_recording_end)
            t.start()

        else:
            self.ui.groupBoxCameraControls.setEnabled(True)
            self.ui.groupBoxCameraConnection.setEnabled(True)
            self.ui.buttonRecordVideo.setText("Record")
            self.ui.buttonRecordVideo.setStyleSheet("color:Black")
            self.cam.stop()

    def wait_for_recording_end(self):
        time.sleep(0.1)
        while self.cam.alive == True:
            time.sleep(0.1)
        else:
            self.record_video(False)

    #            self.ui.buttonRecordVideo.setChecked(False)
    #
    """
    ==========================================================================================
    METHODS TO RUN AN ENTIRE EXPERIMENT
    ==========================================================================================
    """

    def start_experiment(self, event):
        if event:
            if not hasattr(self, "cam"):
                QtWidgets.QMessageBox.warning(
                    self, "Not Connected Warning",
                    "No open connection with Camera")
                self.ui.buttonStartExperiment.setChecked(False)
            elif not self.cam.cap.isOpened():
                QtWidgets.QMessageBox.warning(
                    self, "Not Connected Warning",
                    "No open connection with Camera")
                self.ui.buttonStartExperiment.setChecked(False)
            elif not self.arduino.connected:
                QtWidgets.QMessageBox.warning(
                    self, "Not Connected Warning",
                    "No open connection with Controller")
                self.ui.buttonStartExperiment.setChecked(False)
            else:
                if not self.working_directory_selected:
                    QtWidgets.QMessageBox.warning(
                        self, "No valid working directory",
                        "Select a directory to save your experiment")
                    self.set_working_directory()

                self.experiment_live = True
                self.ui.buttonStartExperiment.setStyleSheet(
                    'color: rgba(255,0,0,255)')
                self.ui.buttonStartExperiment.setText('Interrupt')

                self.set_experiment_autonaming()
                self.ui.widgetMetaData.setEnabled(False)
                self.experiment_name = self.ui.lineeditExperimentName.text()

                self.experiment_path = os.path.join(
                    self.path, "Exp_" + self.experiment_name)
                if not os.path.exists(
                        self.experiment_path) or not os.path.isdir(
                            self.experiment_path):
                    os.mkdir(self.experiment_path)

                if self.ui.checkBoxReadSerialLive.isChecked():
                    self.ui.checkBoxReadSerialLive.setChecked(False)
                self.ui.checkBoxReadSerialLive.setChecked(True)
                self.listen_to_serial()

                duration = (
                    self.ui.spinBoxExperimentDurationMinutes.value() *
                    60) + self.ui.spinBoxExperimentDurationSeconds.value()
                preview = self.ui.checkBoxPreviewWhileRecording.isChecked()
                self.cam.video(
                    os.path.join(self.experiment_path, self.experiment_name),
                    duration, preview)
                self.Stims.start_stimuli()
                t = Thread(target=self.wait_for_experiment_end, args=())
                t.start()
        else:
            self.experiment_live = False
            self.cam.stop()
            self.ui.checkBoxReadSerialLive.setChecked(False)
            self.ui.buttonStartExperiment.setStyleSheet("color: Black")
            self.ui.buttonStartExperiment.setText("Start Experiment")

            df = pd.DataFrame()
            df["date"] = [time.strftime("%Y%m%d")]
            df["time"] = [time.strftime("%H%M%S")]
            df["duration"] = [
                (self.ui.spinBoxExperimentDurationMinutes.value() * 60) +
                self.ui.spinBoxExperimentDurationSeconds.value()
            ]
            df["drugs"] = [self.ui.lineeditMetaDataDrugName.text()]
            df["genetics"] = [self.ui.lineeditMetaDataGenetics.text()]
            df["age"] = [self.ui.spinboxAge]
            df["framerate"] = [self.cam.framerate]
            df["dechorionated"] = [
                self.ui.checkboxMetaDataDechorionation.isChecked()
            ]
            df["exposture"] = [
                float(self.ui.comboboxCameraExposure.currentText())
            ]
            df["gamma"] = [self.cam.gamma]
            df["brightness"] = [self.cam.brightness]
            df["infrared"] = [self.ui.sliderIRLight.value()]

            df.to_csv(os.path.join(self.experiment_path, "metadata.txt"),
                      sep="\t")

            self.Stims.df.to_csv(os.path.join(self.experiment_path,
                                              "stimuli_profile.txt"),
                                 sep="\t")
            df = pd.DataFrame(np.hstack([
                self.logged_temperature_time.reshape(-1, 1),
                self.logged_temperature.reshape(-1, 1),
                self.logged_temperature_2.reshape(-1, 1)
            ]),
                              columns=["time", "temperature", "temperature2"])
            df.set_index("time", inplace=True)
            df.to_csv(os.path.join(self.experiment_path,
                                   "logged_temperatures.txt"),
                      sep="\t")
            self.ui.widgetMetaData.setEnabled(True)

    def wait_for_experiment_end(self):
        time.sleep(0.2)  # Give camera a chance to start.
        while self.cam.alive:
            time.sleep(0.2)
        else:
            if self.experiment_live:
                self.start_experiment(False)
                self.ui.buttonStartExperiment.setChecked(False)

    # def start_experiment(self):
    #
    #     if self.experiment_live:
    #         self.experiment_live = False
    #         self.cam.stop()
    #         self.ui.checkBoxReadSerialLive.setChecked(False)
    #         self.ui.buttonStartExperiment.setStyleSheet("color: Black")
    #         self.ui.buttonStartExperiment.setText("Start Experiment")
    #
    #         df = pd.DataFrame()
    #         df["date"] = [time.strftime("%Y%m%d")]
    #         df["time"] = [time.strftime("%H%M%S")]
    #         df["duration"] = [(self.ui.spinBoxExperimentDurationMinutes.value() * 60) + self.ui.spinBoxExperimentDurationSeconds.value()]
    #         df["drugs"] = [self.ui.lineeditMetaDataDrugName.text()]
    #         df["genetics"] = [self.ui.lineeditMetaDataGenetics.text()]
    #         df["framerate"] = [self.cam.framerate]
    #         df["dechorionated"] = [self.ui.checkboxMetaDataDechorionation.isChecked()]
    #         df["exposture"] = [float(self.ui.comboboxCameraExposure.currentText())]
    #         df["gamma"] = [self.cam.brightness]
    #         df["brightness"] = [self.cam.brightness]
    #         df["infrared"] = [self.ui.sliderIRLight.value]
    #
    #
    #         df.to_csv(os.path.join(self.experiment_path, "metadata.txt"), sep="\t")
    #
    #         self.Stims.df.to_csv(os.path.join(self.experiment_path, "stimuli_profile.txt"), sep="\t")
    #         df = pd.DataFrame(np.hstack([self.logged_temperature_time.reshape(-1,1), self.logged_temperature.reshape(-1,1), self.logged_temperature_2.reshape(-1,1)]), columns = ["time", "temperature", "temperature2"])
    #         df.set_index("time", inplace=True)
    #         df.to_csv(os.path.join(self.experiment_path, "logged_temperatures.txt"), sep="\t")
    #
    #
    #         self.ui.groupboxMetaData.setEnabled(True)
    #
    #     elif not self.experiment_live:
    #         if not hasattr(self, "cam"):
    #             QtWidgets.QMessageBox.warning(self, "Not Connected Warning", "No open connection with Camera or Controller")
    #         elif self.cam.cap.isOpened() != True or self.arduino.ser.isOpen() != True:
    #             QtWidgets.QMessageBox.warning(self, "Not Connected Warning", "No open connection with Camera or Controller")
    #         else:
    #             self.experiment_live = True
    #             self.ui.buttonStartExperiment.setStyleSheet('color: rgba(255,0,0,255)')
    #             self.ui.buttonStartExperiment.setText('Interrupt')
    #
    #             self.set_experiment_autonaming()
    #             self.ui.groupboxMetaData.setEnabled(False)
    #             self.experiment_name = self.ui.lineeditExperimentName.text()
    #
    #             self.experiment_path = os.path.join(self.path, "Exp_" + self.experiment_name)
    #             if not os.path.exists(self.experiment_path) or not os.path.isdir(self.experiment_path):
    #                 os.mkdir(self.experiment_path)
    #
    #             if self.ui.checkBoxReadSerialLive.isChecked():
    #                 self.ui.checkBoxReadSerialLive.setChecked(False)
    #             self.ui.checkBoxReadSerialLive.setChecked(True)
    #             self.listen_to_serial()
    #
    #             duration = (self.ui.spinBoxExperimentDurationMinutes.value() * 60) + self.ui.spinBoxExperimentDurationSeconds.value()
    #             self.cam.video(os.path.join(self.experiment_path, self.experiment_name), duration)
    #             self.Stims.start_stimuli()
    #             t = Thread(target=self.wait_for_experiment_end, args=())
    #             t.start()

    # def wait_for_experiment_end(self):
    #     time.sleep(0.2)  # Give camera a chance to start.
    #     while self.cam.alive:
    #         time.sleep(0.1)
    #     else:
    #         if self.experiment_live:
    #             self.start_experiment()

    def closeEvent(self, event):
        QtWidgets.QMessageBox.warning(self, "Closing",
                                      "Nothing you can do about it")
        self.arduino.ser.close()
        self.cam.cap.release()
        event.accept()
        print("yay")
 def __init__(self, name, parent=None):
     super(makeTimeseriesCurveNode, self).__init__(name, parent=parent, terminals={'df': {'io': 'in'}, 'pd.Series': {'io': 'out'}, 'Curve': {'io': 'out'}}, color=(150, 150, 250, 150))
     self._plotRequired = False
     self.item = PlotDataItem(clipToView=False)
Exemple #37
0
class PMTWidgetUI(QWidget):
    
#    waveforms_generated = pyqtSignal(object, object, list, int)
    SignalForContourScanning = pyqtSignal(int, int, int, np.ndarray, np.ndarray)
    MessageBack = pyqtSignal(str)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
#        os.chdir('./')# Set directory to current folder.
        self.setFont(QFont("Arial"))
        
        self.setMinimumSize(1200,850)
        self.setWindowTitle("PMTWidget")
        self.layout = QGridLayout(self)
        #------------------------Initiating class-------------------
        self.pmtTest = pmtimagingTest()
        self.pmtTest_contour = pmtimagingTest_contour()
        
        self.savedirectory = r'M:\tnw\ist\do\projects\Neurophotonics\Brinkslab\Data\Octoscope\pmt_image_default_dump'
        self.prefixtextboxtext = '_fromGalvoWidget'

        #**************************************************************************************************************************************
        #--------------------------------------------------------------------------------------------------------------------------------------
        #-----------------------------------------------------------GUI for PMT tab------------------------------------------------------------
        #--------------------------------------------------------------------------------------------------------------------------------------  
        #**************************************************************************************************************************************        
        pmtimageContainer = QGroupBox("PMT image")
        self.pmtimageLayout = QGridLayout()
        
        self.pmtvideoWidget = pg.ImageView()
        self.pmtvideoWidget.ui.roiBtn.hide()
        self.pmtvideoWidget.ui.menuBtn.hide()  
        self.pmtvideoWidget.resize(400,400)
        self.pmtimageLayout.addWidget(self.pmtvideoWidget, 0, 0)
        
        pmtroiContainer = QGroupBox("PMT ROI")
        self.pmtimageroiLayout = QGridLayout()
        
        self.pmt_roiwidget = pg.GraphicsLayoutWidget()
        self.pmt_roiwidget.resize(150,150)
        self.pmt_roiwidget.addLabel('ROI', row=0, col=0) 
        # create ROI
        self.vb_2 = self.pmt_roiwidget.addViewBox(row=1, col=0, lockAspect=True, colspan=1)
        self.vb_2.name = 'ROI'
        
        self.pmtimgroi = pg.ImageItem()
        self.vb_2.addItem(self.pmtimgroi)        
        #self.roi = pg.RectROI([20, 20], [20, 20], pen=(0,9))
        #r1 = QRectF(0, 0, 895, 500)
        ROIpen = QPen()  # creates a default pen
        ROIpen.setStyle(Qt.DashDotLine)
        ROIpen.setWidth(0.5)
        ROIpen.setBrush(QColor(0,161,255))
        self.roi = pg.PolyLineROI([[0,0], [80,0], [80,80], [0,80]], closed=True, pen=ROIpen)#, maxBounds=r1
        #self.roi.addScaleHandle([1,0], [1, 0])
        self.roi.sigHoverEvent.connect(lambda: self.show_handle_num()) # update handle numbers
        
        self.pmtvb = self.pmtvideoWidget.getView()
        self.pmtimageitem = self.pmtvideoWidget.getImageItem()
        self.pmtvb.addItem(self.roi)# add ROIs to main image
        
        self.pmtimageroiLayout.addWidget(self.pmt_roiwidget, 0, 0)
        
        pmtimageContainer.setMinimumWidth(850)
        pmtroiContainer.setMaximumHeight(380)
#        pmtroiContainer.setMaximumWidth(300)
        
        pmtimageContainer.setLayout(self.pmtimageLayout)
        pmtroiContainer.setLayout(self.pmtimageroiLayout)
        #----------------------------Contour-----------------------------------        
        pmtContourContainer = QGroupBox("Contour selection")
        pmtContourContainer.setFixedWidth(280)
        self.pmtContourLayout = QGridLayout()
        #contour_Description = QLabel("Handle number updates when parking mouse cursor upon ROI. Points in contour are divided evenly between handles.")
        #contour_Description.setStyleSheet('color: blue')        
        #self.pmtContourLayout.addWidget(contour_Description,0,0)
       
        self.pmt_handlenum_Label = QLabel("Handle number: ")
        self.pmtContourLayout.addWidget(self.pmt_handlenum_Label,1,0)
        
        self.contour_strategy = QComboBox()
        self.contour_strategy.addItems(['Manual','Uniform'])
        self.pmtContourLayout.addWidget(self.contour_strategy, 1, 1)        
        
        self.pointsinContour = QSpinBox(self)
        self.pointsinContour.setMinimum(1)
        self.pointsinContour.setMaximum(1000)
        self.pointsinContour.setValue(100)
        self.pointsinContour.setSingleStep(100)        
        self.pmtContourLayout.addWidget(self.pointsinContour, 2, 1)
        self.pmtContourLayout.addWidget(QLabel("Points in contour:"), 2, 0)

        self.contour_samprate = QSpinBox(self)
        self.contour_samprate.setMinimum(0)
        self.contour_samprate.setMaximum(1000000)
        self.contour_samprate.setValue(50000)
        self.contour_samprate.setSingleStep(50000)        
        self.pmtContourLayout.addWidget(self.contour_samprate, 3, 1)        
        self.pmtContourLayout.addWidget(QLabel("Sampling rate:"), 3, 0)
        
        self.generate_contour_sacn = StylishQT.generateButton()
        self.pmtContourLayout.addWidget(self.generate_contour_sacn, 4, 1)
        self.generate_contour_sacn.clicked.connect(lambda: self.generate_contour())
        
        self.do_contour_sacn = StylishQT.runButton("Contour")
        self.do_contour_sacn.setFixedHeight(32)
        self.pmtContourLayout.addWidget(self.do_contour_sacn, 5, 0)
        self.do_contour_sacn.clicked.connect(lambda:self.buttonenabled('contourscan', 'start'))
        self.do_contour_sacn.clicked.connect(lambda: self.measure_pmt_contourscan())
        
        self.stopButton_contour = StylishQT.stop_deleteButton()
        self.stopButton_contour.setFixedHeight(32)
        self.stopButton_contour.clicked.connect(lambda:self.buttonenabled('contourscan', 'stop'))
        self.stopButton_contour.clicked.connect(lambda: self.stopMeasurement_pmt_contour())
        self.stopButton_contour.setEnabled(False)
        self.pmtContourLayout.addWidget(self.stopButton_contour, 5, 1)
        
        pmtContourContainer.setLayout(self.pmtContourLayout)
        #----------------------------Control-----------------------------------
        controlContainer = QGroupBox("Galvo Scanning Panel")
        controlContainer.setFixedWidth(280)
        self.controlLayout = QGridLayout()
        
        self.pmt_fps_Label = QLabel("Per frame: ")
        self.controlLayout.addWidget(self.pmt_fps_Label, 5, 0)
    
        self.saveButton_pmt = StylishQT.saveButton()
        self.saveButton_pmt.clicked.connect(lambda: self.saveimage_pmt())
        self.controlLayout.addWidget(self.saveButton_pmt, 5, 1)
    
        self.startButton_pmt = StylishQT.runButton("")
        self.startButton_pmt.setFixedHeight(32)
        self.startButton_pmt.setCheckable(True)
        self.startButton_pmt.clicked.connect(lambda:self.buttonenabled('rasterscan', 'start'))
        self.startButton_pmt.clicked.connect(lambda: self.measure_pmt())

        self.controlLayout.addWidget(self.startButton_pmt, 6, 0)
        
        self.stopButton = StylishQT.stop_deleteButton()
        self.stopButton.setFixedHeight(32)
        self.stopButton.clicked.connect(lambda:self.buttonenabled('rasterscan', 'stop'))
        self.stopButton.clicked.connect(lambda: self.stopMeasurement_pmt())
        self.stopButton.setEnabled(False)
        self.controlLayout.addWidget(self.stopButton, 6, 1)
        
        #-----------------------------------Galvo scanning------------------------------------------------------------------------
        self.textboxAA_pmt = QSpinBox(self)
        self.textboxAA_pmt.setMinimum(0)
        self.textboxAA_pmt.setMaximum(1000000)
        self.textboxAA_pmt.setValue(500000)
        self.textboxAA_pmt.setSingleStep(100000)        
        self.controlLayout.addWidget(self.textboxAA_pmt, 1, 1)        
        self.controlLayout.addWidget(QLabel("Sampling rate:"), 1, 0)
        
        #self.controlLayout.addWidget(QLabel("Galvo raster scanning : "), 1, 0)
        self.textbox1B_pmt = QSpinBox(self)
        self.textbox1B_pmt.setMinimum(-10)
        self.textbox1B_pmt.setMaximum(10)
        self.textbox1B_pmt.setValue(3)
        self.textbox1B_pmt.setSingleStep(1)        
        self.controlLayout.addWidget(self.textbox1B_pmt, 2, 1)
        self.controlLayout.addWidget(QLabel("Volt range:"), 2, 0)
        
        self.Scanning_pixel_num_combobox = QSpinBox(self)
        self.Scanning_pixel_num_combobox.setMinimum(0)
        self.Scanning_pixel_num_combobox.setMaximum(1000)
        self.Scanning_pixel_num_combobox.setValue(500)
        self.Scanning_pixel_num_combobox.setSingleStep(244)        
        self.controlLayout.addWidget(self.Scanning_pixel_num_combobox, 3, 1)
        self.controlLayout.addWidget(QLabel("Pixel number:"), 3, 0)

        self.textbox1H_pmt = QSpinBox(self)
        self.textbox1H_pmt.setMinimum(1)
        self.textbox1H_pmt.setMaximum(20)
        self.textbox1H_pmt.setValue(1)
        self.textbox1H_pmt.setSingleStep(1)
        self.controlLayout.addWidget(self.textbox1H_pmt, 4, 1)
        self.controlLayout.addWidget(QLabel("average over:"), 4, 0)
        
        controlContainer.setLayout(self.controlLayout)
        
        #---------------------------Set tab1 layout---------------------------
#        pmtmaster = QGridLayout()
        self.layout.addWidget(pmtimageContainer, 0,0,3,1)
        self.layout.addWidget(pmtroiContainer,1,1)       
        self.layout.addWidget(pmtContourContainer,2,1)
        self.layout.addWidget(controlContainer,0,1)
        
#        self.layout.setLayout(pmtmaster)
        
        #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
        #--------------------------------------------------------------------------------------------------------------------------------------
        #------------------------------------------------------Functions for TAB 'PMT'---------------------------------------------------------
        #-------------------------------------------------------------------------------------------------------------------------------------- 
        #**************************************************************************************************************************************
    def buttonenabled(self, button, switch):
        
        if button == 'rasterscan':
            if switch == 'start':

                self.startButton_pmt.setEnabled(False)
                self.stopButton.setEnabled(True)
                    
            elif switch == 'stop':
                self.startButton_pmt.setEnabled(True)
                self.stopButton.setEnabled(False)
                    
        elif button == 'contourscan':
            if switch == 'start': #disable start button and enable stop button
                self.do_contour_sacn.setEnabled(False)
                self.stopButton_contour.setEnabled(True)
            elif switch == 'stop':
                self.do_contour_sacn.setEnabled(True)
                self.stopButton_contour.setEnabled(False)
                
                
                
    def measure_pmt(self):
        self.Daq_sample_rate_pmt = int(self.textboxAA_pmt.value())
        
        # Voltage settings, by default it's equal range square.
        self.Value_voltXMax = self.textbox1B_pmt.value()
        self.Value_voltXMin = self.Value_voltXMax*-1
        Value_voltYMin = self.Value_voltXMin
        Value_voltYMax = self.Value_voltXMax
        
        self.Value_xPixels = int(self.Scanning_pixel_num_combobox.value())
        Value_yPixels = self.Value_xPixels
        self.averagenum =int(self.textbox1H_pmt.value())
        
        Totalscansamples = self.pmtTest.setWave(self.Daq_sample_rate_pmt, self.Value_voltXMin, self.Value_voltXMax, Value_voltYMin, Value_voltYMax, self.Value_xPixels, Value_yPixels, self.averagenum)
        time_per_frame_pmt = Totalscansamples/self.Daq_sample_rate_pmt
        
        ScanArrayXnum=int((Totalscansamples/self.averagenum)/Value_yPixels)
        
        #r1 = QRectF(500, 500, ScanArrayXnum, int(Value_yPixels))
        #self.pmtimageitem.setRect(r1)
        
        self.pmtTest.pmtimagingThread.measurement.connect(self.update_pmt_Graphs) #Connecting to the measurement signal 
        self.pmt_fps_Label.setText("Per frame:  %.4f s" % time_per_frame_pmt)
        self.pmtTest.start()
        
    def measure_pmt_contourscan(self):
        self.Daq_sample_rate_pmt = int(self.contour_samprate.value())
        
        self.pmtTest_contour.setWave_contourscan(self.Daq_sample_rate_pmt, self.handle_viewbox_coordinate_position_array_expanded_forDaq, self.contour_point_number)
        contour_freq = self.Daq_sample_rate_pmt/self.contour_point_number
        
        #r1 = QRectF(500, 500, ScanArrayXnum, int(Value_yPixels))
        #self.pmtimageitem.setRect(r1)
        
        #self.pmtTest_contour.pmtimagingThread_contour.measurement.connect(self.update_pmt_Graphs) #Connecting to the measurement signal 
        self.pmt_fps_Label.setText("Contour frequency:  %.4f Hz" % contour_freq)
        self.pmtTest_contour.start()
        self.MessageToMainGUI('---!! Continuous contour scanning !!---'+'\n')
        
    def saveimage_pmt(self):
        Localimg = Image.fromarray(self.data_pmtcontineous) #generate an image object
        Localimg.save(os.path.join(self.savedirectory, 'PMT_'+ self.prefixtextboxtext + '_' +datetime.now().strftime('%Y-%m-%d_%H-%M-%S')+'.tif')) #save as tif
        #np.save(os.path.join(self.savedirectory, 'PMT'+ self.saving_prefix +datetime.now().strftime('%Y-%m-%d_%H-%M-%S')), self.data_pmtcontineous)
        
    def update_pmt_Graphs(self, data):
        """Update graphs."""
        
        self.data_pmtcontineous = data
        self.pmtvideoWidget.setImage(data)
        self.pmtimgroi.setImage(self.roi.getArrayRegion(data, self.pmtimageitem), levels=(0, data.max()))
        #

        #self.pmtvideoWidget.update_pmt_Window(self.data_pmtcontineous)
    def show_handle_num(self):
        self.ROIhandles = self.roi.getHandles()
        self.ROIhandles_nubmer = len(self.ROIhandles)
        self.pmt_handlenum_Label.setText("Handle number: %.d" % self.ROIhandles_nubmer)
        
    def generate_contour(self):
        """
        getLocalHandlePositions IS THE FUNCTION TO GRAP COORDINATES FROM IMAGEITEM REGARDLESS OF IMAGEITEM ZOOMING OR PANNING!!!
        """
        self.ROIhandles = self.roi.getHandles()
        self.ROIhandles_nubmer = len(self.ROIhandles)
        self.contour_point_number = int(self.pointsinContour.value())
        self.handle_scene_coordinate_position_raw_list = self.roi.getSceneHandlePositions()
        self.handle_local_coordinate_position_raw_list = self.roi.getLocalHandlePositions()
        self.Daq_sample_rate_pmt = int(self.contour_samprate.value())
#        self.galvo_contour_label_1.setText("Points in contour: %.d" % self.contour_point_number)
#        self.galvo_contour_label_2.setText("Sampling rate: %.d" % self.Daq_sample_rate_pmt)
        
        #put scene positions into numpy array
        self.handle_scene_coordinate_position_array = np.zeros((self.ROIhandles_nubmer, 2))# n rows, 2 columns
        for i in range(self.ROIhandles_nubmer):
            self.handle_scene_coordinate_position_array[i] = np.array([self.handle_scene_coordinate_position_raw_list[i][1].x(), self.handle_scene_coordinate_position_raw_list[i][1].y()])
        
        if self.contour_strategy.currentText() == 'Manual':
            #Interpolation
            self.point_num_per_line = int(self.contour_point_number/self.ROIhandles_nubmer)
            self.Interpolation_number = self.point_num_per_line-1
            
            # try to initialize an array then afterwards we can append on it
            #self.handle_scene_coordinate_position_array_expanded = np.array([[self.handle_scene_coordinate_position_array[0][0], self.handle_scene_coordinate_position_array[0][1]], [self.handle_scene_coordinate_position_array[1][0], self.handle_scene_coordinate_position_array[1][1]]])
            
            # -------------------------------------------------------------------------Interpolation from first to last----------------------------------------------------------------------------
            for i in range(self.ROIhandles_nubmer-1):
                self.Interpolation_x_diff = self.handle_scene_coordinate_position_array[i+1][0] - self.handle_scene_coordinate_position_array[i][0]
                self.Interpolation_y_diff = self.handle_scene_coordinate_position_array[i+1][1] - self.handle_scene_coordinate_position_array[i][1]
                
                self.Interpolation_x_step = self.Interpolation_x_diff/self.point_num_per_line
                self.Interpolation_y_step = self.Interpolation_y_diff/self.point_num_per_line
                
                Interpolation_temp = np.array([[self.handle_scene_coordinate_position_array[i][0], self.handle_scene_coordinate_position_array[i][1]], [self.handle_scene_coordinate_position_array[i+1][0], self.handle_scene_coordinate_position_array[i+1][1]]])
    
                for j in range(self.Interpolation_number):
                    Interpolation_temp=np.insert(Interpolation_temp,1,[self.handle_scene_coordinate_position_array[i+1][0] - (j+1)*self.Interpolation_x_step,self.handle_scene_coordinate_position_array[i+1][1] - (j+1)*self.Interpolation_y_step],axis = 0)
                Interpolation_temp = np.delete(Interpolation_temp, 0, 0)
                if i == 0:
                    self.handle_scene_coordinate_position_array_expanded = Interpolation_temp
                else:
                    self.handle_scene_coordinate_position_array_expanded=np.append(self.handle_scene_coordinate_position_array_expanded, Interpolation_temp, axis=0)
                    #self.handle_scene_coordinate_position_array_expanded=np.delete(self.handle_scene_coordinate_position_array_expanded, 0, 0)
            
            # Interpolation between last and first
            self.Interpolation_x_diff = self.handle_scene_coordinate_position_array[0][0] - self.handle_scene_coordinate_position_array[-1][0]
            self.Interpolation_y_diff = self.handle_scene_coordinate_position_array[0][1] - self.handle_scene_coordinate_position_array[-1][1]
            
            self.Interpolation_x_step = self.Interpolation_x_diff/self.point_num_per_line
            self.Interpolation_y_step = self.Interpolation_y_diff/self.point_num_per_line
            
            Interpolation_temp = np.array([[self.handle_scene_coordinate_position_array[-1][0], self.handle_scene_coordinate_position_array[-1][1]], [self.handle_scene_coordinate_position_array[0][0], self.handle_scene_coordinate_position_array[0][1]]])
    
            for j in range(self.Interpolation_number):
                Interpolation_temp=np.insert(Interpolation_temp,1,[self.handle_scene_coordinate_position_array[0][0] - (j+1)*self.Interpolation_x_step,self.handle_scene_coordinate_position_array[0][1] - (j+1)*self.Interpolation_y_step],axis = 0)
            Interpolation_temp = np.delete(Interpolation_temp, 0, 0)
            #Interpolation_temp = np.flip(Interpolation_temp, 0)
            
            self.handle_scene_coordinate_position_array_expanded=np.append(self.handle_scene_coordinate_position_array_expanded, Interpolation_temp, axis=0)
            #self.handle_scene_coordinate_position_array_expanded=np.delete(self.handle_scene_coordinate_position_array_expanded, 0, 0)
            #-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            
            self.handle_viewbox_coordinate_position_array_expanded = np.zeros((self.contour_point_number, 2))# n rows, 2 columns
            # Maps from scene coordinates to the coordinate system displayed inside the ViewBox
            for i in range(self.contour_point_number):
                qpoint_Scene = QPoint(self.handle_scene_coordinate_position_array_expanded[i][0], self.handle_scene_coordinate_position_array_expanded[i][1])
                qpoint_viewbox = self.pmtvb.mapSceneToView(qpoint_Scene)
                self.handle_viewbox_coordinate_position_array_expanded[i] = np.array([qpoint_viewbox.x(),qpoint_viewbox.y()])
                
            #print(self.handle_scene_coordinate_position_array)
            #print(self.handle_scene_coordinate_position_array_expanded)
            #print(self.handle_viewbox_coordinate_position_array_expanded)
            constants = HardwareConstants()
            '''Transform into Voltages to galvos'''
            '''coordinates in the view box(handle_viewbox_coordinate_position_array_expanded_x) are equivalent to voltages sending out'''
            if self.Value_xPixels == 500:
                if self.Value_voltXMax == 3:
                    # for 500 x axis, the real ramp region sits around 52~552 out of 0~758
                    self.handle_viewbox_coordinate_position_array_expanded[:,0] = ((self.handle_viewbox_coordinate_position_array_expanded[:,0])/500)*6-3 #(self.handle_viewbox_coordinate_position_array_expanded[:,0]-constants.pmt_3v_indentation_pixels)
                    self.handle_viewbox_coordinate_position_array_expanded[:,1] = ((self.handle_viewbox_coordinate_position_array_expanded[:,1])/500)*6-3
                    self.handle_viewbox_coordinate_position_array_expanded = np.around(self.handle_viewbox_coordinate_position_array_expanded, decimals=3)
                    # shape into (n,) and stack
                    self.handle_viewbox_coordinate_position_array_expanded_x = np.resize(self.handle_viewbox_coordinate_position_array_expanded[:,0],(self.contour_point_number,))
                    self.handle_viewbox_coordinate_position_array_expanded_y = np.resize(self.handle_viewbox_coordinate_position_array_expanded[:,1],(self.contour_point_number,))
                    self.handle_viewbox_coordinate_position_array_expanded_forDaq = np.vstack((self.handle_viewbox_coordinate_position_array_expanded_x,self.handle_viewbox_coordinate_position_array_expanded_y))
            print(self.handle_viewbox_coordinate_position_array_expanded)
            '''Speed and acceleration check'''
            #for i in range(self.contour_point_number):
             #   speed_between_points = ((self.handle_viewbox_coordinate_position_array_expanded_x[i+1]-self.handle_viewbox_coordinate_position_array_expanded_x[i])**2+(self.handle_viewbox_coordinate_position_array_expanded_y[i+1]-self.handle_viewbox_coordinate_position_array_expanded_y[i])**2)**(0.5)
            self.Daq_sample_rate_pmt = int(self.contour_samprate.value())
            time_gap = 1/self.Daq_sample_rate_pmt
            contour_x_speed = np.diff(self.handle_viewbox_coordinate_position_array_expanded_x)/time_gap
            contour_y_speed = np.diff(self.handle_viewbox_coordinate_position_array_expanded_y)/time_gap
            
            contour_x_acceleration = np.diff(contour_x_speed)/time_gap
            contour_y_acceleration = np.diff(contour_y_speed)/time_gap
            
            constants = HardwareConstants()
            speedGalvo = constants.maxGalvoSpeed #Volt/s
            aGalvo = constants.maxGalvoAccel #Acceleration galvo in volt/s^2
            print(np.amax(abs(contour_x_speed)))
            print(np.amax(abs(contour_y_speed)))
            print(np.amax(abs(contour_x_acceleration)))
            print(np.amax(abs(contour_y_acceleration)))  

            print(str(np.mean(abs(contour_x_speed)))+' and mean y speed:'+str(np.mean(abs(contour_y_speed))))
            print(str(np.mean(abs(contour_x_acceleration)))+' and mean y acceleration:'+str(np.mean(abs(contour_y_acceleration))))
            
            if speedGalvo > np.amax(abs(contour_x_speed)) and speedGalvo > np.amax(abs(contour_y_speed)):
                print('Contour speed is OK')
                self.MessageToMainGUI('Contour speed is OK'+'\n')
            else:
                QMessageBox.warning(self,'OverLoad','Speed too high!',QMessageBox.Ok)
            if aGalvo > np.amax(abs(contour_x_acceleration)) and aGalvo > np.amax(abs(contour_y_acceleration)):
                print('Contour acceleration is OK')
                self.MessageToMainGUI('Contour acceleration is OK'+'\n')
            else:
                QMessageBox.warning(self,'OverLoad','Acceleration too high!',QMessageBox.Ok)
                
        if self.contour_strategy.currentText() == 'Uniform':
            # Calculate the total distance
            self.total_distance = 0
            for i in range(self.ROIhandles_nubmer):
                if i != (self.ROIhandles_nubmer-1):
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[i+1][0] - self.handle_scene_coordinate_position_array[i][0]
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[i+1][1] - self.handle_scene_coordinate_position_array[i][1]
                    distance_vector = (Interpolation_x_diff**2+Interpolation_y_diff**2)**(0.5)
                    self.total_distance = self.total_distance + distance_vector
                else:
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[0][0] - self.handle_scene_coordinate_position_array[-1][0]
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[0][1] - self.handle_scene_coordinate_position_array[-1][1]
                    distance_vector = (Interpolation_x_diff**2+Interpolation_y_diff**2)**(0.5)
                    self.total_distance = self.total_distance + distance_vector            
            
            self.averaged_uniform_step = self.total_distance/self.contour_point_number
            
            print(self.averaged_uniform_step)
            print(self.handle_scene_coordinate_position_array)

            for i in range(self.ROIhandles_nubmer):
                if i == 0:
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[i+1][0] - self.handle_scene_coordinate_position_array[i][0]
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[i+1][1] - self.handle_scene_coordinate_position_array[i][1]
                    distance_vector = (Interpolation_x_diff**2+Interpolation_y_diff**2)**(0.5)    
                    num_of_Interpolation = distance_vector//self.averaged_uniform_step
                    
                    #Interpolation_remaining = distance_vector%self.averaged_uniform_step
                    self.Interpolation_remaining_fornextround = self.averaged_uniform_step*(1-(distance_vector/self.averaged_uniform_step-num_of_Interpolation))
                    print('Interpolation_remaining_fornextround: '+str(self.Interpolation_remaining_fornextround))
                    self.Interpolation_x_step = Interpolation_x_diff/(distance_vector/self.averaged_uniform_step)
                    self.Interpolation_y_step = Interpolation_y_diff/(distance_vector/self.averaged_uniform_step)
                    
                    Interpolation_temp = np.array([[self.handle_scene_coordinate_position_array[i][0], self.handle_scene_coordinate_position_array[i][1]], [self.handle_scene_coordinate_position_array[i+1][0], self.handle_scene_coordinate_position_array[i+1][1]]])
        
                    for j in range(int(num_of_Interpolation)):
                        Interpolation_temp=np.insert(Interpolation_temp,-1,[self.handle_scene_coordinate_position_array[i][0] + (j+1)*self.Interpolation_x_step,self.handle_scene_coordinate_position_array[i+1][1] + (j+1)*self.Interpolation_y_step],axis = 0)
                    Interpolation_temp = np.delete(Interpolation_temp,-1,axis=0) 
                    
                    self.handle_scene_coordinate_position_array_expanded_uniform = Interpolation_temp
                    
                elif i != (self.ROIhandles_nubmer-1):
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[i+1][0] - self.handle_scene_coordinate_position_array[i][0]
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[i+1][1] - self.handle_scene_coordinate_position_array[i][1]
                    distance_vector = (Interpolation_x_diff**2+Interpolation_y_diff**2)**(0.5)                    
                    num_of_Interpolation = (distance_vector-self.Interpolation_remaining_fornextround)//self.averaged_uniform_step       
                    print('Interpolation_remaining_fornextround: '+str(self.Interpolation_remaining_fornextround))
                    
                    if self.Interpolation_remaining_fornextround != 0:
                        self.Interpolation_remaining_fornextround_x =Interpolation_x_diff/(distance_vector/self.Interpolation_remaining_fornextround)#(self.Interpolation_remaining_fornextround/distance_vector)*Interpolation_x_diff
                        self.Interpolation_remaining_fornextround_y =Interpolation_y_diff/(distance_vector/self.Interpolation_remaining_fornextround)#(self.Interpolation_remaining_fornextround/distance_vector)*Interpolation_y_diff
                    else:
                        self.Interpolation_remaining_fornextround_x = 0
                        self.Interpolation_remaining_fornextround_y = 0
                        
                    
                    # Reset the starting point
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[i+1][0] - self.handle_scene_coordinate_position_array[i][0] - self.Interpolation_remaining_fornextround_x
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[i+1][1] - self.handle_scene_coordinate_position_array[i][1] - self.Interpolation_remaining_fornextround_y                 
                    
                    
                    self.Interpolation_x_step = Interpolation_x_diff/((distance_vector-self.Interpolation_remaining_fornextround)/self.averaged_uniform_step)
                    self.Interpolation_y_step = Interpolation_y_diff/((distance_vector-self.Interpolation_remaining_fornextround)/self.averaged_uniform_step)
                    
                    Interpolation_temp = np.array([[self.handle_scene_coordinate_position_array[i][0]+self.Interpolation_remaining_fornextround_x, self.handle_scene_coordinate_position_array[i][1]+self.Interpolation_remaining_fornextround_y],
                                                   [self.handle_scene_coordinate_position_array[i+1][0], self.handle_scene_coordinate_position_array[i+1][1]]])
        
                    for j in range(int(num_of_Interpolation)):
                        Interpolation_temp=np.insert(Interpolation_temp,-1,[self.handle_scene_coordinate_position_array[i][0]+self.Interpolation_remaining_fornextround_x + (j+1)*self.Interpolation_x_step,self.handle_scene_coordinate_position_array[i][1]+\
                                                                            self.Interpolation_remaining_fornextround_y + (j+1)*self.Interpolation_y_step],axis = 0)
                    Interpolation_temp = np.delete(Interpolation_temp,-1,axis=0)   
                    
                    self.handle_scene_coordinate_position_array_expanded_uniform=np.append(self.handle_scene_coordinate_position_array_expanded_uniform, Interpolation_temp, axis=0) 
                    
                    self.Interpolation_remaining_fornextround = self.averaged_uniform_step*(1-((distance_vector-self.Interpolation_remaining_fornextround)/self.averaged_uniform_step-num_of_Interpolation))
                    
                else:  # connect the first and the last
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[0][0] - self.handle_scene_coordinate_position_array[-1][0]
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[0][1] - self.handle_scene_coordinate_position_array[-1][1]
                    distance_vector = (Interpolation_x_diff**2+Interpolation_y_diff**2)**(0.5)                    
                    num_of_Interpolation = (distance_vector-self.Interpolation_remaining_fornextround)//self.averaged_uniform_step       
                    
                    #self.Interpolation_remaining_fornextround = self.averaged_uniform_step*(1-((distance_vector-self.Interpolation_remaining_fornextround)/self.averaged_uniform_step-num_of_Interpolation))
                    self.Interpolation_remaining_fornextround_x =(self.Interpolation_remaining_fornextround/distance_vector)*Interpolation_x_diff
                    self.Interpolation_remaining_fornextround_y =(self.Interpolation_remaining_fornextround/distance_vector)*Interpolation_y_diff
                    
                    # Reset the starting point
                    Interpolation_x_diff = self.handle_scene_coordinate_position_array[0][0] - self.handle_scene_coordinate_position_array[i][0] + self.Interpolation_remaining_fornextround_x
                    Interpolation_y_diff = self.handle_scene_coordinate_position_array[0][1] - self.handle_scene_coordinate_position_array[i][1] + self.Interpolation_remaining_fornextround_y   
                    
                    self.Interpolation_x_step = Interpolation_x_diff/((distance_vector-self.Interpolation_remaining_fornextround)/self.averaged_uniform_step)
                    self.Interpolation_y_step = Interpolation_y_diff/((distance_vector-self.Interpolation_remaining_fornextround)/self.averaged_uniform_step)  
                    
                    Interpolation_temp = np.array([[self.handle_scene_coordinate_position_array[-1][0]+self.Interpolation_remaining_fornextround_x, self.handle_scene_coordinate_position_array[-1][1]+self.Interpolation_remaining_fornextround_y], 
                                                   [self.handle_scene_coordinate_position_array[0][0], self.handle_scene_coordinate_position_array[0][1]]])
        
                    for j in range(int(num_of_Interpolation)):
                        Interpolation_temp=np.insert(Interpolation_temp,-1,[self.handle_scene_coordinate_position_array[-1][0]+self.Interpolation_remaining_fornextround_x + (j+1)*self.Interpolation_x_step,self.handle_scene_coordinate_position_array[-1][1]+\
                                                     self.Interpolation_remaining_fornextround_y + (j+1)*self.Interpolation_y_step],axis = 0)
                    Interpolation_temp = np.delete(Interpolation_temp,-1,axis=0)   
                    
                    self.handle_scene_coordinate_position_array_expanded_uniform=np.append(self.handle_scene_coordinate_position_array_expanded_uniform, Interpolation_temp, axis=0)        
            
            print(self.handle_scene_coordinate_position_array_expanded_uniform)
            print(self.handle_scene_coordinate_position_array_expanded_uniform.shape)
            #-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            
            self.handle_viewbox_coordinate_position_array_expanded = np.zeros((self.contour_point_number, 2))# n rows, 2 columns
            # Maps from scene coordinates to the coordinate system displayed inside the ViewBox
            for i in range(self.contour_point_number):
                qpoint_Scene = QPoint(self.handle_scene_coordinate_position_array_expanded_uniform[i][0], self.handle_scene_coordinate_position_array_expanded_uniform[i][1])
                qpoint_viewbox = self.pmtvb.mapSceneToView(qpoint_Scene)
                self.handle_viewbox_coordinate_position_array_expanded[i] = np.array([qpoint_viewbox.x(),qpoint_viewbox.y()])
                
            #print(self.handle_scene_coordinate_position_array)
            #print(self.handle_scene_coordinate_position_array_expanded)
            #print(self.handle_viewbox_coordinate_position_array_expanded)
            
            '''Transform into Voltages to galvos'''
            
            constants = HardwareConstants()
            if self.Value_xPixels == 500:
                if self.Value_voltXMax == 3:
                    # for 500 x axis, the real ramp region sits around 52~552 out of 0~758
                    self.handle_viewbox_coordinate_position_array_expanded[:,0] = ((self.handle_viewbox_coordinate_position_array_expanded[:,0])/500)*6-3 #self.handle_viewbox_coordinate_position_array_expanded[:,0]-constants.pmt_3v_indentation_pixels
                    self.handle_viewbox_coordinate_position_array_expanded[:,1] = ((self.handle_viewbox_coordinate_position_array_expanded[:,1])/500)*6-3
                    self.handle_viewbox_coordinate_position_array_expanded = np.around(self.handle_viewbox_coordinate_position_array_expanded, decimals=3)
                    # shape into (n,) and stack
                    self.handle_viewbox_coordinate_position_array_expanded_x = np.resize(self.handle_viewbox_coordinate_position_array_expanded[:,0],(self.contour_point_number,))
                    self.handle_viewbox_coordinate_position_array_expanded_y = np.resize(self.handle_viewbox_coordinate_position_array_expanded[:,1],(self.contour_point_number,))
                    self.handle_viewbox_coordinate_position_array_expanded_forDaq = np.vstack((self.handle_viewbox_coordinate_position_array_expanded_x,self.handle_viewbox_coordinate_position_array_expanded_y))
            print(self.handle_viewbox_coordinate_position_array_expanded)
            '''Speed and acceleration check'''
            #for i in range(self.contour_point_number):
             #   speed_between_points = ((self.handle_viewbox_coordinate_position_array_expanded_x[i+1]-self.handle_viewbox_coordinate_position_array_expanded_x[i])**2+(self.handle_viewbox_coordinate_position_array_expanded_y[i+1]-self.handle_viewbox_coordinate_position_array_expanded_y[i])**2)**(0.5)
            self.Daq_sample_rate_pmt = int(self.contour_samprate.value())
            time_gap = 1/self.Daq_sample_rate_pmt
            contour_x_speed = np.diff(self.handle_viewbox_coordinate_position_array_expanded_x)/time_gap
            contour_y_speed = np.diff(self.handle_viewbox_coordinate_position_array_expanded_y)/time_gap
            
            contour_x_acceleration = np.diff(contour_x_speed)/time_gap
            contour_y_acceleration = np.diff(contour_y_speed)/time_gap
            
            constants = HardwareConstants()
            speedGalvo = constants.maxGalvoSpeed #Volt/s
            aGalvo = constants.maxGalvoAccel #Acceleration galvo in volt/s^2
            print(np.amax(abs(contour_x_speed)))
            print(np.amax(abs(contour_y_speed)))
            print(np.amax(abs(contour_x_acceleration)))
            print(np.amax(abs(contour_y_acceleration)))  

            print(str(np.mean(abs(contour_x_speed)))+' and mean y speed:'+str(np.mean(abs(contour_y_speed))))
            print(str(np.mean(abs(contour_x_acceleration)))+' and mean y acceleration:'+str(np.mean(abs(contour_y_acceleration))))
            
            if speedGalvo > np.amax(abs(contour_x_speed)) and speedGalvo > np.amax(abs(contour_y_speed)):
                print('Contour speed is OK')
                self.MessageToMainGUI('Contour speed is OK'+'\n')
            if aGalvo > np.amax(abs(contour_x_acceleration)) and aGalvo > np.amax(abs(contour_y_acceleration)):
                print('Contour acceleration is OK')
                self.MessageToMainGUI('Contour acceleration is OK'+'\n')
        
        self.SignalForContourScanning.emit(self.contour_point_number, self.Daq_sample_rate_pmt, (1/int(self.contour_samprate.value())*1000)*self.contour_point_number, 
                                           self.handle_viewbox_coordinate_position_array_expanded_x, self.handle_viewbox_coordinate_position_array_expanded_y)
        
    def generate_contour_for_waveform(self):
        self.contour_time = int(self.textbox1L.value())
        self.time_per_contour = (1/int(self.contour_samprate.value())*1000)*self.contour_point_number
        repeatnum_contour = int(self.contour_time/self.time_per_contour)
        self.repeated_contoursamples_1 = np.tile(self.handle_viewbox_coordinate_position_array_expanded_x, repeatnum_contour)
        self.repeated_contoursamples_2 = np.tile(self.handle_viewbox_coordinate_position_array_expanded_y, repeatnum_contour)       
        
        self.handle_viewbox_coordinate_position_array_expanded_forDaq_waveform = np.vstack((self.repeated_contoursamples_1,self.repeated_contoursamples_2))
                
        return self.handle_viewbox_coordinate_position_array_expanded_forDaq_waveform
        
    def generate_galvos_contour_graphy(self):

        self.xlabelhere_galvos = np.arange(len(self.handle_viewbox_coordinate_position_array_expanded_forDaq_waveform[1,:]))/self.Daq_sample_rate_pmt
        self.PlotDataItem_galvos = PlotDataItem(self.xlabelhere_galvos, self.handle_viewbox_coordinate_position_array_expanded_forDaq_waveform[1,:])
        self.PlotDataItem_galvos.setDownsampling(auto=True, method='mean')            
        self.PlotDataItem_galvos.setPen('w')

        self.pw.addItem(self.PlotDataItem_galvos)
        self.textitem_galvos = pg.TextItem(text='Contour', color=('w'), anchor=(1, 1))
        self.textitem_galvos.setPos(0, 5)
        self.pw.addItem(self.textitem_galvos)
        
    def MessageToMainGUI(self, text):
        self.MessageBack.emit(text)
                    
    def stopMeasurement_pmt(self):
        """Stop the seal test."""
        self.pmtTest.aboutToQuitHandler()
        
    def stopMeasurement_pmt_contour(self):
        """Stop the seal test."""
        self.pmtTest_contour.aboutToQuitHandler()
        self.MessageToMainGUI('---!! Contour stopped !!---'+'\n')
        
#    def closeEvent(self, event):
#            
#        QtWidgets.QApplication.quit()
#        event.accept()
    '''