Newer
Older
nl, ns = chipData[bands[0]].shape
dtype= 'uint8'
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
bands = band_view.getBands(TSD.sensor)
band_ranges = band_view.getRanges(TSD.sensor)
assert TSD in self.data.keys(), 'Time Series Datum {} is not in buffer'.format(TSD.getDate())
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')
if band_view.useMaskValues():
rgb = band_view.getMaskColor()
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
return rgb_data
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)
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):
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])
"""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

benjamin.jakimow@geo.hu-berlin.de
committed
if isinstance(self.iface, qgis.gui.QgisInterface):
import console
console.show_console()
from timeseriesviewer.ui.widgets import TimeSeriesViewerUI
self.ui = TimeSeriesViewerUI()
#init empty time series
self.TS = TimeSeries()
self.hasInitialCenterPoint = False
self.TS.sigTimeSeriesDatumAdded.connect(self.ua_datumAdded)
self.TS.sigChanged.connect(self.timeseriesChanged)
self.TS.sigProgress.connect(self.ua_TSprogress)
#init TS model
TSM = TimeSeriesTableModel(self.TS)
D = self.ui
self.ICP = D.scrollAreaSubsetContent.layout()
D.scrollAreaBandViewsContent.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.BVP = self.ui.scrollAreaBandViewsContent.layout()
D.tableView_TimeSeries.setModel(TSM)
D.tableView_TimeSeries.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
self.bandViewManager = BandViewManager(self)
self.timeSeriesViewManager = TimeSeriesDatumViewManager(self)
self.PIXMAPS = PixmapBuffer()
self.PIXMAPS.sigPixmapCreated.connect(self.showSubset)
self.CHIPWIDGETS = collections.OrderedDict()
self.ValidatorPxX = QIntValidator(0,99999)
self.ValidatorPxY = QIntValidator(0,99999)
#connect actions with logic
#D.btn_showPxCoordinate.clicked.connect(lambda: self.showSubsetsStart())
D.actionSelectCenter.triggered.connect(self.ua_selectByCoordinate)
D.actionSelectArea.triggered.connect(self.ua_selectByRectangle)
D.actionAddBandView.triggered.connect(self.bandViewManager.createBandView)
D.actionAddTSD.triggered.connect(self.ua_addTSImages)
D.actionRemoveTSD.triggered.connect(self.removeTimeSeriesDates)
D.actionLoadTS.triggered.connect(self.ua_loadTSFile)
D.actionClearTS.triggered.connect(self.clearTimeSeries)
D.actionSaveTS.triggered.connect(self.ua_saveTSFile)
D.actionAddTSExample.triggered.connect(self.ua_loadExampleTS)
#connect buttons with actions
D.btnClearLabelList.clicked.connect(D.tbCollectedLabels.clear)
lambda: QMessageBox.about(self.ui, 'SenseCarbon TimeSeriesViewer', 'A viewer to visualize raster time series data'))
D.actionFirstTSD.triggered.connect(lambda: self.setDOISliderValue('first'))
D.actionLastTSD.triggered.connect(lambda: self.setDOISliderValue('last'))
D.actionNextTSD.triggered.connect(lambda: self.setDOISliderValue('next'))
D.actionPreviousTSD.triggered.connect(lambda: self.setDOISliderValue('previous'))
D.sliderDOI.valueChanged.connect(self.setDOI)
D.actionSetSubsetSize.triggered.connect(lambda : self.timeSeriesViewManager.setSubsetSize(
self.ui.subsetSize()))
D.actionSetExtent.triggered.connect(lambda: self.timeSeriesViewManager.setExtent(self.ui.extent()))
self.RectangleMapTool = None
self.PointMapTool = None
self.canvasCrs = QgsCoordinateReferenceSystem()
self.RectangleMapTool = qgis_add_ins.RectangleMapTool(self.canvas)
self.RectangleMapTool.rectangleDrawed.connect(self.setSpatialSubset)
self.PointMapTool.coordinateSelected.connect(self.setSpatialSubset)
def setDOISliderValue(self, key):
ui = self.ui
v = ui.sliderDOI.value()
if key == 'first':
v = ui.sliderDOI.minimum()
elif key == 'last':
v = ui.sliderDOI.maximum()
elif key =='next':
v = min([v+1,ui.sliderDOI.maximum()])
elif key =='previous':
v = max([v - 1, ui.sliderDOI.minimum()])
ui.sliderDOI.setValue(v)
def setDOI(self, i):
TSD = self.TS.data[i - 1]
text = str(TSD.date)
if TSD:
self.timeSeriesViewManager.navToDOI(TSD)
@staticmethod
def icon():
return QIcon(':/plugins/SenseCarbon/icon.png')
def icon(self):
return TimeSeriesViewer.icon()
D = self.ui
D.sliderDOI.setMinimum(1)
D.sliderDOI.setMaximum(len(self.TS.data))
if len(self.TS.data)>0 and not self.hasInitialCenterPoint:
extent = self.TS.getMaxExtent(self.canvasCrs)
self.setSpatialSubset(extent.center(), self.canvasCrs)
self.hasInitialCenterPoint = True
if len(self.TS.data) == 0:
self.hasInitialCenterPoint = False
else:
if len(self.bandViewManager) == 0:
# add two empty band-views by default
self.ua_addBandView()
self.ua_addBandView()
if path is None or path is False:
path = QFileDialog.getOpenFileName(self.ui, 'Open Time Series file', '')
if os.path.exists(path):
M = self.ui.tableView_TimeSeries.model()
def ua_saveTSFile(self):
path = QFileDialog.getSaveFileName(self.ui, caption='Save Time Series file')
if path is not None:
self.TS.saveToFile(path)
def ua_loadExampleTS(self):
from timeseriesviewer import PATH_EXAMPLE_TIMESERIES
if not os.path.exists(PATH_EXAMPLE_TIMESERIES):
QMessageBox.information(self.ui, 'File not found', '{} - this file describes an exemplary time series.'.format(path_example))
if self.RectangleMapTool is not None:
self.canvas.setMapTool(self.RectangleMapTool)
if self.PointMapTool is not None:
self.canvas.setMapTool(self.PointMapTool)
#self.canvas_srs = srs
self.canvasCrs = srs
self.ui.tb_bb_srs.setPlainText(self.canvasCrs.toWkt())
def setSpatialSubset(self, geometry, crs):
assert isinstance(crs, QgsCoordinateReferenceSystem)
assert isinstance(geometry, QgsRectangle) or isinstance(geometry, QgsPoint)
extent = SpatialExtent(crs,geometry).toCrs(self.ui.crs())
self.ui.setSpatialExtent(extent)

benjamin.jakimow@geo.hu-berlin.de
committed
def ua_TSprogress(self, v_min, v, v_max):
assert v_min <= v and v <= v_max
P = self.ui.progressBar
if P.minimum() != v_min or P.maximum() != v_max:
P.setRange(v_min, v_max)
else:
s = ""
P.setValue(v)
def ua_datumAdded(self, TSD):
if len(self.TS) == 1:
self.ui.tableView_TimeSeries.resizeColumnsToContents()
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
# 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):
"""Removes the plugin menu item and icon """
self.iface.removeToolBarIcon(self.action)
self.ui.show()

Benjamin Jakimow
committed
def scrollToDate(self, date_of_interest):

Benjamin Jakimow
committed
QApplication.processEvents()
HBar = self.ui.scrollArea_imageChips.horizontalScrollBar()
TSDs = list(self.CHIPWIDGETS.keys())
if len(TSDs) == 0:

Benjamin Jakimow
committed
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
committed
step = int(float(HBar.maximum()) / (len(TSDs)+1))
HBar.setSingleStep(step)
HBar.setPageStep(step*5)
HBar.setValue(i_doi * step)

Benjamin Jakimow
committed
def showSubsetsStart(self):
D = self.ui
easting = QgsVector(D.doubleSpinBox_subset_size_x.value(), 0.0)
northing = QgsVector(0.0, D.doubleSpinBox_subset_size_y.value())
Center = QgsPoint(D.spinBox_coordinate_x.value(), D.spinBox_coordinate_y.value())
UL = Center - (easting * 0.5) + (northing * 0.5)
LR = Center + (easting * 0.5) - (northing * 0.5)
extent = QgsRectangle(UL,LR)
maxPx = int(D.spinBoxMaxPixmapSize.value())
pxSize = self.PIXMAPS.setExtent(extent, self.canvasCrs, maxPx)
allDates = self.TS.getObservationDates()
i_doi = allDates.index(centerDate)
dates_of_interest = allDates
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]
diff = set(dates_of_interest)
diff = diff.symmetric_difference(self.CHIPWIDGETS.keys())

Benjamin Jakimow
committed
cnt_chips = 0
TSDs_of_interest = list()
for date in dates_of_interest:
#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.sensorName)
textLabel = QLabel(info_label_text)
tt = [TSD.date,TSD.pathImg, TSD.pathMsk]
self.ICP.addWidget(textLabel, 0, cnt_chips)
viewList = list()
j = 1
layerRenderer = viewWidget.layerRenderer()
#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(self, TSD, layerRenderer)
imgLabel.setMinimumSize(pxSize)
imgLabel.setMaximumSize(pxSize)
imgLabel.clicked.connect(self.ua_collect_date)
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
self.ui.scrollArea_imageChip_content.update()
self.scrollToDate(centerDate)
#todo: start pixmap loading
#define render jobs
#(TSD, [renderers] in order of views)
LUT_RENDERER = {}
for sensor in view.Sensors.keys():
if sensor not in LUT_RENDERER.keys():
LUT_RENDERER[sensor] = []
LUT_RENDERER[sensor].append(
for TSD in TSDs_of_interest:
for i, r in enumerate(LUT_RENDERER[TSD.sensor]):
jobs.append(RenderJob(TSD, r.clone(), destinationId=i))
#oder jobs by distance to DOI
jobs = sorted(jobs, key = lambda j: abs(j.TSD.date - doiTSD.date))
#todo: recycling to save loading time
self.PIXMAPS.loadSubsets(jobs)
def showSubset(self, renderJob, pixmap):
assert isinstance(renderJob, RenderJob)
chipLabel = self.CHIPWIDGETS[renderJob.TSD][renderJob.destinationId]
chipLabel.setPixmap(pixmap)
chipLabel.setFixedSize(pixmap.size())
chipLabel.update()
s = ""
def ua_collect_date(self, ICL, event):
if self.ui.rb_labeling_activate.isChecked():
txt = self.ui.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:
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.ui.tb_labeling_text.setText(txt)
def clearLayoutWidgets(self, L):
if L is not None:
while L.count():
w = L.takeAt(0)
if w.widget():
w.widget().deleteLater()

Benjamin Jakimow
committed
QApplication.processEvents()
def ua_addTSImages(self, files=None):
if files is None:
files = QFileDialog.getOpenFileNames()
if files:
M = self.ui.tableView_TimeSeries.model()
M.beginResetModel()
self.TS.addFiles(files)
M.endResetModel()
M = self.ui.tableView_TimeSeries.model()
M.beginResetModel()
self.TS.clear()
M.endResetModel()
def removeTimeSeriesDates(self, TSDs=None):
if TSDs is None:
TSDs = self.getSelectedTSDs()
assert isinstance(TSDs,list)
M = self.ui.tableView_TimeSeries.model()
self.TS.removeDates(TSDs)
def getSelectedTSDs(self):
TV = self.ui.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
def showRGBData(data):
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)
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)
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
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')
range_r = [0,500]
range_g = [0,500]
range_b = [0,500]
bands = [3,2,1]
#chipData = TSD.readSpatialChip(bb,bands=bands )
#main.addNumpy(getChip3d(chipData, bands, (range_r, range_g, range_b)))
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)
app=PyQt4.Qt.QApplication([])
dirSrcLS = r'\\141.20.140.107\NAS_Processing\SenseCarbonProcessing\BJ_NOC\01_RasterData\02_CuttedVRT'
dirSrcRE = r'\\141.20.140.91\SAN_RSDBrazil\RapidEye\3A_VRTs'
filesImgRE = file_search(dirSrcRE, '*.vrt', recursive=True)
#filesMsk = file_search(dirSrc, '2014*_Msk.vrt')
S.ua_addTSImages(files=filesImgLS[0:2])
S.ua_addTSImages(files=filesImgRE[0:2])
#S.ua_addTSImages(files=filesImgLS)
#S.ua_addTSImages(files=filesImgRE)
#S.ua_addTSMasks(files=filesMsk)
#S.ua_addView(bands=[4,5,3])
if False:
import qgis.core
# supply path to where is your qgis installed
#QgsApplication.setPrefixPath("/Applications/QGIS_2.12.app/Contents/MacOS/QGIS", True)
# load providers
QgsApplication.initQgis()
a = QgsApplication([], True)
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')
S.ua_addTSImages(files=filesImgLS)
S.ua_addTSMasks(files=filesMsk)
if __name__ == '__main__':