Example #1
0
    def btn_calculate(self):
        # Note that the super class has several tests in it - if they fail it
        # returns False, which would mean this function should stop execution
        # as well.
        ret = super(DlgCalculateTCSummaryTable, self).btn_calculate()
        if not ret:
            return

        ######################################################################
        # Check that all needed input layers are selected
        if len(self.combo_layer_f_loss.layer_list) == 0:
            QtWidgets.QMessageBox.critical(None, self.tr("Error"),
                                       self.tr("You must add a forest loss layer to your map before you can use the carbon change summary tool."))
            return
        if len(self.combo_layer_tc.layer_list) == 0:
            QtWidgets.QMessageBox.critical(None, self.tr("Error"),
                                       self.tr("You must add a total carbon layer to your map before you can use the carbon change summary tool."))
            return
        #######################################################################
        # Check that the layers cover the full extent needed
        if self.aoi.calc_frac_overlap(QgsGeometry.fromRect(self.combo_layer_f_loss.get_layer().extent())) < .99:
            QtWidgets.QMessageBox.critical(None, self.tr("Error"),
                                       self.tr("Area of interest is not entirely within the forest loss layer."))
            return
        if self.aoi.calc_frac_overlap(QgsGeometry.fromRect(self.combo_layer_tc.get_layer().extent())) < .99:
            QtWidgets.QMessageBox.critical(None, self.tr("Error"),
                                       self.tr("Area of interest is not entirely within the total carbon layer."))
            return

        #######################################################################
        # Check that all of the productivity layers have the same resolution 
        # and CRS
        def res(layer):
            return (round(layer.rasterUnitsPerPixelX(), 10), round(layer.rasterUnitsPerPixelY(), 10))

        if res(self.combo_layer_f_loss.get_layer()) != res(self.combo_layer_tc.get_layer()):
            QtWidgets.QMessageBox.critical(None, self.tr("Error"),
                                       self.tr("Resolutions of forest loss and total carbon layers do not match."))
            return

        self.close()

        # Load all datasets to VRTs (to select only the needed bands)
        f_loss_vrt = self.combo_layer_f_loss.get_vrt()
        tc_vrt = self.combo_layer_tc.get_vrt()

        # Figure out start and end dates
        year_start = self.combo_layer_f_loss.get_band_info()['metadata']['year_start']
        year_end = self.combo_layer_f_loss.get_band_info()['metadata']['year_end']

        summary_task = SummaryTask(self.aoi, year_start, year_end, 
                f_loss_vrt, tc_vrt, self.output_tab.output_basename.text() + '.xlsx')
        log("Adding task to task manager")
        QgsApplication.taskManager().addTask(summary_task)
        if summary_task.status() not in [QgsTask.Complete, QgsTask.Terminated]:
            QCoreApplication.processEvents()
        # while QgsApplication.taskManager().countActiveTasks() > 0:
        #         QCoreApplication.processEvents()

        return True
Example #2
0
def login(email=None, password=None):
    if (email == None):
        email = get_user_email()
    if (password == None):
        password = QtCore.QSettings().value("LDMP/password", None)
    if not email or not password:
        log('API unable to login - check username/password')
        QtGui.QMessageBox.critical(
            None, QtGui.QApplication.translate("LDMP", "Error"),
            QtGui.QApplication.translate(
                "LDMP",
                "Unable to login to LDMP server. Check your username and password."
            ))
        resp = None

    resp = call_api('/auth',
                    method='post',
                    payload={
                        "email": email,
                        "password": password
                    })

    if resp != None:
        QtCore.QSettings().setValue("LDMP/email", email)
        QtCore.QSettings().setValue("LDMP/password", password)

    return resp
Example #3
0
 def start(self):
     try:
         worker = RequestWorker(self.url, self.method, self.payload,
                                self.headers)
         pause = QEventLoop()
         worker.finished.connect(pause.quit)
         worker.successfully_finished.connect(self.save_resp)
         worker.error.connect(self.save_exception)
         start_worker(
             worker, iface,
             tr_api.tr(u'Contacting {} server...'.format(self.server_name)))
         pause.exec_()
         if self.get_exception():
             raise self.get_exception()
     except requests.exceptions.ConnectionError:
         log('API unable to access server - check internet connection')
         QMessageBox.critical(
             None, tr_api.tr("Error"),
             tr_api.
             tr(u"Unable to login to {} server. Check your internet connection."
                .format(self.server_name)))
         resp = None
     except requests.exceptions.Timeout:
         log('API unable to login - general error')
         QMessageBox.critical(
             None, tr_api.tr("Error"),
             tr_api.tr(u"Unable to connect to {} server.".format(
                 self.server_name)))
         resp = None
Example #4
0
 def ok_clicked(self):
     self.close()
     rows = []
     for i in self.layers_view.selectionModel().selectedRows():
         rows.append(i.row())
     if len(rows) > 0:
         results = get_results(self.file_lineedit.text())
         if results:
             for row in rows:
                 if results.get('local_format', None) == 'tif':
                     f = os.path.splitext(
                         self.file_lineedit.text())[0] + '.tif'
                 elif results.get('local_format', None) == 'vrt':
                     f = os.path.splitext(
                         self.file_lineedit.text())[0] + '.vrt'
                 else:
                     raise Vband_infosalueError(
                         "Unrecognized local file format in download results: {}"
                         .format(results.get('local_format', None)))
                 resp = add_layer(f, results['bands'][row])
                 if not resp:
                     mb.pushMessage(
                         tr("Error"),
                         self.
                         tr('Unable to automatically add "{}". No style is defined for this type of layer.'
                            .format(results['bands'][row]['name'])),
                         level=1,
                         duration=5)
         else:
             log('Error loading "{}" results from {}'.format(
                 layer, self.file_lineedit.text()))
     else:
         QtGui.QMessageBox.critical(None, self.tr("Error"),
                                    self.tr("Select a layer to load."))
Example #5
0
    def update_from_geojson(self,
                            geojson,
                            crs_src='epsg:4326',
                            datatype='polygon',
                            wrap=False):
        log('Setting up AOI with geojson. Wrap is {}.'.format(wrap))
        self.datatype = datatype
        # Note geojson is assumed to be in 4326
        l = QgsVectorLayer(
            "{datatype}?crs={crs}".format(datatype=self.datatype, crs=crs_src),
            "calculation boundary", "memory")
        fields = QgsJsonUtils.stringToFields(json.dumps(geojson),
                                             QTextCodec.codecForName('UTF8'))
        features = QgsJsonUtils.stringToFeatureList(
            json.dumps(geojson), fields, QTextCodec.codecForName('UTF8'))
        l.dataProvider().addFeatures(features)
        l.commitChanges()
        if not l.isValid():
            QtWidgets.QMessageBox.critical(
                None, tr("Error"),
                tr("Failed to add geojson to temporary layer."))
            log("Failed to add geojson to temporary layer.")
            return

        self.l = transform_layer(l,
                                 self.crs_dst,
                                 datatype=self.datatype,
                                 wrap=wrap)
Example #6
0
def extract_zipfile(file, verify=True):
    filename = os.path.join(os.path.dirname(__file__), 'data', file)
    url = u'https://s3.amazonaws.com/trends.earth/sharing/{}'.format(file)

    if os.path.exists(filename) and verify:
        if not check_hash_against_etag(url, filename):
            os.remove(filename)

    if not os.path.exists(filename):
        log(u'Downloading {}'.format(file))
        # TODO: Dialog box with two options:
        #   1) Download
        #   2) Load from local folder
        worker = Download(url, filename)
        worker.start()
        resp = worker.get_resp()
        if not resp:
            return None
        if not check_hash_against_etag(url, filename):
            return None

    try:
        with zipfile.ZipFile(filename, 'r') as fin:
            fin.extractall(os.path.join(os.path.dirname(__file__), 'data'))
        return True
    except zipfile.BadZipfile:
        os.remove(filename)
        return False
Example #7
0
def read_json(file, verify=True):
    filename = os.path.join(os.path.dirname(__file__), 'data', file)
    url = u'https://s3.amazonaws.com/trends.earth/sharing/{}'.format(file)

    if os.path.exists(filename) and verify:
        if not check_hash_against_etag(url, filename):
            os.remove(filename)

    if not os.path.exists(filename):
        log(u'Downloading {}'.format(file))
        # TODO: Dialog box with two options:
        #   1) Download
        #   2) Load from local folder
        worker = Download(url, filename)
        worker.start()
        resp = worker.get_resp()
        if not resp:
            return None
        if not check_hash_against_etag(url, filename):
            return None

    with gzip.GzipFile(filename, 'r') as fin:
        json_bytes = fin.read()
        json_str = json_bytes.decode('utf-8')

    return json.loads(json_str)
Example #8
0
 def start(self):
     try:
         worker = RequestWorker(self.url, self.method, self.payload,
                                self.headers)
         pause = QtCore.QEventLoop()
         worker.finished.connect(pause.quit)
         worker.successfully_finished.connect(self.save_resp)
         worker.error.connect(self.save_exception)
         start_worker(
             worker, iface,
             QtGui.QApplication.translate("LDMP",
                                          'Contacting LDMP server...'))
         pause.exec_()
         if self.get_exception():
             raise self.get_exception()
     except requests.exceptions.ConnectionError:
         log('API unable to access server - check internet connection')
         QtGui.QMessageBox.critical(
             None, QtGui.QApplication.translate("LDMP", "Error"),
             QtGui.QApplication.translate(
                 "LDMP",
                 "Unable to login to LDMP server. Check your internet connection."
             ))
         resp = None
     except requests.exceptions.Timeout:
         log('API unable to login - general error')
         QtGui.QMessageBox.critical(
             None, QtGui.QApplication.translate("LDMP", "Error"),
             QtGui.QApplication.translate(
                 "LDMP", "Unable to connect to LDMP server."))
         resp = None
Example #9
0
def get_execution(id=None, date=None):
    log('Fetching executions')
    query = []
    if id:
        query.append('user_id={}'.format(quote_plus(id)))
    if date:
        query.append('updated_at={}'.format(date))
    if len(query) > 0:
        query = "?" + "&".join(query)
    else:
        query = ''

    resp = call_api('/api/v1/execution{}'.format(query), method='get', use_token=True)
    if not resp:
        return None
    else:
        data = resp['data']
        # Sort responses in descending order using start time by default
        data = sorted(data, key=lambda job: job['start_date'], reverse=True)
        # Convert start/end dates into datatime objects in local time zone
        for job in data:
            start_date = datetime.strptime(job['start_date'], '%Y-%m-%dT%H:%M:%S.%f')
            start_date = start_date.replace(tzinfo=tz.tzutc())
            start_date = start_date.astimezone(tz.tzlocal())
            job['start_date'] = start_date
            end_date = datetime.strptime(job['end_date'], '%Y-%m-%dT%H:%M:%S.%f')
            end_date = end_date.replace(tzinfo=tz.tzutc())
            end_date = end_date.astimezone(tz.tzlocal())
            job['end_date'] = end_date
        return data
Example #10
0
def extract_zipfile(f, verify=True):
    filename = os.path.join(os.path.dirname(__file__), 'data', f)
    url = u'https://s3.amazonaws.com/trends.earth/sharing/{}'.format(f)

    if os.path.exists(filename) and verify:
        if not check_hash_against_etag(url, filename):
            os.remove(filename)

    if not os.path.exists(filename):
        log(u'Downloading {}'.format(f))
        # TODO: Dialog box with two options:
        #   1) Download
        #   2) Load from local folder
        worker = Download(url, filename)
        try:
            worker.start()
        except PermissionError:
            QtWidgets.QMessageBox.critical(None,
                                       tr_download.tr("Error"),
                                       tr_download.tr("Unable to write to {}.".format(filename)))
            return None
        resp = worker.get_resp()
        if not resp:
            return None
        if not check_hash_against_etag(url, filename):
            return None

    try:
        with zipfile.ZipFile(filename, 'r') as fin:
            fin.extractall(os.path.join(os.path.dirname(__file__), 'data'))
        return True
    except zipfile.BadZipfile:
        os.remove(filename)
        return False
Example #11
0
def get_sample(f, band_number, n=1e6):
    '''Get a gridded sample of a raster dataset'''
    ds = gdal.Open(f)
    b = ds.GetRasterBand(band_number)

    xsize = b.XSize
    ysize = b.YSize

    # Select grid size from shortest side to ensure we have enough samples
    if xsize > ysize:
        edge = ysize
    else:
        edge = xsize
    grid_size = np.ceil(edge / np.sqrt(n))
    if (n > xsize * ysize) or ((grid_size * grid_size) > (xsize * ysize)):
        # Don't sample if the sample would be larger than the array itself
        return b.ReadAsArray().astype(np.float)
    else:
        rows = np.arange(0, ysize, grid_size)
        cols = np.arange(0, xsize, grid_size).astype('int64')

        out = np.zeros((rows.shape[0], cols.shape[0]), np.float64)
        log("Sampling from a ({}, {}) array to a {} array (grid size: {}, samples: {})".format(ysize, xsize, out.shape, grid_size, out.shape[0] * out.shape[1]))

        for n in range(rows.shape[0]):
            out[n, :] = b.ReadAsArray(0, int(rows[n]), xsize, 1)[:, cols]

        return out
Example #12
0
def style_land_cover_land_deg(outfile):
    layer_deg = iface.addRasterLayer(
        outfile,
        QtGui.QApplication.translate('LDMPPlugin', 'Land cover (degradation)'))
    if not layer_deg.isValid():
        log('Failed to add layer')
        return None
    fcn = QgsColorRampShader()
    fcn.setColorRampType(QgsColorRampShader.EXACT)
    #TODO The GPG doesn't seem to allow for possibility of improvement...?
    lst = [
        QgsColorRampShader.ColorRampItem(
            -1, QtGui.QColor(153, 51, 4),
            QtGui.QApplication.translate('LDMPPlugin', 'Degradation')),
        QgsColorRampShader.ColorRampItem(
            0, QtGui.QColor(246, 246, 234),
            QtGui.QApplication.translate('LDMPPlugin', 'Stable')),
        QgsColorRampShader.ColorRampItem(
            1, QtGui.QColor(0, 140, 121),
            QtGui.QApplication.translate('LDMPPlugin', 'Improvement'))
    ]
    fcn.setColorRampItemList(lst)
    shader = QgsRasterShader()
    shader.setRasterShaderFunction(fcn)
    pseudoRenderer = QgsSingleBandPseudoColorRenderer(layer_deg.dataProvider(),
                                                      1, shader)
    layer_deg.setRenderer(pseudoRenderer)
    layer_deg.triggerRepaint()
    iface.legendInterface().refreshLayerSymbology(layer_deg)
Example #13
0
def login(email=None, password=None):
    if (email == None):
        email = get_user_email()
    if (password == None):
        password = QSettings().value("LDMP/password", None)
    if not email or not password:
        log('API unable to login - check username/password')
        QMessageBox.critical(
            None, tr_api.tr("Error"),
            tr_api.
            tr("Unable to login to Trends.Earth. Check your username and password."
               ))
        return None

    resp = call_api('/auth',
                    method='post',
                    payload={
                        "email": email,
                        "password": password
                    })

    if resp != None:
        QSettings().setValue("LDMP/email", email)
        QSettings().setValue("LDMP/password", password)

    return resp
Example #14
0
def read_class_file(f):
    if not os.access(f, os.R_OK):
        QtWidgets.QMessageBox.critical(
            None, QtWidgets.QApplication.translate("Error"),
            QtWidgets.QApplication.translate(u"Cannot read {}.".format(f),
                                             None))
        return None

    with open(f) as class_file:
        classes = json.load(class_file)
    if (not isinstance(classes, list) or not len(classes) > 0
            or not isinstance(classes[0], dict)
            or 'Initial_Code' not in classes[0]
            or 'Final_Code' not in classes[0]
            or 'Final_Label' not in classes[0]):

        QtWidgets.QMessageBox.critical(
            None,
            QtWidgets.QApplication.translate('DlgCalculateLCSetAggregation',
                                             "Error"),
            QtWidgets.QApplication.translate(
                'DlgCalculateLCSetAggregation',
                u"{} does not appear to contain a valid class definition.".
                format(f)))
        return None
    else:
        log(u'Loaded class definition from {}'.format(f))
        return classes
Example #15
0
    def calculate_timeseries(self, geojson, ndvi_dataset):
        if self.traj_climate.currentText() != "":
            climate_gee_dataset = self.climate_datasets[self.traj_climate.currentText()]['GEE Dataset']
            log('climate_gee_dataset {}'.format(climate_gee_dataset))
        else:
            climate_gee_dataset = None

        payload = {'year_start': self.traj_year_start.date().year(),
                   'year_end': self.traj_year_end.date().year(),
                   'geojson': json.dumps(geojson),
                   'ndvi_gee_dataset': ndvi_dataset,
                   'task_name': self.task_name.text(),
                   'climate_gee_dataset': climate_gee_dataset}
        # This will add in the method parameter
        payload.update(self.scripts['productivity-trajectory']['functions'][self.traj_indic.currentText()]['params'])

        gee_script = 'time-series' + '-' + self.scripts['time-series']['script version']

        resp = run_script(gee_script, payload)

        if resp:
            mb.pushMessage(self.tr("Submitted"),
                           self.tr("Time series calculation task submitted to Google Earth Engine."),
                           level=0, duration=5)
        else:
            mb.pushMessage(self.tr("Error"),
                           self.tr("Unable to submit time series calculation task to Google Earth Engine."),
                           level=1, duration=5)
Example #16
0
 def update_from_geojson(self,
                         geojson,
                         crs_src='epsg:4326',
                         datatype='polygon',
                         wrap=False):
     log('Setting up AOI with geojson. Wrap is {}.'.format(wrap))
     self.datatype = datatype
     # Note geojson is assumed to be in 4326
     l = QgsVectorLayer(
         "{datatype}?crs={crs}".format(datatype=self.datatype, crs=crs_src),
         "calculation boundary", "memory")
     ds = ogr.Open(json.dumps(geojson))
     layer_in = ds.GetLayer()
     feats_out = []
     for i in range(0, layer_in.GetFeatureCount()):
         feat_in = layer_in.GetFeature(i)
         feat = QgsFeature(l.fields())
         geom = QgsGeometry()
         geom.fromWkb(feat_in.geometry().ExportToWkb())
         feat.setGeometry(geom)
         feats_out.append(feat)
     l.dataProvider().addFeatures(feats_out)
     l.commitChanges()
     if not l.isValid():
         QtWidgets.QMessageBox.critical(
             None, tr("Error"),
             tr("Failed to add geojson to temporary layer."))
         log("Failed to add geojson to temporary layer.")
         return
     self.l = transform_layer(l,
                              self.crs_dst,
                              datatype=self.datatype,
                              wrap=wrap)
Example #17
0
def get_cutoff(f, band_number, band_info, percentiles):
    if len(percentiles) != 1 and len(percentiles) != 2:
        raise ValueError("Percentiles must have length 1 or 2. Percentiles that were passed: {}".format(percentiles))
    d = get_sample(f, band_number)
    md = np.ma.masked_where(d == band_info['no_data_value'], d)
    if md.size == 0:
        # If all of the values are no data, return 0
        log('All values are no data')
        return 0
    else:
        cutoffs = np.nanpercentile(md.compressed(), percentiles)
        if cutoffs.size == 2:
            max_cutoff = np.amax(np.absolute(cutoffs))
            if max_cutoff < 0:
                return 0
            else:
                return round_to_n(max_cutoff, 2)

        elif cutoffs.size == 1:
            if cutoffs < 0:
                # Negative cutoffs are not allowed as stretch is either zero 
                # centered or starting at zero
                return 0
            else:
                return round_to_n(cutoffs, 2)
        else:
            # We only get here if cutoffs is not size 1 or 2, which should 
            # never happen, so raise
            raise ValueError("Stretch calculation returned cutoffs array of size {} ({})".format(cutoffs.size, cutoffs))
Example #18
0
def read_json(f, verify=True):
    filename = os.path.join(os.path.dirname(__file__), 'data', f)
    url = u'https://s3.amazonaws.com/trends.earth/sharing/{}'.format(f)

    if os.path.exists(filename) and verify:
        if not check_hash_against_etag(url, filename):
            os.remove(filename)

    if not os.path.exists(filename):
        log(u'Downloading {}'.format(f))
        # TODO: Dialog box with two options:
        #   1) Download
        #   2) Load from local folder
        worker = Download(url, filename)
        try:
            worker.start()
        except PermissionError:
            QtWidgets.QMessageBox.critical(None,
                                       tr_download.tr("Error"),
                                       tr_download.tr("Unable to write to {}. Do you need administrator permissions?".format(filename)))
            return None
        resp = worker.get_resp()
        if not resp:
            return None
        if not check_hash_against_etag(url, filename):
            return None

    with gzip.GzipFile(filename, 'r') as fin:
        json_bytes = fin.read()
        json_str = json_bytes.decode('utf-8')

    return json.loads(json_str)
Example #19
0
 def point_chooser(self):
     log("Choosing point from canvas...")
     self.canvas.setMapTool(self.choose_point_tool)
     self.window().hide()
     QtWidgets.QMessageBox.critical(
         None, self.tr("Point chooser"),
         self.tr("Click the map to choose a point."))
Example #20
0
 def zoom(self):
     layer = None
     for lyr in QgsProject.instance().layerStore().mapLayers().values():
         if self.lyr_source in os.path.normpath(lyr.source()):
             layer = lyr
             break
     if not layer:
         raise LookupError('Unable to locate layer for extent for admin code {}'.format(self.admin_code))
     # Note that this layer will have the selected admin region filtered out, so 
     # that data will not be masked in this area. So need to temporarily remove 
     # this filter and then reapply it.
     subset_string = layer.subsetString()
     layer.setSubsetString('')
     feature = None
     for f in layer.getFeatures():
         if f.attribute(self.field) == self.admin_code:
             feature = f
             break
     if not feature:
         raise LookupError('Unable to locate polygon for admin code {}'.format(self.admin_code))
     # TODO: Need to reproject the geometry to match the canvas CRS
     self.canvas = iface.mapCanvas()
     # Reapply the original feature filter on this layer
     layer.setSubsetString(subset_string)
     self.bbox = feature.geometry().boundingBox()
     log('Bounding box for zoom is: {}'.format(self.bbox.toString()))
     self.canvas.setExtent(self.bbox)
     self.canvas.refresh()
Example #21
0
    def work(self):
        ds_in = gdal.Open(self.in_vrt)

        soc_band = ds_in.GetRasterBand(1)
        clim_band = ds_in.GetRasterBand(2)

        block_sizes = soc_band.GetBlockSize()
        x_block_size = block_sizes[0]
        y_block_size = block_sizes[1]
        xsize = soc_band.XSize
        ysize = soc_band.YSize

        driver = gdal.GetDriverByName("GTiff")
        # Need a band for SOC degradation, plus bands for annual SOC, and for
        # annual LC
        ds_out = driver.Create(self.out_f, xsize, ysize,
                               1 + len(self.lc_years) * 2, gdal.GDT_Int16,
                               ['COMPRESS=LZW'])
        src_gt = ds_in.GetGeoTransform()
        ds_out.SetGeoTransform(src_gt)
        out_srs = osr.SpatialReference()
        out_srs.ImportFromWkt(ds_in.GetProjectionRef())
        ds_out.SetProjection(out_srs.ExportToWkt())

        blocks = 0
        for y in range(0, ysize, y_block_size):
            if y + y_block_size < ysize:
                rows = y_block_size
            else:
                rows = ysize - y
            for x in range(0, xsize, x_block_size):
                if self.killed:
                    log("Processing of {} killed by user after processing {} out of {} blocks."
                        .format(self.prod_out_file, y, ysize))
                    break
                self.progress.emit(100 * (float(y) +
                                          (float(x) / xsize) * y_block_size) /
                                   ysize)
                if x + x_block_size < xsize:
                    cols = x_block_size
                else:
                    cols = xsize - x

                # Write initial soc to band 2 of the output file. Read SOC in
                # as float so the soc change calculations won't accumulate
                # error due to repeated truncation of ints
                soc = np.array(soc_band.ReadAsArray(x, y, cols,
                                                    rows)).astype(np.float32)
                ds_out.GetRasterBand(2).WriteArray(soc, x, y)

                blocks += 1

        if self.killed:
            del ds_in
            del ds_out
            os.remove(self.out_f)
            return None
        else:
            return True
Example #22
0
    def setup_class_table(self, f=None):
        default_class_file = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), 'data',
            'land_cover_classes.json')
        if not f:
            f = default_class_file
        with open(f) as class_file:
            classes = json.load(class_file)

        if (not isinstance(classes, list) or not len(classes) > 0
                or not isinstance(classes[0], dict)
                or not classes[0].has_key('Initial_Code')
                or not classes[0].has_key('Initial_Label')
                or not classes[0].has_key('Final_Code')
                or not classes[0].has_key('Final_Label')):

            QtGui.QMessageBox.critical(
                None,
                QtGui.QApplication.translate('DlgCalculateLCSetAggregation',
                                             "Error"),
                QtGui.QApplication.translate(
                    'DlgCalculateLCSetAggregation',
                    "{} does not appear to contain a valid class definition.".
                    format(f)))
            return None
        else:
            self.classes = classes

        log('Loaded class definition from {}'.format(f))

        table_model = LCAggTableModel(self.classes, self)
        proxy_model = QtGui.QSortFilterProxyModel()
        proxy_model.setSourceModel(table_model)
        self.lc_agg_view.setModel(proxy_model)

        # Add selector in cell
        for row in range(0, len(self.classes)):
            lc_classes = QtGui.QComboBox()
            # Add the classes in order of their codes
            lc_classes.addItems(
                sorted(self.final_classes.keys(),
                       key=lambda k: self.final_classes[k]))
            ind = lc_classes.findText(self.classes[row]['Final_Label'])
            if ind != -1:
                lc_classes.setCurrentIndex(ind)
            self.lc_agg_view.setIndexWidget(proxy_model.index(row, 1),
                                            lc_classes)

        self.lc_agg_view.setSelectionBehavior(
            QtGui.QAbstractItemView.SelectRows)
        self.lc_agg_view.setColumnWidth(0, 500)
        self.lc_agg_view.horizontalHeader().setStretchLastSection(True)

        # Load and emit the new remap matrix
        self.update_remap_matrix()

        return True
Example #23
0
    def btn_calculate(self):
        if self.area_admin.isChecked():
            if not self.area_admin_0.currentText():
                QtGui.QMessageBox.critical(
                    None, self.tr("Error"),
                    self.tr("Choose a first level administrative boundary."),
                    None)
                return False
            self.button_calculate.setEnabled(False)
            geojson = self.load_admin_polys()
            self.button_calculate.setEnabled(True)
            if not geojson:
                QtGui.QMessageBox.critical(
                    None, self.tr("Error"),
                    self.tr("Unable to load administrative boundaries."), None)
                return False
        else:
            if not self.area_fromfile_file.text():
                QtGui.QMessageBox.critical(
                    None, self.tr("Error"),
                    self.tr("Choose a file to define the area of interest."),
                    None)
                return False
            layer = QgsVectorLayer(self.area_fromfile_file.text(),
                                   'calculation boundary', 'ogr')
            if not layer.isValid():
                QtGui.QMessageBox.critical(
                    None, self.tr("Error"),
                    self.tr("Unable to read area file."), None)
                return False
            log('Loaded layer: {}'.format(
                layer.dataProvider().dataSourceUri()))
            #TODO: Fix this kludge
            for f in layer.getFeatures():
                aoi = f.geometry()
                break
            crs_source = layer.crs()
            crs_dest = QgsCoordinateReferenceSystem(4326)
            aoi.transform(QgsCoordinateTransform(crs_source, crs_dest))
            geojson = json.loads(aoi.exportToGeoJSON())

        # Calculate bounding box of input polygon and then convert back to
        # geojson
        fields = QgsJSONUtils.stringToFields(json.dumps(geojson),
                                             QTextCodec.codecForName('UTF8'))
        features = QgsJSONUtils.stringToFeatureList(
            json.dumps(geojson), fields, QTextCodec.codecForName('UTF8'))
        if len(features) > 1:
            log("Found {} features in geojson - using first feature only.".
                format(len(features)))
        # Make a copy of this geometry
        self.aoi = QgsGeometry(features[0].geometry())
        self.bbox = json.loads(
            QgsGeometry.fromRect(self.aoi.boundingBox()).exportToGeoJSON())

        return True
Example #24
0
def download_timeseries(job):
    log("processing timeseries results...")
    table = job['results'].get('table', None)
    if not table:
        return None
    data = [x for x in table if x['name'] == 'mean'][0]
    dlg_plot = DlgPlot()
    dlg_plot.plot_data(data['time'], data['y'], job['task_name'])
    dlg_plot.show()
    dlg_plot.exec_()
Example #25
0
 def set_point_coords(self, point, button):
     log("Set point coords")
     #TODO: Show a messagebar while tool is active, and then remove the bar when a point is chosen.
     self.point = point
     # Disable the choose point tool
     self.canvas.setMapTool(QgsMapToolPan(self.canvas))
     self.show()
     self.point = self.canvas.getCoordinateTransform().toMapCoordinates(self.canvas.mouseLastXY())
     log("Chose point: {}, {}.".format(self.point.x(), self.point.y()))
     self.point_x.setText("{:.8f}".format(self.point.x()))
     self.point_y.setText("{:.8f}".format(self.point.y()))
Example #26
0
def download_result(url, outfile, job):
    log("Downloading {}".format(url))
    #TODO: Check if this file was already downloaded
    worker = Download(url, outfile)
    worker.start()
    if worker.get_resp():
        create_json_metadata(job, outfile)
        check_goog_cloud_store_hash(url, outfile)
        return True
    else:
        return None
Example #27
0
def make_summary_table(forest_change, carbon_change, area_missing, area_water,
                       area_non_forest, area_site, initial_forest_area,
                       initial_carbon_total, year_start, year_end, out_file):
    def tr(s):
        return QtWidgets.QApplication.translate("LDMP", s)

    wb = openpyxl.load_workbook(
        os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data',
                     'summary_table_tc.xlsx'))

    ##########################################################################
    # SDG table
    ws_summary = wb.get_sheet_by_name('Total Carbon Summary Table')
    ws_summary.cell(6, 3).value = initial_forest_area
    ws_summary.cell(7, 3).value = area_non_forest
    ws_summary.cell(8, 3).value = area_water
    ws_summary.cell(9, 3).value = area_missing
    #ws_summary.cell(10, 3).value = area_site

    ws_summary.cell(18, 2).value = initial_forest_area
    ws_summary.cell(18, 4).value = initial_carbon_total
    write_col_to_sheet(ws_summary, np.arange(year_start, year_end + 1), 1,
                       18)  # Years
    write_table_to_sheet(ws_summary, forest_change, 19, 3)
    write_table_to_sheet(ws_summary, carbon_change, 19, 5)

    try:
        ws_summary_logo = Image(
            os.path.join(os.path.dirname(__file__), 'data',
                         'trends_earth_logo_bl_300width.png'))
        ws_summary.add_image(ws_summary_logo, 'E1')
    except ImportError:
        # add_image will fail on computers without PIL installed (this will be
        # an issue on some Macs, likely others). it is only used here to add
        # our logo, so no big deal.
        pass

    try:
        wb.save(out_file)
        log(u'Summary table saved to {}'.format(out_file))
        QtWidgets.QMessageBox.information(
            None, QtWidgets.QApplication.translate("LDMP", "Success"),
            QtWidgets.QApplication.translate(
                "LDMP", u'Summary table saved to {}'.format(out_file)))

    except IOError:
        log(u'Error saving {}'.format(out_file))
        QtWidgets.QMessageBox.critical(
            None, QtWidgets.QApplication.translate("LDMP", "Error"),
            QtWidgets.QApplication.translate(
                "LDMP",
                u"Error saving output table - check that {} is accessible and not already open."
                .format(out_file)))
Example #28
0
def check_hash_against_etag(url, filename):
    h = get_header(url)
    expected = h.get('ETag', '').strip('"')

    md5hash = hashlib.md5(open(filename, 'rb').read()).hexdigest()

    if md5hash == expected:
        log("File hash verified for {}".format(filename))
        return True
    else:
        log("Failed verification of file hash for {}. Expected {}, but got {}".format(filename, expected, md5hash), 2)
        return False
Example #29
0
    def btn_calculate(self):
        # Note that the super class has several tests in it - if they fail it
        # returns False, which would mean this function should stop execution
        # as well.
        ret = super(DlgTimeseries, self).btn_calculate()
        if not ret:
            return

        self.close()

        if self.traj_climate.currentText() != "":
            climate_gee_dataset = self.climate_datasets[
                self.traj_climate.currentText()]['GEE Dataset']
            log('climate_gee_dataset {}'.format(climate_gee_dataset))
        else:
            climate_gee_dataset = None
        ndvi_dataset = self.datasets['NDVI'][
            self.dataset_ndvi.currentText()]['GEE Dataset']

        crosses_180th, geojsons = self.aoi.bounding_box_gee_geojson()
        payload = {
            'year_start': self.traj_year_start.date().year(),
            'year_end': self.traj_year_end.date().year(),
            'crosses_180th': crosses_180th,
            'geojsons': json.dumps(geojsons),
            'crs': self.aoi.get_crs_dst_wkt(),
            'ndvi_gee_dataset': ndvi_dataset,
            'task_name': self.options_tab.task_name.text(),
            'task_notes': self.options_tab.task_notes.toPlainText(),
            'climate_gee_dataset': climate_gee_dataset
        }
        # This will add in the method parameter
        payload.update(self.scripts['productivity']['trajectory functions'][
            self.traj_indic.currentText()]['params'])

        resp = run_script(get_script_slug('time-series'), payload)

        if resp:
            mb.pushMessage(
                self.tr("Submitted"),
                self.
                tr("Time series calculation task submitted to Google Earth Engine."
                   ),
                level=0,
                duration=5)
        else:
            mb.pushMessage(
                self.tr("Error"),
                self.
                tr("Unable to submit time series calculation task to Google Earth Engine."
                   ),
                level=1,
                duration=5)
Example #30
0
def style_prod_traj_trend(outfile):
    # Trends layer
    layer_ndvi = iface.addRasterLayer(
        outfile,
        QtGui.QApplication.translate(
            'LDMPPlugin',
            'Productivity trajectory trend\n(slope of NDVI * 10000)'))
    if not layer_ndvi.isValid():
        log('Failed to add layer')
        return None
    provider = layer_ndvi.dataProvider()

    # Set a colormap centred on zero, going to the extreme value significant to
    # three figures (after a 2 percent stretch)
    ds = gdal.Open(outfile)
    band1 = np.array(ds.GetRasterBand(1).ReadAsArray())
    band1[band1 >= 9997] = 0
    ds = None
    cutoffs = np.percentile(band1, [2, 98])
    extreme = get_extreme(cutoffs[0], cutoffs[1])

    fcn = QgsColorRampShader()
    fcn.setColorRampType(QgsColorRampShader.INTERPOLATED)
    lst = [
        QgsColorRampShader.ColorRampItem(
            -extreme, QtGui.QColor(153, 51, 4),
            QtGui.QApplication.translate('LDMPPlugin',
                                         '-{} (declining)').format(extreme)),
        QgsColorRampShader.ColorRampItem(
            0, QtGui.QColor(246, 246, 234),
            QtGui.QApplication.translate('LDMPPlugin', '0 (stable)')),
        QgsColorRampShader.ColorRampItem(
            extreme, QtGui.QColor(0, 140, 121),
            QtGui.QApplication.translate('LDMPPlugin',
                                         '{} (increasing)').format(extreme)),
        QgsColorRampShader.ColorRampItem(
            9997, QtGui.QColor(0, 0, 0),
            QtGui.QApplication.translate('LDMPPlugin', 'No data')),
        QgsColorRampShader.ColorRampItem(
            9998, QtGui.QColor(58, 77, 214),
            QtGui.QApplication.translate('LDMPPlugin', 'Water')),
        QgsColorRampShader.ColorRampItem(
            9999, QtGui.QColor(192, 105, 223),
            QtGui.QApplication.translate('LDMPPlugin', 'Urban land cover'))
    ]
    fcn.setColorRampItemList(lst)
    shader = QgsRasterShader()
    shader.setRasterShaderFunction(fcn)
    pseudoRenderer = QgsSingleBandPseudoColorRenderer(
        layer_ndvi.dataProvider(), 1, shader)
    layer_ndvi.setRenderer(pseudoRenderer)
    layer_ndvi.triggerRepaint()
    iface.legendInterface().refreshLayerSymbology(layer_ndvi)