def openTestProject(name): orgPath = os.path.join(os.path.dirname(__file__), "data", "projects", name) destPath = tempFolderInTempFolder() copy_tree(orgPath, destPath) projectFile = os.path.join(destPath, name + ".qgs") if projectFile != QgsProject.instance().fileName(): iface.addProject(projectFile)
def createAppFromTestAppdef(appdefName, preview=True, aboutContent=None): appdef = testAppdef(appdefName, True, aboutContent) if preview: folder = tempFolderInTempFolder("webappbuilder") else: folder = os.environ["WEB_APP_OUTPUT_FOLDER"] appFolder = os.path.join(folder, "webapp") if os.path.exists(appFolder): shutil.rmtree(appFolder) writeWebApp(appdef, folder, preview, SilentProgress()) return folder
def saveTiles(self, _extent): folder = tempFolderInTempFolder() layer = self.layer() if _extent.intersects(layer.extent()): extent = _extent.intersect(layer.extent()) xSize = extent.width() / layer.rasterUnitsPerPixelX() ySize = extent.height() / layer.rasterUnitsPerPixelY() xTiles = math.ceil(xSize / self.TILESIZE) yTiles = math.ceil(ySize / self.TILESIZE) i = 0 startProgressBar( "Retrieving and preparing data [layer %s]" % self.name(), xTiles * yTiles) for x in xrange(xTiles): for y in xrange(yTiles): minX = extent.xMinimum( ) + x * layer.rasterUnitsPerPixelX() * self.TILESIZE maxX = min( extent.xMaximum(), extent.xMinimum() + (x + 1) * layer.rasterUnitsPerPixelX() * self.TILESIZE) minY = extent.yMinimum( ) + y * layer.rasterUnitsPerPixelY() * self.TILESIZE maxY = min( extent.yMaximum(), extent.yMinimum() + (y + 1) * layer.rasterUnitsPerPixelY() * self.TILESIZE) pt1 = QgsPoint(minX, minY) pt2 = QgsPoint(maxX, maxY) tileExtent = QgsRectangle(pt1, pt2) filename = os.path.join(folder, "%i_%i.tif" % (x, y)) self._save(filename, tileExtent) i += 1 setProgressValue(i) closeProgressBar() return folder
def preview(self): try: appdef = self.createAppDefinition() except WrongValueException: return problems = checkAppCanBeCreated(appdef, True) if problems: dlg = AppDefProblemsDialog(problems) dlg.exec_() if not dlg.ok: return try: self.currentFolder = tempFolderInTempFolder("webappbuilder") pub.subscribe(self.endCreatePreviewListener, utils.topics.endFunction) try: self._run(lambda: createApp(appdef, self.currentFolder, True, self.progress)) except: QgsMessageLog.logMessage(traceback.format_exc(), level=QgsMessageLog.CRITICAL) self.endCreatePreviewListener(False, traceback.format_exc()) except WrongValueException: pass
def _createMosaic(self): mosaicFunction = mosaicFunctions[self.comboMosaicType.currentIndex()] def getValue(textbox, paramName): try: v = float(textbox.text()) return v except: iface.messageBar().pushMessage( "", "Wrong value for parameter %s: %s" % (paramName, textbox.text()), level=QgsMessageBar.WARNING) raise try: widgets = [ self.textXMin, self.textXMax, self.textYMin, self.textYMax ] names = ["X min", "X max", "Y min", "Y max"] xmin, xmax, ymin, ymax = [ getValue(w, n) for w, n in zip(widgets, names) ] except: return extent = QgsRectangle(QgsPoint(xmin, ymin), QgsPoint(xmax, ymax)) txt = self.comboCoverage.currentText() if not txt: iface.messageBar().pushMessage("", "No coverage selected", level=QgsMessageBar.WARNING) return name, coverageName = txt.split(" : ") loadedLayers = self._loadedLayersForCoverage(name, coverageName) minDays = self.sliderStartDate.value() maxDays = self.sliderEndDate.value() validLayers = [] for layer in loadedLayers: time = daysFromDate(parser.parse(layer.time())) if (time >= minDays and time <= maxDays): validLayers.append(layer) bandNames = layers._coverages[name][coverageName].bands if validLayers: newBands = [] tilesFolders = [] dstFolder = tempFolderInTempFolder() '''We download the layers so we can access them locally''' lay = validLayers[0] xSize = extent.width() / lay.layer().rasterUnitsPerPixelX() ySize = extent.height() / lay.layer().rasterUnitsPerPixelY() xTiles = math.ceil(xSize / lay.TILESIZE) yTiles = math.ceil(ySize / lay.TILESIZE) logger.info( "Downloading datacube layers to local files. Extent:%sx%s. Tiles count: %sx%s" % (extent.width(), extent.height(), xTiles, yTiles)) for i, lay in enumerate(validLayers): start = timelib.time() tilesFolders.append(lay.saveTiles(extent)) end = timelib.time() logger.info("Layer %s downloaded in %s seconds." % (str(i), str(end - start))) try: qaBand = bandNames.index("pixel_qa") except: qaBand = None tileFiles = os.listdir(tilesFolders[0]) if not tileFiles: iface.messageBar().pushMessage( "", "No available data within the selected extent.", level=QgsMessageBar.WARNING) return startProgressBar("Processing mosaic data", len(tileFiles)) '''Now we process all tiles separately''' for i, filename in enumerate(tileFiles): tilestart = timelib.time() setProgressValue(i) start = timelib.time() newBands = {} files = [ os.path.join(folder, filename) for folder in tilesFolders ] if qaBand is not None: qaData = [getArray(f, qaBand + 1) for f in files] else: qaData = None end = timelib.time() logger.info("QA band prepared in %s seconds" % (str(end - start))) if mosaicFunction.bandByBand: ''' We operate band by band, since a given band in the the final result layer depends only on the values of that band in the input layers, not the value of other bands''' start = timelib.time() for band, bandName in enumerate(bandNames): if band == qaBand: newBands[bandName] = mosaicFunction.computeQAMask( qaData) else: bandData = [getArray(f, band + 1) for f in files] newBands[bandName] = mosaicFunction.compute( bandData, qaData) bandData = None end = timelib.time() logger.info("Tile %s read and processed in %s seconds." % (str(i), str(end - start))) else: ''' We operate with all bands at once, and the output layer will have only each band computed from the set of them in the input layers''' bandData = [] bandNamesArray = [] start = timelib.time() for i, band in enumerate(bandNames): if i != qaBand: bandData.append( [getArray(f, i + 1) for f in files]) bandNamesArray.append(band) end = timelib.time() logger.info( "Tile %s data read and prepared in %s seconds." % (str(i), str(end - start))) start = timelib.time() newBandsArray = mosaicFunction.compute(bandData, qaData) end = timelib.time() logger.info("Tile %s data processed in %s seconds." % (str(i), str(end - start))) newBands = { k: v for k, v in zip(bandNamesArray, newBandsArray) } if qaBand is not None: start = timelib.time() newBands[bandNames[ qaBand]] = mosaicFunction.computeQAMask(qaData) end = timelib.time() logger.info("QA band prepared in %s seconds" % (str(end - start))) bandData = None start = timelib.time() '''We write the set of bands as a new layer. That will be an output tile''' templateFilename = os.path.join(tilesFolders[0], filename) ds = gdal.Open(templateFilename, GA_ReadOnly) bandCount = ds.RasterCount datatype = ds.GetRasterBand(1).DataType width = ds.RasterXSize height = ds.RasterYSize geotransform = ds.GetGeoTransform() projection = ds.GetProjection() del ds driver = gdal.GetDriverByName("GTiff") dstFilename = os.path.join(dstFolder, filename) dstDs = driver.Create(dstFilename, width, height, bandCount, datatype) for b, band in enumerate(bandNames): gdalBand = dstDs.GetRasterBand(b + 1) gdalBand.SetNoDataValue(NO_DATA) gdalBand.WriteArray(newBands[band]) gdalBand.FlushCache() del newBands dstDs.SetGeoTransform(geotransform) dstDs.SetProjection(projection) del dstDs end = timelib.time() logger.info("Tile %s written to local file in %s seconds." % (str(i), str(end - start))) tileend = timelib.time() logger.info("Total time to process tile: %s seconds." % (str(tileend - tilestart))) '''With all the tiles, we create a virtual raster''' toMerge = ";".join([os.path.join(dstFolder, f) for f in tileFiles]) outputFile = os.path.join(dstFolder, "mosaic.vrt") processing.runalg("gdalogr:buildvirtualraster", { "INPUT": toMerge, "SEPARATE": False, "OUTPUT": outputFile }) layer = QgsRasterLayer(outputFile, "Mosaic [%s]" % mosaicFunction.name, "gdal") layers._mosaicLayers[validLayers[0].datasetName()][ validLayers[0].coverageName()].append(outputFile) addLayerIntoGroup(layer, validLayers[0].datasetName(), validLayers[0].coverageName(), bandNames) closeProgressBar() iface.messageBar().pushMessage( "", "Mosaic has been correctly created and added to project.", level=QgsMessageBar.INFO) else: iface.messageBar().pushMessage( "", "No layers available from the selected coverage.", level=QgsMessageBar.WARNING)