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
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
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
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)))
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)