Skip to content
Snippets Groups Projects
main.py 62.1 KiB
Newer Older
        ds = gdal.Open(self.pathImg, gdal.GA_ReadOnly)
unknown's avatar
unknown committed

        assert len(px_x) == 2 and px_x[0] <= px_x[1]
        assert len(px_y) == 2 and px_y[0] <= px_y[1]

        ns = px_x[1]-px_x[0]+1
        nl = px_y[1]-px_y[0]+1
unknown's avatar
unknown committed

        src_ns = ds.RasterXSize
        src_nl = ds.RasterYSize


        chipdata = dict()



        #pixel indices in source image
        x0 = max([0, px_x[0]])
        y0 = max([0, px_y[0]])
        x1 = min([src_ns, px_x[1]])
        y1 = min([src_nl, px_y[1]])
        win_xsize = x1-x0+1
        win_ysize = y1-y0+1

        #pixel indices in image chip (ideally 0 and ns-1 or nl-1)
        i0 = x0 - px_x[0]
        i1 = i0 + win_xsize

        j0 = y0 - px_y[0]
        j1 = j0+ win_ysize




        templateImg = np.zeros((nl,ns))
        if self.nodata:
            templateImg *= self.nodata

unknown's avatar
unknown committed
        templateImg = templateImg.astype(self.getdtype())
        templateMsk = np.ones((nl,ns), dtype='bool')

        if win_xsize < 1 or win_ysize < 1:
            six.print_('Selected image chip is out of raster image {}'.format(self.pathImg), file=sys.stderr)
unknown's avatar
unknown committed
            for i, b in enumerate(bands):
                chipdata[b] = np.copy(templateImg)

        else:
            for i, b in enumerate(bands):
                band = ds.GetRasterBand(b)
                data = np.copy(templateImg)
                data[j0:j1,i0:i1] = band.ReadAsArray(xoff=x0, yoff=y0, win_xsize=win_xsize,win_ysize=win_ysize)
                chipdata[b] = data
                nodatavalue = band.GetNoDataValue()
                if nodatavalue is not None:
                    templateMsk[j0:j1,i0:i1] = np.logical_and(templateMsk[j0:j1,i0:i1], data[j0:j1,i0:i1] != nodatavalue)

            if self.pathMsk:
                ds = gdal.Open(self.pathMsk)
                tmp = ds.GetRasterBand(1).ReadAsArray(xoff=x0, yoff=y0, \
                            win_xsize=win_xsize,win_ysize=win_ysize) == 0

                templateMsk[j0:j1,i0:i1] = np.logical_and(templateMsk[j0:j1,i0:i1], tmp)

        chipdata['mask'] = templateMsk
        return chipdata

    def __repr__(self):
        return 'TS Datum {} {}'.format(self.date, str(self.sensor))

    def __cmp__(self, other):
        return cmp(str((self.date, self.sensor)), str((other.date, other.sensor)))

    def __eq__(self, other):
        return self.date == other.date and self.sensor == other.sensor

    def __hash__(self):
        return hash((self.date,self.sensor.sensor_name))

unknown's avatar
unknown committed

regYYYYDOY = re.compile(r'(19|20)\d{5}')
regYYYYMMDD = re.compile(r'(19|20)\d{2}-\d{2}-\d{2}')
unknown's avatar
unknown committed
regYYYY = re.compile(r'(19|20)\d{2}')
unknown's avatar
unknown committed
def parseAcquisitionDate(text):
    match = regLandsatSceneID.search(text)
    if match:
        id = match.group()
        return getDateTime64FromYYYYDOY(id[9:16])
unknown's avatar
unknown committed
    match = regYYYYMMDD.search(text)
    if match:
        return np.datetime64(match.group())
unknown's avatar
unknown committed
    match = regYYYYDOY.search(text)
unknown's avatar
unknown committed
    if match:
        return getDateTime64FromYYYYDOY(match.group())
unknown's avatar
unknown committed
    match = regYYYY.search(text)
    if match:
        return np.datetime64(match.group())
unknown's avatar
unknown committed
    return None


unknown's avatar
unknown committed
def getDateTime64FromYYYYDOY(yyyydoy):
    return getDateTime64FromDOY(yyyydoy[0:4], yyyydoy[4:7])

def getDateTime64FromDOY(year, doy):
        if type(year) is str:
            year = int(year)
        if type(doy) is str:
            doy = int(doy)
        return np.datetime64('{:04d}-01-01'.format(year)) + np.timedelta64(doy-1, 'D')


def getChip3d(chips, rgb_idx, ranges):
    assert len(rgb_idx) == 3 and len(rgb_idx) == len(ranges)
    for i in rgb_idx:
        assert i in chips.keys()

    nl, ns = chips[rgb_idx[0]].shape
    a3d = np.ndarray((3,nl,ns), dtype='float')

    for i, rgb_i in enumerate(rgb_idx):
        range = ranges[i]
        data = chips[rgb_i].astype('float')
        data -= range[0]
        data *= 255./range[1]
        a3d[i,:] = data

    np.clip(a3d, 0, 255, out=a3d)

    return a3d.astype('uint8')

def Array2Image(d3d):
    nb, nl, ns = d3d.shape
    byteperline = nb
    d3d = d3d.transpose([1,2,0]).copy()

    return QImage(d3d.data, ns, nl, QImage.Format_RGB888)

class VerticalLabel(QLabel):
    def __init__(self, text):
        super(self.__class__, self).__init__()
        self.text = text

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setPen(Qt.black)
        painter.translate(20, 100)
        painter.rotate(-90)
        if self.text:
            painter.drawText(0, 0, self.text)
        painter.end()
unknown's avatar
unknown committed

    def minimumSizeHint(self):
        size = QLabel.minimumSizeHint(self)
        return QSize(size.height(), size.width())

    def sizeHint(self):
        size = QLabel.sizeHint(self)
        return QSize(size.height(), size.width())
unknown's avatar
unknown committed

unknown's avatar
unknown committed
class ImageChipBuffer(object):


    def __init__(self):
        self.data = dict()
        self.BBox = None
        self.SRS = None
unknown's avatar
unknown committed
        pass

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def hasDataCube(self, TSD):
        return TSD in self.data.keys()
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def getMissingBands(self, TSD, bands):
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        missing = set(bands)
        if TSD in self.data.keys():
            missing = missing - set(self.data[TSD].keys())
unknown's avatar
unknown committed
        return missing

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def addDataCube(self, TSD, chipData):
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        assert self.BBox is not None, 'Please initialize the bounding box first.'
unknown's avatar
unknown committed
        assert isinstance(chipData, dict)

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if TSD not in self.data.keys():
            self.data[TSD] = dict()
        self.data[TSD].update(chipData)

    def getDataCube(self, TSD):
        return self.data.get(TSD)
unknown's avatar
unknown committed

    def getChipArray(self, TSD, band_view, mode='rgb'):
        assert mode in ['rgb', 'bgr']
        bands = band_view.getBands(TSD.sensor)
        band_ranges = band_view.getRanges(TSD.sensor)
        nb = len(bands)
        assert nb == 3 and nb == len(band_ranges)
        assert TSD in self.data.keys(), 'Time Series Datum {} is not in buffer'.format(TSD.getDate())
        chipData = self.data[TSD]
        for b in bands:
            assert b in chipData.keys()



        nl, ns = chipData[bands[0]].shape

        dtype= 'uint8'
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        array_data = np.ndarray((nl,ns, nb), dtype=dtype)

        if mode == 'rgb':
            ch_dst = [0,1,2]
        elif mode == 'bgr':
            # r -> dst channel 2
            # g -> dst channel 1
            # b -> dst channel 0
            ch_dst = [2,1,0]
        for i, i_dst in enumerate(ch_dst):

            offset = band_ranges[i][0]
            scale = 255./band_ranges[i][1]

            res = pg.rescaleData(chipData[bands[i]], scale, offset, dtype='float')
            np.clip(res, 0, 255, out=res)
            array_data[:,:,i_dst] = res

        return array_data


Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def getChipRGB(self, TSD, band_view):
        bands = band_view.getBands(TSD.sensor)
        band_ranges = band_view.getRanges(TSD.sensor)
unknown's avatar
unknown committed
        assert len(bands) == 3 and len(bands) == len(band_ranges)
        assert TSD in self.data.keys(), 'Time Series Datum {} is not in buffer'.format(TSD.getDate())
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        chipData = self.data[TSD]
unknown's avatar
unknown committed
        for b in bands:
            assert b in chipData.keys()

        nl, ns = chipData[bands[0]].shape
        rgb_data = np.ndarray((3,nl,ns), dtype='float')

        for i, b in enumerate(bands):
            range = band_ranges[i]
            data = chipData[b].astype('float')
            data -= range[0]
            data *= 255./range[1]
            rgb_data[i,:] = data

        np.clip(rgb_data, 0, 255, out=rgb_data)
        rgb_data = rgb_data.astype('uint8')

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if band_view.useMaskValues():
            rgb = band_view.getMaskColor()
unknown's avatar
unknown committed
            is_masked = np.where(np.logical_not(chipData['mask']))
            for i, c in enumerate(rgb):
                rgb_data[i, is_masked[0], is_masked[1]] = c

unknown's avatar
unknown committed

    def getChipImage(self, date, view):
        rgb = self.getChipRGB(date, view)
        nb, nl, ns = rgb.shape
        rgb = rgb.transpose([1,2,0]).copy('C')
        return QImage(rgb.data, ns, nl, QImage.Format_RGB888)
unknown's avatar
unknown committed

    def clear(self):
        self.data.clear()

    def setBoundingBox(self, BBox):
        assert type(BBox) is ogr.Geometry
        SRS = BBox.GetSpatialReference()
        assert SRS is not None
        if self.BBox is None or not self.BBox.Equals(BBox) or not self.SRS.IsSame(SRS):
unknown's avatar
unknown committed
            self.BBox = BBox
            self.SRS = SRS

    def __repr__(self):
        info = ['Chipbuffer']
        info.append('Bounding Box: {}'.format(self.bbBoxWkt))
        info.append('Chips: {}'.format(len(self.data)))
        return '\n'.join(info)


list2str = lambda ll : '\n'.join([str(l) for l in ll])

class TimeSeriesViewer:
unknown's avatar
unknown committed
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        if isinstance(self.iface, qgis.gui.QgisInterface):
            import console
            console.show_console()
unknown's avatar
unknown committed
        # Create the dialog (after translation) and keep reference
        from timeseriesviewer.ui.widgets import TimeSeriesViewerUI
        self.dlg = TimeSeriesViewerUI()
unknown's avatar
unknown committed
        D = self.dlg
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        #init on empty time series
        self.TS = None
        self.init_TimeSeries()
        self.BAND_VIEWS = list()
unknown's avatar
unknown committed
        self.ImageChipBuffer = ImageChipBuffer()
        self.CHIPWIDGETS = collections.OrderedDict()

        self.ValidatorPxX = QIntValidator(0,99999)
        self.ValidatorPxY = QIntValidator(0,99999)
        D.btn_showPxCoordinate.clicked.connect(lambda: self.ua_showPxCoordinate_start())
        D.btn_selectByCoordinate.clicked.connect(self.ua_selectByCoordinate)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        D.btn_selectByRectangle.clicked.connect(self.ua_selectByRectangle)
        D.btn_addBandView.clicked.connect(lambda :self.ua_addBandView())
unknown's avatar
unknown committed
        D.btn_addTSImages.clicked.connect(lambda :self.ua_addTSImages())
        D.btn_addTSMasks.clicked.connect(lambda :self.ua_addTSMasks())
        D.btn_loadTSFile.clicked.connect(self.ua_loadTSFile)
        D.btn_saveTSFile.clicked.connect(self.ua_saveTSFile)
        D.btn_addTSExample.clicked.connect(self.ua_loadExampleTS)
        D.btn_labeling_clear.clicked.connect(D.tb_labeling_text.clear)
        D.actionAdd_Images.triggered.connect(lambda :self.ua_addTSImages())
        D.actionAdd_Masks.triggered.connect(lambda :self.ua_addTSMasks())
        D.actionLoad_Time_Series.triggered.connect(self.ua_loadTSFile)
        D.actionSave_Time_Series.triggered.connect(self.ua_saveTSFile)
        D.actionLoad_Example_Time_Series.triggered.connect(self.ua_loadExampleTS)
        D.actionAbout.triggered.connect( \
            lambda: QMessageBox.about(self.dlg, 'SenseCarbon TimeSeriesViewer', 'A viewer to visualize raster time series data'))

        D.btn_removeTSD.clicked.connect(lambda : self.ua_removeTSD(None))
        D.btn_removeTS.clicked.connect(self.ua_clear_TS)


unknown's avatar
unknown committed
        D.spinBox_ncpu.setRange(0, multiprocessing.cpu_count())

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.RectangleMapTool = None
        self.PointMapTool = None
        self.canvas_srs = osr.SpatialReference()

unknown's avatar
unknown committed
        if self.iface:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.canvas = self.iface.mapCanvas()
unknown's avatar
unknown committed

unknown's avatar
unknown committed
            self.RectangleMapTool = qgis_add_ins.RectangleMapTool(self.canvas)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.RectangleMapTool.rectangleDrawed.connect(self.ua_selectBy_Response)
unknown's avatar
unknown committed
            self.PointMapTool = qgis_add_ins.PointMapTool(self.canvas)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.PointMapTool.coordinateSelected.connect(self.ua_selectBy_Response)
            #self.RectangleMapTool.connect(self.ua_selectByRectangle_Done)
        self.ICP = self.dlg.scrollArea_imageChip_content.layout()
        self.dlg.scrollArea_bandViews_content.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.BVP = self.dlg.scrollArea_bandViews_content.layout()
unknown's avatar
unknown committed
        self.check_enabled()
        s = ""

    @staticmethod
    def icon():
        return QIcon(':/plugins/SenseCarbon/icon.png')

    def icon(self):
        return TimeSeriesViewer.icon()

    def init_TimeSeries(self, TS=None):
        if TS is None:
            TS = TimeSeries()
        assert type(TS) is TimeSeries

        if self.TS is not None:
            disconnect_signal(self.TS.datumAdded)
            disconnect_signal(self.TS.progress)
            disconnect_signal(self.TS.chipLoaded)

        self.TS = TS
        self.TS.datumAdded.connect(self.ua_datumAdded)
        self.TS.progress.connect(self.ua_TSprogress)
        self.TS.chipLoaded.connect(self.ua_showPxCoordinate_addChips)

        TSM = TimeSeriesTableModel(self.TS)
        D = self.dlg
        D.tableView_TimeSeries.setModel(TSM)
        D.tableView_TimeSeries.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
        D.cb_doi.setModel(TSM)
        D.cb_doi.setModelColumn(0)
        D.cb_doi.currentIndexChanged.connect(self.scrollToDate)


    def ua_loadTSFile(self, path=None):
        if path is None or path is False:
            path = QFileDialog.getOpenFileName(self.dlg, 'Open Time Series file', '')

            M = self.dlg.tableView_TimeSeries.model()
            M.beginResetModel()
            self.ua_clear_TS()
            self.TS.loadFromFile(path)
            M.endResetModel()

            self.refreshBandViews()
        self.check_enabled()

    def ua_saveTSFile(self):
        path = QFileDialog.getSaveFileName(self.dlg, caption='Save Time Series file')
        if path is not None:
            self.TS.saveToFile(path)


    def ua_loadExampleTS(self):
        from timeseriesviewer import DIR_EXAMPLE
        path_example = jp(DIR_EXAMPLE, 'testdata.txt')
        if not os.path.exists(path_example):
            QMessageBox.information(self.dlg, 'File not found', '{} - this file describes an exemplary time series.'.format(path_example))
            self.ua_loadTSFile(path=path_example)
unknown's avatar
unknown committed
    def ua_selectByRectangle(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if self.RectangleMapTool is not None:
            self.canvas.setMapTool(self.RectangleMapTool)
unknown's avatar
unknown committed

    def ua_selectByCoordinate(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if self.PointMapTool is not None:
            self.canvas.setMapTool(self.PointMapTool)

    def setCanvasSRS(self,srs):
        if type(srs) is osr.SpatialReference:
            self.canvas_srs = srs
        else:
            self.canvas_srs.ImportFromWkt(srs)

        self.dlg.tb_bb_srs.setPlainText(self.canvas_srs.ExportToProj4())

    def ua_selectBy_Response(self, geometry, srs_wkt):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        D = self.dlg
        x = D.spinBox_coordinate_x.value()
        y = D.spinBox_coordinate_x.value()
        dx = D.doubleSpinBox_subset_size_x.value()
        dy = D.doubleSpinBox_subset_size_y.value()

        self.setCanvasSRS(osr.GetUserInputAsWKT(str(srs_wkt)))

Benjamin Jakimow's avatar
Benjamin Jakimow committed

        if type(geometry) is QgsRectangle:
            center = geometry.center()
            x = center.x()
            y = center.y()

            dx = geometry.xMaximum() - geometry.xMinimum()
            dy = geometry.yMaximum() - geometry.yMinimum()

        if type(geometry) is QgsPoint:
            x = geometry.x()
            y = geometry.y()

        """
        ref_srs = self.TS.getSRS()
        if ref_srs is not None and not ref_srs.IsSame(canvas_srs):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            print('Convert canvas coordinates to time series SRS')
            g = ogr.Geometry(ogr.wkbPoint)
            g.AddPoint(x,y)
            g.AssignSpatialReference(canvas_srs)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            x = g.GetX()
            y = g.GetY()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        D.doubleSpinBox_subset_size_x.setValue(dx)
        D.doubleSpinBox_subset_size_y.setValue(dy)
        D.spinBox_coordinate_x.setValue(x)
        D.spinBox_coordinate_y.setValue(y)

        if D.cb_loadSubsetDirectly.isChecked():
            self.ua_showPxCoordinate_start()

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def qgs_handleMouseDown(self, pt, btn):
unknown's avatar
unknown committed


    def ua_TSprogress(self, v_min, v, v_max):
        assert v_min <= v and v <= v_max
        if v_min < v_max:
            P = self.dlg.progressBar
            if P.minimum() != v_min or P.maximum() != v_max:
                P.setRange(v_min, v_max)
            else:
                s = ""

            P.setValue(v)
unknown's avatar
unknown committed

    def ua_datumAdded(self):
unknown's avatar
unknown committed
        if len(self.TS) > 0:
            self.setCanvasSRS(self.TS.getSRS())
unknown's avatar
unknown committed
            if self.dlg.spinBox_coordinate_x.value() == 0.0 and \
               self.dlg.spinBox_coordinate_y.value() == 0.0:
                xmin, ymin, xmax, ymax = self.TS.getMaxExtent(srs=self.canvas_srs)
unknown's avatar
unknown committed
                self.dlg.spinBox_coordinate_x.setRange(xmin, xmax)
                self.dlg.spinBox_coordinate_y.setRange(ymin, ymax)
                #x, y = self.TS.getSceneCenter()
unknown's avatar
unknown committed
                self.dlg.spinBox_coordinate_x.setValue(0.5*(xmin+xmax))
                self.dlg.spinBox_coordinate_y.setValue(0.5*(ymin+ymax))
        self.dlg.cb_doi.setCurrentIndex(int(len(self.TS) / 2))
unknown's avatar
unknown committed
        self.dlg.tableView_TimeSeries.resizeColumnsToContents()

    def check_enabled(self):
        D = self.dlg
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        hasTS = len(self.TS) > 0 or DEBUG
        hasTSV = len(self.BAND_VIEWS) > 0
unknown's avatar
unknown committed
        hasQGIS = qgis_available

        #D.tabWidget_viewsettings.setEnabled(hasTS)
unknown's avatar
unknown committed
        D.btn_showPxCoordinate.setEnabled(hasTS and hasTSV)
        D.btn_selectByCoordinate.setEnabled(hasQGIS)
        D.btn_selectByRectangle.setEnabled(hasQGIS)


unknown's avatar
unknown committed


    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('EnMAPBox', message)





    def ua_addTSD_to_QGIS(self, TSD, bands):
unknown's avatar
unknown committed
    def unload(self):
        """Removes the plugin menu item and icon """
        self.iface.removeToolBarIcon(self.action)
unknown's avatar
unknown committed

    def run(self):
        self.dlg.show()


    def scrollToDate(self, date_of_interest):
        HBar = self.dlg.scrollArea_imageChips.horizontalScrollBar()
        TSDs = list(self.CHIPWIDGETS.keys())
        if len(TSDs) == 0:
            return

        #get date INDEX that is closest to requested date
        if type(date_of_interest) is str:
            date_of_interest = np.datetime64(date_of_interest)

        if type(date_of_interest) is np.datetime64:
            i_doi = TSDs.index(sorted(TSDs, key=lambda TSD: abs(date_of_interest - TSD.getDate()))[0])
        else:
            i_doi = date_of_interest
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        step = int(float(HBar.maximum()) / (len(TSDs)+1))
        HBar.setSingleStep(step)
        HBar.setPageStep(step*5)
        HBar.setValue(i_doi * step)
unknown's avatar
unknown committed
    def ua_showPxCoordinate_start(self):
unknown's avatar
unknown committed

        if len(self.TS) == 0:
            return
unknown's avatar
unknown committed
        D = self.dlg
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        dx = D.doubleSpinBox_subset_size_x.value() * 0.5
unknown's avatar
unknown committed
        dy = D.doubleSpinBox_subset_size_y.value() * 0.5
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        cx = D.spinBox_coordinate_x.value()
        cy = D.spinBox_coordinate_y.value()
unknown's avatar
unknown committed

        pts = [(cx - dx, cy + dy), \
               (cx + dx, cy + dy), \
               (cx + dx, cy - dy), \
               (cx - dx, cy - dy)]
unknown's avatar
unknown committed

        bb = getBoundingBoxPolygon(pts, srs=self.canvas_srs)
unknown's avatar
unknown committed
        bbWkt = bb.ExportToWkt()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        srsWkt = bb.GetSpatialReference().ExportToWkt()
unknown's avatar
unknown committed
        self.ImageChipBuffer.setBoundingBox(bb)

        D = self.dlg
unknown's avatar
unknown committed
        ratio = dx / dy
        size_px = D.spinBox_chipsize_max.value()
        if ratio > 1: #x is largest side
            size_x = size_px
            size_y = int(size_px / ratio)
        else: #y is largest
            size_y = size_px
            size_x = int(size_px * ratio)
unknown's avatar
unknown committed

unknown's avatar
unknown committed
        #get the dates of interes
        dates_of_interest = list()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        doiTSD = D.cb_doi.itemData(D.cb_doi.currentIndex())
        if doiTSD is None:
            idx = int(len(self.TS)/2)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            doiTSD = D.cb_doi.itemData(idx)
            D.cb_doi.setCurrentIndex(idx)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        centerDate = doiTSD.getDate()
        allDates = self.TS.getObservationDates()
        i_doi = allDates.index(centerDate)

unknown's avatar
unknown committed
        if D.rb_showEntireTS.isChecked():
            dates_of_interest = allDates
unknown's avatar
unknown committed
        elif D.rb_showTimeWindow.isChecked():
            i0 = max([0, i_doi-D.sb_ndates_before.value()])
            ie = min([i_doi + D.sb_ndates_after.value(), len(allDates)-1])
            dates_of_interest = allDates[i0:ie+1]
unknown's avatar
unknown committed


        diff = set(dates_of_interest)
        diff = diff.symmetric_difference(self.CHIPWIDGETS.keys())
unknown's avatar
unknown committed

        self.clearLayoutWidgets(self.ICP)
unknown's avatar
unknown committed
        self.CHIPWIDGETS.clear()

unknown's avatar
unknown committed

        #initialize image labels

        cnt_chips = 0

        TSDs_of_interest = list()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        for date in dates_of_interest:
unknown's avatar
unknown committed

            #LV = QVBoxLayout()
            #LV.setSizeConstraint(QLayout.SetNoConstraint)

            for TSD in self.TS.getTSDs(date_of_interest=date):
                TSDs_of_interest.append(TSD)
                info_label_text = '{}\n{}'.format(TSD.date, TSD.sensor.sensor_name)
                textLabel = QLabel(info_label_text)
                tt = [TSD.date,TSD.pathImg, TSD.pathMsk]
                textLabel.setToolTip(list2str(tt))
                self.ICP.addWidget(textLabel, 0, cnt_chips)
                viewList = list()
                j = 1
                for view in self.BAND_VIEWS:
                    bands = view.getBands(TSD.sensor)
                    #imageLabel = QLabel()
                    #imv = pg.GraphicsView()
                    #imv = QGraphicsView(self.dlg.scrollArea_imageChip_content)
                    #imv = MyGraphicsView(self.dlg.scrollArea_imageChip_content, iface=self.iface, path=TSD.pathImg, bands=bands)
                    #imv = pg.ImageView(view=None)
                    imgLabel = ImageChipLabel(time_series_viewer=self.dlg, iface=self.iface, TSD=TSD, bands=bands)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

                    imgLabel.setMinimumSize(size_x, size_y)
                    imgLabel.setMaximumSize(size_x, size_y)
                    imgLabel.clicked.connect(self.ua_collect_date)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

                    viewList.append(imgLabel)
                    self.ICP.addWidget(imgLabel, j, cnt_chips)
                    j += 1

                textLabel = QLabel(info_label_text)
                textLabel.setToolTip(str(TSD))
                self.ICP.addWidget(textLabel, j, cnt_chips)

                self.CHIPWIDGETS[TSD] = viewList

                cnt_chips += 1
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.dlg.scrollArea_imageChip_content.update()

        self.scrollToDate(centerDate)

        s = ""
        #ScrollArea.show()
        #ScrollArea.horizontalScrollBar().setValue()


unknown's avatar
unknown committed

        #fill image labels
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        required_bands = dict()
        for j, view in enumerate(self.BAND_VIEWS):
                for S in view.Sensors.keys():
                    bands = set()
                    bands.update(view.getBands(S))
                    if len(bands) != 3:
                        s = ""
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                    assert len(bands) == 3
                    if S not in required_bands.keys():
                        required_bands[S] = set()
                    required_bands[S] = required_bands[S].union(bands)
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        missing = set()
        for TSD in TSDs_of_interest:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            missing_bands = self.ImageChipBuffer.getMissingBands(TSD, required_bands[TSD.sensor])
            if len(missing_bands) == 0:
                self.ua_showPxCoordinate_addChips(None, TSD=TSD)
unknown's avatar
unknown committed
            else:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                missing.add((TSD, tuple(missing_bands)))

unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        missing =list(missing)
        if len(missing) > 0:
            missing = sorted(missing, key=lambda d: abs(centerDate - d[0].getDate()))
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.TS.getSpatialChips_parallel(bbWkt, srsWkt, TSD_band_list=missing)
    def ua_collect_date(self, ICL, event):
        if self.dlg.rb_labeling_activate.isChecked():
            txt = self.dlg.tb_labeling_text.toPlainText()
            reg = re.compile('\d{4}-\d{2}-\d{2}', re.I | re.MULTILINE)
            dates = set([np.datetime64(m) for m in reg.findall(txt)])
            doi = ICL.TSD.getDate()

            if event.button() == Qt.LeftButton:
                dates.add(doi)
            elif event.button() == Qt.MiddleButton and doi in dates:
                dates.remove(doi)

            dates = sorted(list(dates))
            txt = ' '.join([d.astype(str) for d in dates])
            self.dlg.tb_labeling_text.setText(txt)
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed

    def ua_showPxCoordinate_addChips(self, results, TSD=None):
unknown's avatar
unknown committed

        if results is not None:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            TSD, chipData = results
            self.ImageChipBuffer.addDataCube(TSD, chipData)
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if TSD not in self.CHIPWIDGETS.keys():
            six.print_('TSD {} does not exist in CHIPBUFFER'.format(TSD), file=sys.stderr)
        else:
            for imgChipLabel, bandView in zip(self.CHIPWIDGETS[TSD], self.BAND_VIEWS):
                #imgView.clear()
                #imageLabel.setScaledContents(True)

                #rgb = self.ImageChipBuffer.getChipRGB(TSD, bandView)
                array = self.ImageChipBuffer.getChipArray(TSD, bandView, mode = 'bgr')
                qimg = pg.makeQImage(array, copy=True, transpose=False)

                #rgb2 = rgb.transpose([1,2,0]).copy('C')
                #qImg = qimage2ndarray.array2qimage(rgb2)
                #img = QImage(rgb2.data, nl, ns, QImage.Format_RGB888)

                pxMap = QPixmap.fromImage(qimg).scaled(imgChipLabel.size(), Qt.KeepAspectRatio)
                imgChipLabel.setPixmap(pxMap)
                imgChipLabel.update()
                #imgView.setPixmap(pxMap)
                #imageLabel.update()
                #imgView.adjustSize()
                #pxmap = QPixmap.fromImage(qimg)
                #

                """
                pxmapitem = QGraphicsPixmapItem(pxmap)
                if imgChipLabel.scene() is None:
                    imgChipLabel.setScene(QGraphicsScene())
                else:
                    imgChipLabel.scene().clear()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                scene = imgChipLabel.scene()
                scene.addItem(pxmapitem)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                imgChipLabel.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
                """
unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
                pass
            self.ICP.layout().update()
            self.dlg.scrollArea_imageChip_content.update()
            s = ""
unknown's avatar
unknown committed

        pass

    def clearLayoutWidgets(self, L):
        if L is not None:
            while L.count():
                w = L.takeAt(0)
                w.widget().deleteLater()
                #if w is not None:
                #    w.widget().deleteLater()
unknown's avatar
unknown committed

    def ua_addTSImages(self, files=None):
        if files is None:
            files = QFileDialog.getOpenFileNames()

        if files:
            M = self.dlg.tableView_TimeSeries.model()
            M.beginResetModel()
            self.TS.addFiles(files)
            M.endResetModel()
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.refreshBandViews()

unknown's avatar
unknown committed
        self.check_enabled()


    def ua_addTSMasks(self, files=None):

        if files is None:
            files = QFileDialog.getOpenFileNames()

        l = len(files)
        if l > 0:
            M = self.dlg.tableView_TimeSeries.model()
            M.beginResetModel()
unknown's avatar
unknown committed
            self.TS.addMasks(files, raise_errors=False)
unknown's avatar
unknown committed
            M.endResetModel()

        self.check_enabled()



    def ua_addBandView(self, band_recommendation = [3, 2, 1]):
        bandView = BandView(self.TS, recommended_bands=band_recommendation)
        #bandView.removeView.connect(self.ua_removeBandView)
        self.BAND_VIEWS.append(bandView)
Benjamin Jakimow's avatar
Benjamin Jakimow committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def refreshBandViews(self):

        if len(self.BAND_VIEWS) == 0 and len(self.TS) > 0:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            self.ua_addBandView(band_recommendation=[3, 2, 1])
            self.ua_addBandView(band_recommendation=[4, 5, 3])
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.clearLayoutWidgets(self.BVP)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        for i, BV in enumerate(self.BAND_VIEWS):
            W = QWidget()
            hl = QHBoxLayout()
            textLabel = VerticalLabel('View {}'.format(i+1))
            textLabel = QLabel('View {}'.format(i+1))
            textLabel.setToolTip('')
            textLabel.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
            hl.addWidget(textLabel)
            for S in self.TS.Sensors.keys():
                w = BV.getWidget(S)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                w.setMaximumSize(w.size())
                #w.setMinimumSize(w.size())
                w.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.MinimumExpanding)
                #w.setBands(band_recommendation)
                hl.addWidget(w)
                s = ""

            hl.addItem(QSpacerItem(20,20,QSizePolicy.Expanding,QSizePolicy.Minimum))
            W.setLayout(hl)
            self.BVP.addWidget(W)
        self.check_enabled()
unknown's avatar
unknown committed

unknown's avatar
unknown committed

Benjamin Jakimow's avatar
Benjamin Jakimow committed
    def ua_removeBandView(self, w):
        self.BAND_VIEWS.remove(w)
    def ua_clear_TS(self):
unknown's avatar
unknown committed
        #remove views

        M = self.dlg.tableView_TimeSeries.model()
        M.beginResetModel()
        self.TS.clear()
        M.endResetModel()
        self.check_enabled()

    def ua_removeTSD(self, TSDs=None):
        if TSDs is None:
            TSDs = self.getSelectedTSDs()
        assert isinstance(TSDs,list)
unknown's avatar
unknown committed

unknown's avatar
unknown committed
        M = self.dlg.tableView_TimeSeries.model()
        M.beginResetModel()
        self.TS.removeDates(TSDs)
unknown's avatar
unknown committed
        M.endResetModel()
unknown's avatar
unknown committed
        self.check_enabled()
unknown's avatar
unknown committed


    def getSelectedTSDs(self):
        TV = self.dlg.tableView_TimeSeries
        TVM = TV.model()
        return [TVM.getTimeSeriesDatumFromIndex(idx) for idx in TV.selectionModel().selectedRows()]
def disconnect_signal(signal):
    while True:
        try:
            signal.disconnect()
        except TypeError:
            break
unknown's avatar
unknown committed


unknown's avatar
unknown committed
    from scipy.misc import toimage
    toimage(data).show()

unknown's avatar
unknown committed
def run_tests():

    if False:

        pathImg = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted\2014-07-26_LC82270652014207LGN00_BOA.vrt'
        pathMsk = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted\2014-07-26_LC82270652014207LGN00_Msk.vrt'

        if False:
            TSD = TimeSeriesDatum(pathImg)
            TSD.setMask(pathMsk)
unknown's avatar
unknown committed

unknown's avatar
unknown committed

            c = [670949.883,-786288.771]

            w_x = w_y = 1000 #1km box
            srs = TSD.getSpatialReference()
            ring = ogr.Geometry(ogr.wkbLinearRing)
            import itertools
            for x,y in itertools.product([1000, -1000], repeat=2):
                ring.AddPoint(c[0]+x, c[1]+y)
            ring.AssignSpatialReference(srs)
            bb = ogr.Geometry(ogr.wkbPolygon)
            bb.AddGeometry(ring)
            bb.AssignSpatialReference(srs)
unknown's avatar
unknown committed




        def getChip3d_OLD(chips, r,g,b, range_r, range_g, range_b):

            nl, ns = chips[r].shape
            a3d = np.ndarray((3,nl,ns), dtype='float')

            rgb_idx = [r,g,b]
            ranges = [range_r, range_g, range_b]

            for i, rgb_i in enumerate(rgb_idx):
                range = ranges[i]
                data = chips[rgb_i].astype('float')
                data -= range[0]
                data *= 255./range[1]
                a3d[i,:] = data

            np.clip(a3d, 0, 255, out=a3d)

            return a3d.astype('uint8')

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        app  = QApplication([])
        main = PictureTest()
unknown's avatar
unknown committed
        main.show()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

unknown's avatar
unknown committed
        range_r = [0,500]
        range_g = [0,500]
        range_b = [0,500]

        bands = [3,2,1]
        #chipData = TSD.readSpatialChip(bb,bands=bands )
unknown's avatar
unknown committed

        #main.addNumpy(getChip3d(chipData, bands, (range_r, range_g, range_b)))
unknown's avatar
unknown committed
        app.exec_()
        exit(0)

    if False:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        dirSrcLS = r'O:\SenseCarbonProcessing\BJ_NOC\01_RasterData\00_VRTs\02_Cutted'
        filesImgLS = file_search(dirSrcLS, '2014*_BOA.vrt')
        filesMsk = file_search(dirSrcLS, '2014*_Msk.vrt')
        TS = TimeSeries(imageFiles=filesImgLS, maskFiles=filesMsk)