Esempio n. 1
0
    def __init__(self, parent=None):
        super(ExperimentResultWidget, self).__init__()

        self.tab = QtGui.QTabWidget()

        # Figure 1
        figure = plt.figure()
        canvas = FigureCanvas(figure)
        canvas.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        canvas.setMinimumSize(50, 50)
        toolbar = NavigationToolbar(canvas, self)
        toolbar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        widget = QtGui.QWidget()
        layout = QtGui.QVBoxLayout()
        layout.addWidget(canvas)
        layout.addWidget(toolbar)
        widget.setLayout(layout)
        self.tab.addTab(widget, 'Results')
        self.plot = figure

        # Tab 1
        self.trackCountsTable = QtGui.QTableWidget()
        self.tab.addTab(self.trackCountsTable, 'Track Counts')

        # Tab 2
        self.networkOverviewTable = QtGui.QTableWidget()
        self.tab.addTab(self.networkOverviewTable, 'Network Overview')

        # Tab 3
        self.trackTerminationTable = QtGui.QTableWidget()
        self.trackInitiationTable = QtGui.QTableWidget()

        widget = QtGui.QWidget()
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.trackTerminationTable)
        layout.addWidget(self.trackInitiationTable)
        widget.setLayout(layout)
        self.tab.addTab(widget, 'Track Fragmentation')

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.tab)
        self.setLayout(layout)
Esempio n. 2
0
class PandasMplWidget(QtGui.QWidget):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.pmc = PandasMplCanvas(width=2, height=2, dpi=100)
        self.toolbar = NavigationToolbar(self.pmc.figure.canvas, self)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Fixed)
        sizePolicy.setHeightForWidth(True)
        self.toolbar.setSizePolicy(sizePolicy)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(self.pmc)
        vbox.addWidget(self.toolbar)
        self.setLayout(vbox)

    def get_figure_canvas(self):
        return self.pmc

    def plot(self, data):
        self.pmc.plot_data_frame(data)
Esempio n. 3
0
class ThresholdCacheWidget(QtGui.QWidget):
    def __init__(self, on_changed_ev, parent=None):
        super(ThresholdCacheWidget, self).__init__()
        self.on_changed_ev = on_changed_ev
        self.parent = parent

        self.histogram_figure = plt.figure()
        self.histogram_canvas = FigureCanvas(self.histogram_figure)
        self.histogram_canvas.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.histogram_canvas.setMinimumSize(50, 50)
        self.histogram_toolbar = NavigationToolbar(self.histogram_canvas, parent)
        self.histogram_toolbar.coordinates = False
        self.histogram_toolbar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        self.image_figure = plt.figure()
        self.image_canvas = FigureCanvas(self.image_figure)
        self.image_canvas.setMinimumSize(50, 50)
        self.image_canvas.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.image_toolbar = NavigationToolbar(self.image_canvas, parent)
        self.image_toolbar.coordinates = False
        self.image_toolbar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        gs = grd.GridSpec(3, 1)
        self.ax_objects = self.histogram_figure.add_subplot(gs[0, 0])
        self.ax_area = self.histogram_figure.add_subplot(gs[1, 0], sharex=self.ax_objects)
        self.ax_image = self.image_figure.add_subplot(111)

        layout = QtGui.QGridLayout()

        q1 = QtGui.QLabel("<b>Choose Threshold</b>")
        layout.addWidget(q1, 0, 0, 1, 1)
        layout.addWidget(QtGui.QLabel("Click on either graph to pick a threshold value"), 1, 0, 1, 1)
        layout.addWidget(self.histogram_canvas, 3, 0, 1, 1)
        layout.addWidget(self.histogram_toolbar, 4, 0, 1, 1)

        self.roiSelectorBar = ROISelectorBar(self.image_figure, self.ax_image)
        self.roiSelectorBar.roi_changed.connect(self.roiSelectorBar_roi_changed)

        self.calibrationBar = CalibrationBar(10, self.image_figure, self.ax_image)
        self.calibrationBar.calibration_changed.connect(self.calibrationBar_calibration_changed)

        q2 = QtGui.QLabel("<b>Define Region of Interest</b>")
        layout.addWidget(q2, 0, 1, 1, 1)
        layout.addWidget(self.roiSelectorBar, 1, 1, 1, 1)
        layout.addWidget(self.calibrationBar, 2, 1, 1, 1)
        layout.addWidget(self.image_canvas, 3, 1, 1, 1)
        layout.addWidget(self.image_toolbar, 4, 1, 1, 1)
        self.setLayout(layout)

        self.histogram_figure.canvas.mpl_connect('button_press_event', self.on_histogram_button_pressed)
        # self.image_figure.canvas.mpl_connect('button_press_event', self.on_image_button_pressed)

        self.thresholds = []

    @staticmethod
    def create_background(impaths):
        """
        create a background image for background subtraction.
        The background image is the maximum pixel values from three grayscale images.

        params
        ---------
        impaths: (list)
           this is a sorted list containing paths to all the image files from one recording.
        """
        if len(impaths) == 0:
            return None
        first = mpimg.imread(impaths[0])
        mid = mpimg.imread(impaths[int(len(impaths)/2)])
        last = mpimg.imread(impaths[-1])
        return np.maximum(np.maximum(first, mid), last)

    def clear_experiment_data(self):
        self.roiSelectorBar.clear_roi()
        self.threshold = 0.0005

    def load_experiment(self, experiment):
        self.experiment = experiment
        self.annotation_filename = str(paths.threshold_data(experiment.id))
        try:
            with open(self.annotation_filename, "rt") as f:
                data = json.loads(f.read())
            # self.circle = None
            self.roiSelectorBar.json_to_data(data)
            self.threshold = data.get('threshold', 0.0005)
        except IOError as ex:
            self.clear_experiment_data()

        self.calibration_filename = str(paths.calibration_data(experiment.id))
        try:
            with open(self.calibration_filename, "rt") as f:
                data = json.loads(f.read())
            self.calibrationBar.json_to_data(data)
        except IOError as ex:
            self.calibrationBar.clear_calibration()

        times, impaths = zip(*sorted(experiment.image_files.items()))
        impaths = [str(s) for s in impaths]

        if times is not None and len(times) > 0:
            times = [float(t) for t in times]
            times, impaths = zip(*sorted(zip(times, impaths)))

        if impaths is None or len(impaths) == 0:
            self.background = None
            self.mid_image = None
            self.plate_distance = None
            self.roiSelectorBar.set_guess_polygon([])
        else:
            self.background = ThresholdCacheWidget.create_background(impaths)
            self.im_shape = self.background.shape # shape is (y,x)
            self.mid_image = mpimg.imread(impaths[int(len(impaths)/2)])
            self.plate_distance = PlateDistance(self.background)
            self.plate_distance.calculate()
            p = self.plate_distance.polygon(border=settings.ROI_BORDER_OFFSET, corner=settings.ROI_CORNER_OFFSET)
            p = [(y, x) for x, y in p]
            self.roiSelectorBar.set_guess_polygon(p)

        self.calibrationBar.update_plate_distance(self.plate_distance)
        self.mouse_points = []
        QTimer.singleShot(0, self.show_dialog)

    def show_dialog(self):
        dlg = CacheThresholdLoadingDialog(self.experiment.id, self.calculate_threshold, self.finished, self.parent)
        dlg.setModal(True)
        dlg.exec_()

    def calculate_threshold(self, callback):
        self.thresholds = []
        for i, t in enumerate(np.linspace(start=0.00001, stop=0.001, num=30)):
            valid, N, m, s = self.data_from_threshold(t)
            if valid:
                self.thresholds.append((t, N, m, s))
            callback(0, i / 30.)
        callback(0, 1)

    def finished(self):
        self.update_data(self.thresholds, self.threshold)
        self.histogram_figure.canvas.draw()

    def isComplete(self):
        return self.roiSelectorBar.isComplete()

    def create_binary_mask(self, img, background, threshold, minsize=100):
        """
        creates a binary array the same size as the image with 1s denoting objects
        and 0s denoting background.

        params
        --------
        img: (image ie. numpy array)
            each pixel denotes greyscale pixel intensities.
        background: (image ie. numpy array)
            the background image with maximum pixel intensities (made with create_background)
        threshold: (float)
            the threshold value used to create the binary mask after pixel intensities for (background - image) have been calculated.
        minsize: (int)
            the fewest allowable pixels for an object. objects with an area containing fewer pixels are removed.
        """
        if img is None or background is None:
            return None
        mask = (background - img) > threshold
        result = morphology.remove_small_objects(mask, minsize)
        return result

    def data_from_threshold(self, threshold):
        if self.mid_image is None:
            return False, None, None, None
        mask = self.create_binary_mask(self.mid_image, self.background, threshold=threshold)
        labels, N = ndimage.label(mask)
        sizes = [r.area for r in regionprops(labels)]
        if len(sizes) == 0:
            return False, None, None, None
        else:
            m, s = np.mean(sizes), np.std(sizes)
            return True, N, m, s

    @staticmethod
    def mkdir_p(path):
        try:
            os.makedirs(path)
        except OSError as exc: # Python >2.5
            if exc.errno == errno.EEXIST and os.path.isdir(path):
                pass
            else: raise

    def save_roi_data(self):
        if self.annotation_filename is None:
            return

        # note: the image is usually transposed. we didn't here,
        # so x and y are flipped during saving process.
        data = self.roiSelectorBar.data_to_json()
        data['threshold'] = self.threshold
        data['shape'] = self.im_shape

        ThresholdCacheWidget.mkdir_p(os.path.dirname(self.annotation_filename))
        with open(self.annotation_filename, "wt") as f:
            f.write(json.dumps(data, indent=4))

    def save_calibration_data(self):
        if self.calibration_filename is None:
            return

        data = self.calibrationBar.data_to_json()
        ThresholdCacheWidget.mkdir_p(os.path.dirname(self.calibration_filename))
        with open(self.calibration_filename, "wt") as f:
            f.write(json.dumps(data, indent=4))

    def update_data(self, thresholds, current_threshold):
        if len(thresholds) == 0:
            self.ax_objects.clear()
            self.ax_area.clear()
            self.ax_image.clear()
            self.line_objects = None
            self.line_area = None
            return

        x, ns, means, stds = zip(*thresholds)
        final_t = x[-1]

        # make the plot
        self.ax_objects.clear()
        self.ax_objects.plot(x, ns, '.-', color='black')
        self.ax_objects.set_ylabel('N Objects')
        self.ax_objects.set_ylim([0, 150])

        top = np.array(means) + np.array(stds)
        bottom = np.array(means) - np.array(stds)

        self.ax_area.clear()
        self.ax_area.plot(x, means, '.-', color='blue', label='mean')
        self.ax_area.fill_between(x, top, bottom, color='green', alpha=0.5)
        # self.ax_area.plot(x, top, '--', color='green', label='mean')
        # self.ax_area.plot(x, bottom, '--', color='green', label='mean - std')
        self.ax_area.axvline(x=.5, ymin=0, ymax=1)
        self.ax_area.legend(loc='upper right')

        self.ax_area.set_ylim([0, 600])
        self.ax_area.set_ylabel('Blob Area (pxls)')
        self.ax_area.set_xlabel('Contrast Threshold')
        self.ax_objects.set_xlim([0, final_t])

        self.line_objects = self.ax_objects.plot((current_threshold, current_threshold), (-10000, 10000), '--', color='red')
        self.line_area = self.ax_area.plot((current_threshold, current_threshold), (-1000000, 1000000), '--', color='red')
        self.show_threshold()

    def show_threshold(self):
        """
        plots an image with the outlines of all objects overlaid on top.

        params
        --------
        img: (image ie. numpy array)
            each pixel denotes greyscale pixel intensities.
        background: (image ie. numpy array)
            the background image with maximum pixel intensities (made with create_background)
        threshold: (float)
            the threshold value used to create the binary mask after pixel intensities for (background - image) have been calculated.
        """
        mask = self.create_binary_mask(self.mid_image, self.background, self.threshold)
        self.ax_image.clear()
        self.ax_image.imshow(self.mid_image, cmap=plt.cm.gray, interpolation='nearest')
        self.ax_image.contour(mask, [0.5], linewidths=1.2, colors='b')
        self.ax_image.axis('off')

        self.roiSelectorBar.update_image()
        self.calibrationBar.update_image()

    def on_histogram_button_pressed(self, ev):
        if self.threshold != ev.xdata:
            self.threshold = ev.xdata

            if self.line_objects is not None and len(self.line_objects) > 0:
                self.line_objects[0].remove()
            if self.line_area is not None and len(self.line_area) > 0:
                self.line_area[0].remove()
            self.line_objects = self.ax_objects.plot((self.threshold, self.threshold), (-10000, 10000), '--', color='red')
            self.line_area = self.ax_area.plot((self.threshold, self.threshold), (-1000000, 1000000), '--', color='red')

            self.show_threshold()
            self.histogram_figure.canvas.draw()
            self.save_roi_data()

    def roiSelectorBar_roi_changed(self):
        self.save_roi_data()
        self.on_changed_ev()

    def calibrationBar_calibration_changed(self):
        self.save_calibration_data()