Exemple #1
0
def generateRandomColors(M=256, colormodel="hsv", clamp=None, zeroIsTransparent=False):
    """Generate a colortable with M entries.
       colormodel: currently only 'hsv' is supported
       clamp:      A dictionary stating which parameters of the color in the colormodel are clamped to a certain
                   value. For example: clamp = {'v': 1.0} will ensure that the value of any generated
                   HSV color is 1.0. All other parameters (h,s in the example) are selected randomly
                   to lie uniformly in the allowed range. """
    r = numpy.random.random((M, 3))
    if clamp is not None:
        for k, v in clamp.items():
            idx = colormodel.index(k)
            r[:, idx] = v

    colors = []
    if colormodel == "hsv":
        for i in range(M):
            if zeroIsTransparent and i == 0:
                colors.append(QColor(0, 0, 0, 0).rgba())
            else:
                h, s, v = r[i, :]
                color = numpy.asarray(colorsys.hsv_to_rgb(h, s, v)) * 255
                qColor = QColor(*color)
                colors.append(qColor.rgba())
        return colors
    else:
        raise RuntimeError("unknown color model '%s'" % colormodel)
Exemple #2
0
def generateRandomColors(M=256,
                         colormodel="hsv",
                         clamp=None,
                         zeroIsTransparent=False):
    """Generate a colortable with M entries.
       colormodel: currently only 'hsv' is supported
       clamp:      A dictionary stating which parameters of the color in the colormodel are clamped to a certain
                   value. For example: clamp = {'v': 1.0} will ensure that the value of any generated
                   HSV color is 1.0. All other parameters (h,s in the example) are selected randomly
                   to lie uniformly in the allowed range. """
    r = numpy.random.random((M, 3))
    if clamp is not None:
        for k, v in clamp.items():
            idx = colormodel.index(k)
            r[:, idx] = v

    colors = []
    if colormodel == "hsv":
        for i in range(M):
            if zeroIsTransparent and i == 0:
                colors.append(QColor(0, 0, 0, 0).rgba())
            else:
                h, s, v = r[i, :]
                color = numpy.asarray(colorsys.hsv_to_rgb(h, s, v)) * 255
                qColor = QColor(*color)
                colors.append(qColor.rgba())
        return colors
    else:
        raise RuntimeError("unknown color model '%s'" % colormodel)
 def makeColor(self, specOrFreq):
     col = QColor()
     col.setRgba(int(self.config[specOrFreq]))
     col = QColorDialog.getColor(
         col, self, "Choose color of " + specOrFreq + " in the graph",
         QColorDialog.ShowAlphaChannel)
     self.config[specOrFreq] = str(col.rgba())
     return col
Exemple #4
0
def randColor():
	global nextRand
	global goldenRatioConjugate
	
	color = QColor()
	color.setHsvF(nextRand, 0.5, 1.0, 0.65)
	nextRand += goldenRatioConjugate
	nextRand %= 1
	return color.rgba()
    def getNextCropColor(self):
        """
        Return a QColor to use for the next crop.
        """
        numCrops = self._maxCropNumUsed+1
        if numCrops >= len(self._colorTable16)-1:
            # If the color table isn't large enough to handle all our crops,
            #  append a random color
            randomColor = QColor(numpy.random.randint(0,255), numpy.random.randint(0,255), numpy.random.randint(0,255))
            self._colorTable16.append( randomColor.rgba() )

        color = QColor()
        color.setRgba(self._colorTable16[numCrops+1]) # First entry is transparent (for zero crop)
        return color
Exemple #6
0
    def getNextLabelColor(self):
        """
        Return a QColor to use for the next label.
        """
        numLabels = len(self._labelControlUi.labelListModel)
        if numLabels >= len(self._colorTable16)-1:
            # If the color table isn't large enough to handle all our labels,
            #  append a random color
            randomColor = QColor(numpy.random.randint(0,255), numpy.random.randint(0,255), numpy.random.randint(0,255))
            self._colorTable16.append(randomColor.rgba())

        color = QColor()
        color.setRgba(self._colorTable16[numLabels+1])  # First entry is transparent (for zero label)
        return color
    def getNextCropColor(self):
        """
        Return a QColor to use for the next crop.
        """
        numCrops = self._maxCropNumUsed + 1
        if numCrops >= len(self._colorTable16) - 1:
            # If the color table isn't large enough to handle all our crops,
            #  append a random color
            randomColor = QColor(numpy.random.randint(0, 255),
                                 numpy.random.randint(0, 255),
                                 numpy.random.randint(0, 255))
            self._colorTable16.append(randomColor.rgba())

        color = QColor()
        color.setRgba(self._colorTable16[
            numCrops + 1])  # First entry is transparent (for zero crop)
        return color
Exemple #8
0
def matplotlib_to_qt4_colortable(cmap_name, N, asLong=True):
    """
    get a colortable of desired N in Qt4 format as required from the colortable Layer
    cmap_name can be any matplotlib colortable
    """
    try:
        import matplotlib.cm as cm
    except:
        raise RuntimeError("this function requires matplotlib")

    cmap = cm.get_cmap(cmap_name, N)
    cmap = cmap(np.arange(N))[:, :-1]
    colortable = []
    for el in cmap:
        r, g, b = el * 255
        color = QColor(r, g, b)
        if asLong:
            color = color.rgba()
        colortable.append(color)
    return colortable
Exemple #9
0
def matplotlib_to_qt4_colortable(cmap_name, N, asLong=True):
    """
    get a colortable of desired N in Qt4 format as required from the colortable Layer
    cmap_name can be any matplotlib colortable
    """
    try:
        import matplotlib.cm as cm
    except:
        raise RuntimeError("this function requires matplotlib")

    cmap = cm.get_cmap(cmap_name, N)
    cmap = cmap(np.arange(N))[:, :-1]
    colortable = []
    for el in cmap:
        r, g, b = el * 255
        color = QColor(r, g, b)
        if asLong:
            color = color.rgba()
        colortable.append(color)
    return colortable
def cvt_vtr(self):
    QSWATMOD_path_dict = self.dirs_and_paths()
    selectedVector = self.dlg.comboBox_vector_lyrs.currentText()
    layer = QgsProject.instance().mapLayersByName(str(selectedVector))[0]

    # Find .dis file and read number of rows, cols, x spacing, and y spacing (not allowed to change)
    for filename in glob.glob(str(QSWATMOD_path_dict['SMfolder']) + "/*.dis"):
        with open(filename, "r") as f:
            data = []
            for line in f.readlines():
                if not line.startswith("#"):
                    data.append(line.replace('\n', '').split())
        nrow = int(data[0][1])
        ncol = int(data[0][2])
        delr = float(data[2][1])  # is the cell width along rows (y spacing)
        delc = float(
            data[3][1])  # is the cell width along columns (x spacing).

    # get extent
    ext = layer.extent()
    xmin = ext.xMinimum()
    xmax = ext.xMaximum()
    ymin = ext.yMinimum()
    ymax = ext.yMaximum()
    extent = "{a},{b},{c},{d}".format(a=xmin, b=xmax, c=ymin, d=ymax)

    fdnames = [
        field.name() for field in layer.dataProvider().fields()
        if not (field.name() == 'fid' or field.name() == 'id'
                or field.name() == 'xmin' or field.name() == 'xmax'
                or field.name() == 'ymin' or field.name() == 'ymax'
                or field.name() == 'grid_id' or field.name() == 'row'
                or field.name() == 'col' or field.name() == 'elev_mf')
    ]

    # Create swatmf_results tree inside
    root = QgsProject.instance().layerTreeRoot()
    if root.findGroup("swatmf_results"):
        swatmf_results = root.findGroup("swatmf_results")
    else:
        swatmf_results = root.insertGroup(0, "swatmf_results")

    if root.findGroup(selectedVector):
        rastergroup = root.findGroup(selectedVector)
    else:
        rastergroup = swatmf_results.insertGroup(0, selectedVector)
    per = 0
    self.dlg.progressBar_cvt_vtr.setValue(0)
    for fdnam in fdnames:
        QCoreApplication.processEvents()
        nodata = float(self.dlg.lineEdit_nodata.text())
        mincolor = self.dlg.mColorButton_min_rmap.color().name()
        maxcolor = self.dlg.mColorButton_max_rmap.color().name()
        name = fdnam
        name_ext = "{}.tif".format(name)
        output_dir = QSWATMOD_path_dict['SMshps']
        # create folder for each layer output
        rasterpath = os.path.join(output_dir, selectedVector)
        if not os.path.exists(rasterpath):
            os.makedirs(rasterpath)
        output_raster = os.path.join(rasterpath, name_ext)
        params = {
            'INPUT': layer,
            'FIELD': fdnam,
            'UNITS': 1,
            'WIDTH': delc,
            'HEIGHT': delr,
            'EXTENT': extent,
            'NODATA': nodata,
            'DATA_TYPE': 5,  #Float32
            'OUTPUT': output_raster
        }
        processing.run("gdal:rasterize", params)
        rasterlayer = QgsRasterLayer(output_raster,
                                     '{0} ({1})'.format(fdnam, selectedVector))
        QgsProject.instance().addMapLayer(rasterlayer, False)
        rastergroup.insertChildNode(0, QgsLayerTreeLayer(rasterlayer))
        stats = rasterlayer.dataProvider().bandStatistics(
            1, QgsRasterBandStats.All)
        rmin = stats.minimumValue
        rmax = stats.maximumValue
        fnc = QgsColorRampShader()
        lst = [
            QgsColorRampShader.ColorRampItem(rmin, QColor(mincolor)),
            QgsColorRampShader.ColorRampItem(rmax, QColor(maxcolor))
        ]
        fnc.setColorRampItemList(lst)
        fnc.setColorRampType(QgsColorRampShader.Interpolated)
        shader = QgsRasterShader()
        shader.setRasterShaderFunction(fnc)
        renderer = QgsSingleBandPseudoColorRenderer(rasterlayer.dataProvider(),
                                                    1, shader)
        rasterlayer.setRenderer(renderer)
        rasterlayer.triggerRepaint()

        # create image
        img = QImage(QSize(800, 800), QImage.Format_ARGB32_Premultiplied)
        # set background color
        # bcolor = QColor(255, 255, 255, 255)
        bcolor = QColor(255, 255, 255, 0)
        img.fill(bcolor.rgba())
        # create painter
        p = QPainter()
        p.begin(img)
        p.setRenderHint(QPainter.Antialiasing)
        # create map settings
        ms = QgsMapSettings()
        ms.setBackgroundColor(bcolor)

        # set layers to render
        flayer = QgsProject.instance().mapLayersByName(rasterlayer.name())
        ms.setLayers([flayer[0]])

        # set extent
        rect = QgsRectangle(ms.fullExtent())
        rect.scale(1.1)
        ms.setExtent(rect)

        # set ouptut size
        ms.setOutputSize(img.size())

        # setup qgis map renderer
        render = QgsMapRendererCustomPainterJob(ms, p)
        render.start()
        render.waitForFinished()
        # get timestamp
        p.drawImage(QPoint(), img)
        pen = QPen(Qt.red)
        pen.setWidth(2)
        p.setPen(pen)

        font = QFont()
        font.setFamily('Times')
        # font.setBold(True)
        font.setPointSize(18)
        p.setFont(font)
        # p.setBackground(QColor('sea green')) doesn't work
        p.drawText(QRect(0, 0, 800, 800), Qt.AlignRight | Qt.AlignBottom,
                   fdnam)
        p.end()

        # save the image
        img.save(os.path.join(rasterpath, '{:03d}_{}.jpg'.format(per, fdnam)))

        # Update progress bar
        per += 1
        progress = round((per / len(fdnames)) * 100)
        self.dlg.progressBar_cvt_vtr.setValue(progress)
        QCoreApplication.processEvents()
        self.dlg.raise_()

    duration = self.dlg.doubleSpinBox_ani_r_time.value()

    # filepaths
    fp_in = os.path.join(rasterpath, '*.jpg')
    fp_out = os.path.join(rasterpath, '{}.gif'.format(selectedVector))

    # https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif
    fimg, *fimgs = [Image.open(f) for f in sorted(glob.glob(fp_in))]
    fimg.save(fp=fp_out,
              format='GIF',
              append_images=fimgs,
              save_all=True,
              duration=duration * 1000,
              loop=0,
              transparency=0)

    msgBox = QMessageBox()
    msgBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png'))
    msgBox.setWindowTitle("Coverted!")
    msgBox.setText(
        "Fields from {} were converted successfully!".format(selectedVector))
    msgBox.exec_()

    questionBox = QMessageBox()
    questionBox.setWindowIcon(QtGui.QIcon(':/QSWATMOD2/pics/sm_icon.png'))
    reply = QMessageBox.question(questionBox, 'Open?',
                                 'Do you want to open the animated gif file?',
                                 QMessageBox.Yes, QMessageBox.No)
    if reply == QMessageBox.Yes:
        os.startfile(os.path.join(rasterpath, '{}.gif'.format(selectedVector)))
Exemple #11
0
class MaskTransparencyWidget(QWidget):
    def __init__(self, parent, imgPaths, fov_id_list, mask_dir):
        super(MaskTransparencyWidget, self).__init__(parent)

        self.mask_dir = mask_dir
        self.frameIndex = 0

        self.imgPaths = imgPaths
        self.fov_id_list = fov_id_list
        self.fovIndex = 0
        self.fov_id = self.fov_id_list[self.fovIndex]

        self.imgIndex = 0
        self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1]

        # TO DO: check if re-annotated mask exists in training_dir, and present that instead of original mask
        #        make indicator appear if we're re-editing the mask again.
        experiment_name = params['experiment_name']
        original_file_name = self.maskImgPath
        pat = re.compile(
            r'.+(xy\d{3,4})_(p\d{3,4})_.+')  # supports 3- or 4-digit naming
        mat = pat.match(original_file_name)
        fovID = mat.groups()[0]
        peakID = mat.groups()[1]
        fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID,
                                                     peakID,
                                                     self.frameIndex + 1)
        savePath = os.path.join(self.mask_dir, fileBaseName)

        self.maskStack = io.imread(self.maskImgPath)
        if os.path.isfile(savePath):
            print(
                'Re-annotated mask exists in training directory. Loading it.')
            # add widget to express whether this mask is one you already re-annotated
            # print(self.frameIndex)
            self.maskStack[self.frameIndex, :, :] = io.imread(savePath)
            overwriteSegFile = True
        else:
            overwriteSegFile = False

        img = self.maskStack[self.frameIndex, :, :]
        img[img > 0] = 255
        self.RGBImg = color.gray2rgb(img).astype('uint8')
        self.RGBImg[:, :,
                    1:] = 0  # set GB channels to 0 to make the transarency mask red
        alphaFloat = 0.15
        alphaArray = np.zeros(img.shape, dtype='uint8')
        alphaArray = np.expand_dims(alphaArray, -1)
        self.alpha = int(255 * alphaFloat)
        alphaArray[...] = self.alpha
        self.RGBAImg = np.append(self.RGBImg, alphaArray, axis=-1)

        self.originalHeight, self.originalWidth, self.originalChannelNumber = self.RGBAImg.shape
        self.maskQimage = QImage(self.RGBAImg, self.originalWidth,
                                 self.originalHeight, self.RGBAImg.strides[0],
                                 QImage.Format_RGBA8888).scaled(
                                     1024,
                                     1024,
                                     aspectRatioMode=Qt.KeepAspectRatio)
        self.maskQpixmap = QPixmap(self.maskQimage)

        self.label = QLabel(self)
        self.label.setPixmap(self.maskQpixmap)

        self.drawing = False
        self.brushSize = 2
        self.brushColor = QColor(0, 0, 0, self.alpha)
        self.lastPoint = QPoint()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drawing = True
            self.lastPoint = event.pos()

    def mouseMoveEvent(self, event):
        if (event.buttons() & Qt.LeftButton) & self.drawing:

            # make the mouse position the center of a circle whose radius is defined as self.brushSize
            rr, cc = draw.circle(event.y(), event.x(), self.brushSize)
            for pix in zip(rr, cc):
                rowIndex = pix[0]
                colIndex = pix[1]
                self.maskQimage.setPixel(colIndex, rowIndex,
                                         self.brushColor.rgba())

            self.maskQpixmap = QPixmap(self.maskQimage)
            self.label.setPixmap(self.maskQpixmap)
            self.lastPoint = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button == Qt.LeftButton:
            self.drawing = False

    def save(self):
        filePath, _ = QFileDialog.getSaveFileName(
            self, "Save Image", "",
            "PNG(*.png);;JPEG(*.jpg *.jpeg);;TIFF(*.tif *.tiff);;ALL FILES(*.*)"
        )
        if filePath == "":
            return
        saveImg = self.maskQimage.convertToFormat(
            QImage.Format_Grayscale8).scaled(self.originalWidth,
                                             self.originalHeight)
        qimgHeight = saveImg.height()
        qimgWidth = saveImg.width()

        for rowIndex in range(qimgHeight):

            for colIndex in range(qimgWidth):
                pixVal = qGray(saveImg.pixel(colIndex, rowIndex))
                if pixVal > 0:
                    saveImg.setPixelColor(colIndex, rowIndex, QColor(1, 1, 1))
                    pixVal = qGray(saveImg.pixel(colIndex, rowIndex))

        saveImg.save(filePath)

    def buttonSave(self):
        experiment_name = params['experiment_name']
        original_file_name = self.maskImgPath
        pat = re.compile(
            r'.+(xy\d{3,4})_(p\d{3,4})_.+')  # supports 3- or 4-digit naming
        mat = pat.match(original_file_name)
        fovID = mat.groups()[0]
        peakID = mat.groups()[1]
        fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID,
                                                     peakID,
                                                     self.frameIndex + 1)
        savePath = os.path.join(self.mask_dir, fileBaseName)
        # labelSavePath = os.path.join(params['seg_dir'],fileBaseName)
        print("Saved binary mask image as: ", savePath)

        if not os.path.isdir(self.mask_dir):
            os.makedirs(self.mask_dir)

        # saveImg = self.maskQimage.convertToFormat(QImage.Format_Grayscale8)

        # This was bugging out and making the image not the same size as it started
        # saveImg = self.maskQimage.convertToFormat(QImage.Format_Grayscale8).scaled(self.originalWidth,self.originalHeight,aspectRatioMode=Qt.KeepAspectRatio)

        saveImg = self.maskQimage.convertToFormat(
            QImage.Format_Grayscale8).scaled(self.originalWidth,
                                             self.originalHeight)

        qimgHeight = saveImg.height()
        qimgWidth = saveImg.width()

        print(self.originalHeight, self.originalWidth, qimgHeight, qimgWidth)

        saveArr = np.zeros((qimgHeight, qimgWidth), dtype='uint8')
        for rowIndex in range(qimgHeight):

            for colIndex in range(qimgWidth):
                pixVal = qGray(saveImg.pixel(colIndex, rowIndex))
                if pixVal > 0:
                    saveArr[rowIndex, colIndex] = 1

        io.imsave(savePath, saveArr)
        # labelArr = measure.label(saveArr, connectivity=1)
        # labelArr = labelArr.astype('uint8')

        # print(labelSavePath)
        # io.imsave(labelSavePath,labelArr)

    def reset(self):
        self.maskQimage = QImage(self.RGBAImg, self.originalWidth,
                                 self.originalHeight, self.RGBAImg.strides[0],
                                 QImage.Format_RGBA8888).scaled(
                                     1024,
                                     1024,
                                     aspectRatioMode=Qt.KeepAspectRatio)
        self.maskQpixmap = QPixmap(self.maskQimage)
        self.label.setPixmap(self.maskQpixmap)
        self.update()

    def clear(self):
        self.imgFill = QColor(0, 0, 0, self.alpha)
        self.maskQimage = QImage(self.RGBAImg, self.originalWidth,
                                 self.originalHeight, self.RGBAImg.strides[0],
                                 QImage.Format_RGBA8888).scaled(
                                     1024,
                                     1024,
                                     aspectRatioMode=Qt.KeepAspectRatio)
        self.maskQimage.fill(self.imgFill)
        self.maskQpixmap = QPixmap(self.maskQimage)
        self.label.setPixmap(self.maskQpixmap)
        self.update()

    def onePx(self):
        self.brushSize = 1

    def threePx(self):
        self.brushSize = 3

    def fivePx(self):
        self.brushSize = 5

    def sevenPx(self):
        self.brushSize = 7

    def ninePx(self):
        self.brushSize = 9

    def blackColor(self):
        self.brushColor = QColor(0, 0, 0, self.alpha)

    def redColor(self):
        self.brushColor = QColor(255, 0, 0, self.alpha)

    def whiteColor(self):
        self.brushColor = QColor(255, 255, 255, self.alpha)

    # def setFOVPeakFrameIndex(self,frame_index,peak_index,fov_id):
    #     self.frameIndex = frame_index
    #     self.fov_id = fov_id
    #     self.imgIndex = peak_id

    def setImg(self, img):
        img[img > 0] = 255
        self.RGBImg = color.gray2rgb(img).astype('uint8')
        self.RGBImg[:, :,
                    1:] = 0  # set green and blue channels to 0 to make the transarency mask red
        alphaFloat = 0.25
        alphaArray = np.zeros(img.shape, dtype='uint8')
        alphaArray = np.expand_dims(alphaArray, -1)
        self.alpha = int(255 * alphaFloat)
        alphaArray[...] = self.alpha
        self.RGBAImg = np.append(self.RGBImg, alphaArray, axis=-1)

        self.originalHeight, self.originalWidth, self.originalChannelNumber = self.RGBAImg.shape
        self.maskQimage = QImage(self.RGBAImg, self.originalWidth,
                                 self.originalHeight, self.RGBAImg.strides[0],
                                 QImage.Format_RGBA8888).scaled(
                                     1024,
                                     1024,
                                     aspectRatioMode=Qt.KeepAspectRatio)
        self.maskQpixmap = QPixmap(self.maskQimage)
        self.label.setPixmap(self.maskQpixmap)

    def next_frame(self):
        self.frameIndex += 1
        try:
            experiment_name = params['experiment_name']
            original_file_name = self.maskImgPath
            pat = re.compile(r'.+(xy\d{3,4})_(p\d{3,4})_.+'
                             )  # supports 3- or 4-digit naming
            mat = pat.match(original_file_name)
            fovID = mat.groups()[0]
            peakID = mat.groups()[1]
            fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(
                experiment_name, fovID, peakID, self.frameIndex + 1)
            savePath = os.path.join(self.mask_dir, fileBaseName)

            if os.path.isfile(savePath):
                print(
                    'Re-annotated mask exists in training directory. Loading it.'
                )
                # add widget to express whether this mask is one you already re-annotated
                self.maskStack[self.frameIndex, :, :] = io.imread(savePath)
            img = self.maskStack[self.frameIndex, :, :]
        except IndexError:
            sys.exit(
                "You've already edited the last frame's mask. Write in functionality to increment to next peak_id now!"
            )

        self.setImg(img)

    def prior_frame(self):
        self.frameIndex -= 1
        try:
            experiment_name = params['experiment_name']
            original_file_name = self.maskImgPath
            pat = re.compile(r'.+(xy\d{3,4})_(p\d{3,4})_.+'
                             )  # supports 3- or 4-digit naming
            mat = pat.match(original_file_name)
            fovID = mat.groups()[0]
            peakID = mat.groups()[1]
            fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(
                experiment_name, fovID, peakID, self.frameIndex + 1)
            savePath = os.path.join(self.mask_dir, fileBaseName)

            if os.path.isfile(savePath):
                print(
                    'Re-annotated mask exists in training directory. Loading it.'
                )
                # add widget to express whether this mask is one you already re-annotated
                self.maskStack[self.frameIndex, :, :] = io.imread(savePath)
            img = self.maskStack[self.frameIndex, :, :]
        except IndexError:
            sys.exit(
                "You've already edited the last frame's mask. Write in functionality to increment to next peak_id now!"
            )
        self.setImg(img)

    def next_peak(self):
        self.imgIndex += 1
        self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1]
        self.maskStack = io.imread(self.maskImgPath)

        self.frameIndex = 0

        experiment_name = params['experiment_name']
        original_file_name = self.maskImgPath
        pat = re.compile(
            r'.+(xy\d{3,4})_(p\d{3,4})_.+')  # supports 3- or 4-digit naming
        mat = pat.match(original_file_name)
        fovID = mat.groups()[0]
        peakID = mat.groups()[1]
        fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID,
                                                     peakID,
                                                     self.frameIndex + 1)
        savePath = os.path.join(self.mask_dir, fileBaseName)

        if os.path.isfile(savePath):
            print(
                'Re-annotated mask exists in training directory. Loading it.')
            # add widget to express whether this mask is one you already re-annotated
            self.maskStack[self.frameIndex, :, :] = io.imread(savePath)

        img = self.maskStack[self.frameIndex, :, :]
        self.setImg(img)

    def prior_peak(self):
        self.imgIndex -= 1
        self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1]
        self.maskStack = io.imread(self.maskImgPath)

        self.frameIndex = 0

        experiment_name = params['experiment_name']
        original_file_name = self.maskImgPath
        pat = re.compile(
            r'.+(xy\d{3,4})_(p\d{3,4})_.+')  # supports 3- or 4-digit naming
        mat = pat.match(original_file_name)
        fovID = mat.groups()[0]
        peakID = mat.groups()[1]
        fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID,
                                                     peakID,
                                                     self.frameIndex + 1)
        savePath = os.path.join(self.mask_dir, fileBaseName)

        if os.path.isfile(savePath):
            print(
                'Re-annotated mask exists in training directory. Loading it.')
            # add widget to express whether this mask is one you already re-annotated
            self.maskStack[self.frameIndex, :, :] = io.imread(savePath)
        img = self.maskStack[self.frameIndex, :, :]
        self.setImg(img)

    def next_fov(self):
        self.fovIndex += 1
        self.fov_id = self.fov_id_list[self.fovIndex]

        self.imgIndex = 0
        self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1]
        self.maskStack = io.imread(self.maskImgPath)

        self.frameIndex = 0

        experiment_name = params['experiment_name']
        original_file_name = self.maskImgPath
        pat = re.compile(
            r'.+(xy\d{3,4})_(p\d{3,4})_.+')  # supports 3- or 4-digit naming
        mat = pat.match(original_file_name)
        fovID = mat.groups()[0]
        peakID = mat.groups()[1]
        fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID,
                                                     peakID,
                                                     self.frameIndex + 1)
        savePath = os.path.join(self.mask_dir, fileBaseName)

        if os.path.isfile(savePath):
            print(
                'Re-annotated mask exists in training directory. Loading it.')
            # add widget to express whether this mask is one you already re-annotated
            self.maskStack[self.frameIndex, :, :] = io.imread(savePath)
        img = self.maskStack[self.frameIndex, :, :]
        self.setImg(img)

    def prior_fov(self):
        self.fovIndex -= 1
        self.fov_id = self.fov_id_list[self.fovIndex]

        self.imgIndex = 0
        self.maskImgPath = self.imgPaths[self.fov_id][self.imgIndex][1]
        self.maskStack = io.imread(self.maskImgPath)

        self.frameIndex = 0
        experiment_name = params['experiment_name']
        original_file_name = self.maskImgPath
        pat = re.compile(
            r'.+(xy\d{3,4})_(p\d{3,4})_.+')  # supports 3- or 4-digit naming
        mat = pat.match(original_file_name)
        fovID = mat.groups()[0]
        peakID = mat.groups()[1]
        fileBaseName = '{}_{}_{}_t{:0=4}.tif'.format(experiment_name, fovID,
                                                     peakID,
                                                     self.frameIndex + 1)
        savePath = os.path.join(self.mask_dir, fileBaseName)

        if os.path.isfile(savePath):
            print(
                'Re-annotated mask exists in training directory. Loading it.')
            # add widget to express whether this mask is one you already re-annotated
            self.maskStack[self.frameIndex, :, :] = io.imread(savePath)
        img = self.maskStack[self.frameIndex, :, :]
        self.setImg(img)