Пример #1
0
    def run(self):
        # create a maptool to select a point feature from the canvas
        if not self.featFinder:
            from MapTools import FeatureFinder
            self.featFinder = FeatureFinder(self.iface.mapCanvas())
            self.featFinder.setAction(self.action)
            QObject.connect(self.featFinder, SIGNAL("pointEmitted"),
                            self.onPointClicked)

        # enable the maptool and set a message in the status bar
        self.featFinder.startCapture()
        self.iface.mainWindow().statusBar().showMessage(
            u"Click on a point feature in canvas")
Пример #2
0
	def run(self):
		# create a maptool to select a point feature from the canvas
		if not self.featFinder:
			from MapTools import FeatureFinder
			self.featFinder = FeatureFinder(self.iface.mapCanvas())
			self.featFinder.setAction( self.action )
			QObject.connect(self.featFinder, SIGNAL( "pointEmitted" ), self.onPointClicked)

		# enable the maptool and set a message in the status bar 
		self.featFinder.startCapture()
		self.iface.mainWindow().statusBar().showMessage( u"Click on a point feature in canvas" )
Пример #3
0
class PSTimeSeries_Plugin:
    def __init__(self, iface):
        self.iface = iface
        self.featFinder = None

        # used to know where to ask for a new time-series tablename
        self.last_ps_layerid = None
        self.ts_tablename = None

    def initGui(self):
        # create the actions
        self.action = QAction(QIcon(":/pstimeseries_plugin/icons/logo"),
                              "PS Time Series Viewer", self.iface.mainWindow())
        QObject.connect(self.action, SIGNAL("triggered()"), self.run)
        self.action.setCheckable(True)

        self.aboutAction = QAction(QIcon(":/pstimeseries_plugin/icons/about"),
                                   "About", self.iface.mainWindow())
        QObject.connect(self.aboutAction, SIGNAL("triggered()"), self.about)

        # add actions to toolbars and menus
        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu("&Permanent Scatterers", self.action)
        #self.iface.addPluginToMenu( "&Permanent Scatterers", self.aboutAction )

    def unload(self):
        # remove actions from toolbars and menus
        self.iface.removeToolBarIcon(self.action)
        self.iface.removePluginMenu("&Permanent Scatterers", self.action)
        #self.iface.removePluginMenu( "&Permanent Scatterers", self.aboutAction )

    def about(self):
        """ display the about dialog """
        from about_dlg import AboutDlg
        dlg = AboutDlg(self.iface.mainWindow())
        dlg.exec_()

    def run(self):
        # create a maptool to select a point feature from the canvas
        if not self.featFinder:
            from MapTools import FeatureFinder
            self.featFinder = FeatureFinder(self.iface.mapCanvas())
            self.featFinder.setAction(self.action)
            QObject.connect(self.featFinder, SIGNAL("pointEmitted"),
                            self.onPointClicked)

        # enable the maptool and set a message in the status bar
        self.featFinder.startCapture()
        self.iface.mainWindow().statusBar().showMessage(
            u"Click on a point feature in canvas")

    def onPointClicked(self, point):
        layer = self.iface.activeLayer()
        if not layer or layer.type(
        ) != QgsMapLayer.VectorLayer or layer.geometryType() != QGis.Point:
            QMessageBox.information(self.iface.mainWindow(),
                                    "PS Time Series Viewer",
                                    u"Select a vector layer and try again.")
            return

        # set the waiting cursor
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        try:
            dlg = self._onPointClicked(layer, point)
        finally:
            # restore the cursor
            QApplication.restoreOverrideCursor()

        if dlg:
            dlg.exec_()

        self.run()

    def _onPointClicked(self, ps_layer, point):
        # get the id of the point feature under the mouse click
        from .MapTools import FeatureFinder
        fid = FeatureFinder.findAtPoint(ps_layer,
                                        point,
                                        canvas=self.iface.mapCanvas(),
                                        onlyTheClosestOne=True,
                                        onlyIds=True)
        if fid is None:
            return

        # get the attribute map of the selected feature
        feat = QgsFeature()
        ps_layer.featureAtId(fid, feat, False)
        attrs = feat.attributeMap()

        x, y = [], []  # lists containg x,y values
        infoFields = {
        }  # hold the index->name of the fields containing info to be displayed

        ps_source = ps_layer.source()
        ps_fields = ps_layer.dataProvider().fields()

        providerType = ps_layer.providerType()
        uri = QString(ps_source)
        subset = ""

        if providerType == 'ogr' and ps_source.endsWith(
                ".shp", Qt.CaseInsensitive):
            # Shapefile
            for idx, fld in ps_fields.iteritems():
                if QRegExp("D\\d{8}", Qt.CaseInsensitive).indexIn(
                        fld.name()) < 0:
                    # info fields are all except those containing dates
                    infoFields[idx] = fld
                else:
                    x.append(
                        QDate.fromString(fld.name()[1:],
                                         "yyyyMMdd").toPyDate())
                    y.append(attrs[idx].toDouble()[0])

        elif providerType == 'ogr' and (ps_source.startsWith(
                "OCI:", Qt.CaseInsensitive) or ps_source.endsWith(
                    ".vrt", Qt.CaseInsensitive)):  # Oracle Spatial

            # fields containing values
            dateField = "data_misura"
            valueField = "spost_rel_mm"
            infoFields = ps_fields

            # search for the id_dataset and code_target fields needed to join
            # PS and TS tables
            idDataset = codeTarget = None
            for idx, fld in ps_fields.iteritems():
                if fld.name().toLower() == "id_dataset":
                    idDataset = attrs[idx].toString()
                if fld.name().toLower() == "code_target":
                    codeTarget = attrs[idx].toString()

            if idDataset is None or codeTarget is None:
                QgsMessageLog.logMessage(
                    u"idDataset is %s, codeTarget is %s. Exiting" %
                    (idDataset, codeTarget), "PSTimeSeriesViewer")
                return
            subset = u"id_dataset='%s' AND code_target='%s'" % (idDataset,
                                                                codeTarget)

            # create the uri
            if ps_source.startsWith("OCI:", Qt.CaseInsensitive):
                default_tbl_name = "RISKNAT.RNAT_TARGET_SSTO"
            elif ps_source.endsWith(".vrt", Qt.CaseInsensitive):
                default_tbl_name = "rnat_target_sso.vrt"
            else:
                default_tbl_name = ""
            if not self._askTStablename(ps_layer, default_tbl_name):
                return

            if ps_source.startsWith("OCI:", Qt.CaseInsensitive):
                # uri is like OCI:userid/password@database:table
                pos = uri.indexOf(':', 4)
                if pos >= 0:
                    uri = uri[0:pos]
                uri = u"%s:%s" % (uri, self.ts_tablename)
            else:
                # it's a VRT file
                uri = u"%s/%s" % (QFileInfo(ps_source).path(),
                                  self.ts_tablename)
                uri = QDir.toNativeSeparators(uri)

            # load the layer containing time series
            ts_layer = self._createTSlayer(uri, providerType, subset)
            if ts_layer is None:
                return

            # get time series X and Y values
            try:
                x, y = self._getXYvalues(ts_layer, dateField, valueField)
            finally:
                ts_layer.deleteLater()
                del ts_layer

        elif providerType in ['postgres',
                              'spatialite']:  # either PostGIS or SpatiaLite

            # fields containing values
            dateField = "dataripresa"
            valueField = "valore"
            infoFields = ps_fields

            # search for the id_dataset and code_target fields needed to join
            # PS and TS tables
            code = None
            for idx, fld in ps_fields.iteritems():
                if fld.name().toLower() == "code":
                    code = attrs[idx].toString()

            if code is None:
                QgsMessageLog.logMessage(u"code is None. Exiting" % code,
                                         "PSTimeSeriesViewer")
                return
            subset = u"code='%s'" % code

            # create the uri
            dsuri = QgsDataSourceURI(ps_layer.source())
            default_tbl_name = u"ts_%s" % dsuri.table()
            if not self._askTStablename(ps_layer, default_tbl_name):
                return
            dsuri.setDataSource(dsuri.schema(), self.ts_tablename, QString())
            uri = dsuri.uri()

            # load the layer containing time series
            ts_layer = self._createTSlayer(uri, providerType, subset)
            if ts_layer is None:
                return

            # get time series X and Y values
            try:
                x, y = self._getXYvalues(ts_layer, dateField, valueField)
            finally:
                ts_layer.deleteLater()
                del ts_layer

        if len(x) * len(y) <= 0:
            QMessageBox.warning(
                self.iface.mainWindow(), "PS Time Series Viewer",
                u"No time series values found for the selected point.")
            QgsMessageLog.logMessage(
                u"provider: %s - uri: %s\nsubset: %s" %
                (providerType, uri, subset), "PSTimeSeriesViewer")
            return

        # display the plot dialog
        from .pstimeseries_dlg import PSTimeSeries_Dlg
        dlg = PSTimeSeries_Dlg(ps_layer, infoFields)
        dlg.setFeatureId(fid)
        dlg.setData(x, y)
        return dlg

    def _getXYvalues(self, ts_layer, dateField, valueField):
        # utility function used to get the X and Y values
        x, y = [], []

        # get indexes of date (x) and value (y) fields
        dateIdx, valueIdx = None, None
        for idx, fld in ts_layer.dataProvider().fields().iteritems():
            if fld.name().toLower() == dateField:
                dateIdx = idx
            elif fld.name().toLower() == valueField:
                valueIdx = idx

        if dateIdx is None or valueIdx is None:
            QgsMessageLog.logMessage(
                u"field %s -> index %s, field %s -> index %s. Exiting" %
                (dateField, dateIdx, valueField, valueIdx),
                "PSTimeSeriesViewer")
            return

        # fetch and loop through all the features
        ts_layer.select([dateIdx, valueIdx], QgsRectangle(), False)
        f = QgsFeature()
        while ts_layer.nextFeature(f):
            # get x and y values
            a = f.attributeMap()
            x.append(
                QDate.fromString(a[dateIdx].toString(), "yyyyMMdd").toPyDate())
            y.append(a[valueIdx].toDouble()[0])

        return x, y

    def _askTStablename(self, ps_layer, default_tblname=None):
        # utility function used to ask to the user the name of the table
        # containing time series data
        if default_tblname is None:
            default_tblname = ""

        # ask a tablename to the user
        if ps_layer.id() != self.last_ps_layerid or not self.ts_tablename:
            tblname, ok = QInputDialog.getText(
                self.iface.mainWindow(),
                "PS Time Series Viewer",
                "Insert the name of the table containing time-series",
                text=default_tblname)
            if not ok:
                return False

            self.ts_tablename = tblname
            self.last_ps_layerid = ps_layer.id()

        return True

    def _createTSlayer(self, uri, providerType, subset=None):
        # utility function used to create the vector layer containing time
        # series data
        layer = QgsVectorLayer(uri, "time_series_layer", providerType)
        if not layer.isValid():
            QMessageBox.warning(
                self.iface.mainWindow(), "PS Time Series Viewer",
                u"The layer '%s' wasn't found." % self.ts_tablename)
            self.ts_tablename = None
            return

        if subset is not None:
            layer.setSubsetString(subset)

        return layer
Пример #4
0
    def _onPointClicked(self, ps_layer, point):
        # get the id of the point feature under the mouse click
        from .MapTools import FeatureFinder
        fid = FeatureFinder.findAtPoint(ps_layer,
                                        point,
                                        canvas=self.iface.mapCanvas(),
                                        onlyTheClosestOne=True,
                                        onlyIds=True)
        if fid is None:
            return

        # get the attribute map of the selected feature
        feat = QgsFeature()
        ps_layer.featureAtId(fid, feat, False)
        attrs = feat.attributeMap()

        x, y = [], []  # lists containg x,y values
        infoFields = {
        }  # hold the index->name of the fields containing info to be displayed

        ps_source = ps_layer.source()
        ps_fields = ps_layer.dataProvider().fields()

        providerType = ps_layer.providerType()
        uri = QString(ps_source)
        subset = ""

        if providerType == 'ogr' and ps_source.endsWith(
                ".shp", Qt.CaseInsensitive):
            # Shapefile
            for idx, fld in ps_fields.iteritems():
                if QRegExp("D\\d{8}", Qt.CaseInsensitive).indexIn(
                        fld.name()) < 0:
                    # info fields are all except those containing dates
                    infoFields[idx] = fld
                else:
                    x.append(
                        QDate.fromString(fld.name()[1:],
                                         "yyyyMMdd").toPyDate())
                    y.append(attrs[idx].toDouble()[0])

        elif providerType == 'ogr' and (ps_source.startsWith(
                "OCI:", Qt.CaseInsensitive) or ps_source.endsWith(
                    ".vrt", Qt.CaseInsensitive)):  # Oracle Spatial

            # fields containing values
            dateField = "data_misura"
            valueField = "spost_rel_mm"
            infoFields = ps_fields

            # search for the id_dataset and code_target fields needed to join
            # PS and TS tables
            idDataset = codeTarget = None
            for idx, fld in ps_fields.iteritems():
                if fld.name().toLower() == "id_dataset":
                    idDataset = attrs[idx].toString()
                if fld.name().toLower() == "code_target":
                    codeTarget = attrs[idx].toString()

            if idDataset is None or codeTarget is None:
                QgsMessageLog.logMessage(
                    u"idDataset is %s, codeTarget is %s. Exiting" %
                    (idDataset, codeTarget), "PSTimeSeriesViewer")
                return
            subset = u"id_dataset='%s' AND code_target='%s'" % (idDataset,
                                                                codeTarget)

            # create the uri
            if ps_source.startsWith("OCI:", Qt.CaseInsensitive):
                default_tbl_name = "RISKNAT.RNAT_TARGET_SSTO"
            elif ps_source.endsWith(".vrt", Qt.CaseInsensitive):
                default_tbl_name = "rnat_target_sso.vrt"
            else:
                default_tbl_name = ""
            if not self._askTStablename(ps_layer, default_tbl_name):
                return

            if ps_source.startsWith("OCI:", Qt.CaseInsensitive):
                # uri is like OCI:userid/password@database:table
                pos = uri.indexOf(':', 4)
                if pos >= 0:
                    uri = uri[0:pos]
                uri = u"%s:%s" % (uri, self.ts_tablename)
            else:
                # it's a VRT file
                uri = u"%s/%s" % (QFileInfo(ps_source).path(),
                                  self.ts_tablename)
                uri = QDir.toNativeSeparators(uri)

            # load the layer containing time series
            ts_layer = self._createTSlayer(uri, providerType, subset)
            if ts_layer is None:
                return

            # get time series X and Y values
            try:
                x, y = self._getXYvalues(ts_layer, dateField, valueField)
            finally:
                ts_layer.deleteLater()
                del ts_layer

        elif providerType in ['postgres',
                              'spatialite']:  # either PostGIS or SpatiaLite

            # fields containing values
            dateField = "dataripresa"
            valueField = "valore"
            infoFields = ps_fields

            # search for the id_dataset and code_target fields needed to join
            # PS and TS tables
            code = None
            for idx, fld in ps_fields.iteritems():
                if fld.name().toLower() == "code":
                    code = attrs[idx].toString()

            if code is None:
                QgsMessageLog.logMessage(u"code is None. Exiting" % code,
                                         "PSTimeSeriesViewer")
                return
            subset = u"code='%s'" % code

            # create the uri
            dsuri = QgsDataSourceURI(ps_layer.source())
            default_tbl_name = u"ts_%s" % dsuri.table()
            if not self._askTStablename(ps_layer, default_tbl_name):
                return
            dsuri.setDataSource(dsuri.schema(), self.ts_tablename, QString())
            uri = dsuri.uri()

            # load the layer containing time series
            ts_layer = self._createTSlayer(uri, providerType, subset)
            if ts_layer is None:
                return

            # get time series X and Y values
            try:
                x, y = self._getXYvalues(ts_layer, dateField, valueField)
            finally:
                ts_layer.deleteLater()
                del ts_layer

        if len(x) * len(y) <= 0:
            QMessageBox.warning(
                self.iface.mainWindow(), "PS Time Series Viewer",
                u"No time series values found for the selected point.")
            QgsMessageLog.logMessage(
                u"provider: %s - uri: %s\nsubset: %s" %
                (providerType, uri, subset), "PSTimeSeriesViewer")
            return

        # display the plot dialog
        from .pstimeseries_dlg import PSTimeSeries_Dlg
        dlg = PSTimeSeries_Dlg(ps_layer, infoFields)
        dlg.setFeatureId(fid)
        dlg.setData(x, y)
        return dlg
Пример #5
0
class PSTimeSeries_Plugin:

	def __init__(self, iface):
		self.iface = iface
		self.featFinder = None

		# used to know where to ask for a new time-series tablename
		self.last_ps_layerid = None
		self.ts_tablename = None

	def initGui(self):
		# create the actions
		self.action = QAction( QIcon( ":/pstimeseries_plugin/icons/logo" ), "PS Time Series Viewer", self.iface.mainWindow() )
		QObject.connect( self.action, SIGNAL( "triggered()" ), self.run )
		self.action.setCheckable( True )

		self.aboutAction = QAction( QIcon( ":/pstimeseries_plugin/icons/about" ), "About", self.iface.mainWindow() )
		QObject.connect( self.aboutAction, SIGNAL("triggered()"), self.about )

		# add actions to toolbars and menus
		self.iface.addToolBarIcon( self.action )
		self.iface.addPluginToMenu( "&Permanent Scatterers", self.action )
		#self.iface.addPluginToMenu( "&Permanent Scatterers", self.aboutAction )

	def unload(self):
		# remove actions from toolbars and menus
		self.iface.removeToolBarIcon( self.action )
		self.iface.removePluginMenu( "&Permanent Scatterers", self.action )
		#self.iface.removePluginMenu( "&Permanent Scatterers", self.aboutAction )


	def about(self):
		""" display the about dialog """
		from about_dlg import AboutDlg
		dlg = AboutDlg( self.iface.mainWindow() )
		dlg.exec_()

	def run(self):
		# create a maptool to select a point feature from the canvas
		if not self.featFinder:
			from MapTools import FeatureFinder
			self.featFinder = FeatureFinder(self.iface.mapCanvas())
			self.featFinder.setAction( self.action )
			QObject.connect(self.featFinder, SIGNAL( "pointEmitted" ), self.onPointClicked)

		# enable the maptool and set a message in the status bar 
		self.featFinder.startCapture()
		self.iface.mainWindow().statusBar().showMessage( u"Click on a point feature in canvas" )


	def onPointClicked(self, point):
		layer = self.iface.activeLayer()
		if not layer or layer.type() != QgsMapLayer.VectorLayer or layer.geometryType() != QGis.Point:
			QMessageBox.information(self.iface.mainWindow(), "PS Time Series Viewer", u"Select a vector layer and try again.")
			return

		# set the waiting cursor
		QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
		try:
			dlg = self._onPointClicked( layer, point )
		finally:
			# restore the cursor
			QApplication.restoreOverrideCursor()

		if dlg:
			dlg.exec_()

		self.run()


	def _onPointClicked(self, ps_layer, point):
		# get the id of the point feature under the mouse click
		from .MapTools import FeatureFinder
		fid = FeatureFinder.findAtPoint(ps_layer, point, canvas=self.iface.mapCanvas(), onlyTheClosestOne=True, onlyIds=True)
		if fid is None:
			return

		# get the attribute map of the selected feature
		feat = QgsFeature()
		ps_layer.featureAtId( fid, feat, False )
		attrs = feat.attributeMap()

		x, y = [], []	# lists containg x,y values
		infoFields = {}	# hold the index->name of the fields containing info to be displayed

		ps_source = ps_layer.source()
		ps_fields = ps_layer.dataProvider().fields()

		providerType = ps_layer.providerType()
		uri = QString(ps_source)
		subset = ""

		if providerType == 'ogr' and ps_source.endsWith( ".shp", Qt.CaseInsensitive ):
			# Shapefile
			for idx, fld in ps_fields.iteritems():
				if QRegExp( "D\\d{8}", Qt.CaseInsensitive ).indexIn( fld.name() ) < 0:
					# info fields are all except those containing dates
					infoFields[ idx ] = fld
				else:
					x.append( QDate.fromString( fld.name()[1:], "yyyyMMdd" ).toPyDate() )
					y.append( attrs[ idx ].toDouble()[0] )

		elif providerType == 'ogr' and (ps_source.startsWith("OCI:", Qt.CaseInsensitive) or ps_source.endsWith(".vrt", Qt.CaseInsensitive)):	# Oracle Spatial

			# fields containing values
			dateField = "data_misura"
			valueField = "spost_rel_mm"
			infoFields = ps_fields

			# search for the id_dataset and code_target fields needed to join 
			# PS and TS tables
			idDataset = codeTarget = None
			for idx, fld in ps_fields.iteritems():
				if fld.name().toLower() == "id_dataset":
					idDataset = attrs[ idx ].toString()
				if fld.name().toLower() == "code_target":
					codeTarget = attrs[ idx ].toString()

			if idDataset is None or codeTarget is None:
				QgsMessageLog.logMessage( u"idDataset is %s, codeTarget is %s. Exiting" % (idDataset, codeTarget), "PSTimeSeriesViewer" )
				return
			subset = u"id_dataset='%s' AND code_target='%s'" % (idDataset, codeTarget)

			# create the uri
			if ps_source.startsWith( "OCI:", Qt.CaseInsensitive ):
				default_tbl_name = "RISKNAT.RNAT_TARGET_SSTO"
			elif ps_source.endsWith(".vrt", Qt.CaseInsensitive):
				default_tbl_name = "rnat_target_sso.vrt"
			else:
				default_tbl_name = ""
			if not self._askTStablename( ps_layer,  default_tbl_name ):
				return

			if ps_source.startsWith( "OCI:", Qt.CaseInsensitive ):
				# uri is like OCI:userid/password@database:table
				pos = uri.indexOf(':', 4)
				if pos >= 0:
					uri = uri[0:pos]
				uri = u"%s:%s" % (uri, self.ts_tablename)
			else:
				# it's a VRT file
				uri = u"%s/%s" % (QFileInfo(ps_source).path(), self.ts_tablename)
				uri = QDir.toNativeSeparators( uri )

			# load the layer containing time series
			ts_layer = self._createTSlayer( uri, providerType, subset )
			if ts_layer is None:
				return

			# get time series X and Y values
			try:
				x, y = self._getXYvalues( ts_layer, dateField, valueField )
			finally:
				ts_layer.deleteLater()
				del ts_layer

		elif providerType in ['postgres', 'spatialite']:# either PostGIS or SpatiaLite

			# fields containing values
			dateField = "dataripresa"
			valueField = "valore"
			infoFields = ps_fields

			# search for the id_dataset and code_target fields needed to join 
			# PS and TS tables
			code = None
			for idx, fld in ps_fields.iteritems():
				if fld.name().toLower() == "code":
					code = attrs[ idx ].toString()

			if code is None:
				QgsMessageLog.logMessage( u"code is None. Exiting" % code, "PSTimeSeriesViewer" )
				return
			subset = u"code='%s'" % code

			# create the uri
			dsuri = QgsDataSourceURI( ps_layer.source() )
			default_tbl_name = u"ts_%s" % dsuri.table()
			if not self._askTStablename( ps_layer,  default_tbl_name ):
				return
			dsuri.setDataSource( dsuri.schema(), self.ts_tablename, QString() )
			uri = dsuri.uri()

			# load the layer containing time series
			ts_layer = self._createTSlayer( uri, providerType, subset )
			if ts_layer is None:
				return

			# get time series X and Y values
			try:
				x, y = self._getXYvalues( ts_layer, dateField, valueField )
			finally:
				ts_layer.deleteLater()
				del ts_layer

		if len(x) * len(y) <= 0:
			QMessageBox.warning( self.iface.mainWindow(), 
					"PS Time Series Viewer", 
					u"No time series values found for the selected point." )
			QgsMessageLog.logMessage( u"provider: %s - uri: %s\nsubset: %s" % (providerType, uri, subset), "PSTimeSeriesViewer" )
			return
			
		# display the plot dialog
		from .pstimeseries_dlg import PSTimeSeries_Dlg
		dlg = PSTimeSeries_Dlg( ps_layer, infoFields )
		dlg.setFeatureId( fid )
		dlg.setData( x, y )
		return dlg



	def _getXYvalues(self, ts_layer, dateField, valueField):
		# utility function used to get the X and Y values
		x, y = [], []

		# get indexes of date (x) and value (y) fields
		dateIdx, valueIdx = None, None
		for idx, fld in ts_layer.dataProvider().fields().iteritems():
			if fld.name().toLower() == dateField:
				dateIdx = idx
			elif fld.name().toLower() == valueField:
				valueIdx = idx

		if dateIdx is None or valueIdx is None:
			QgsMessageLog.logMessage(u"field %s -> index %s, field %s -> index %s. Exiting" % (dateField, dateIdx, valueField, valueIdx), "PSTimeSeriesViewer")
			return

		# fetch and loop through all the features
		ts_layer.select( [dateIdx, valueIdx], QgsRectangle(), False )
		f = QgsFeature()
		while ts_layer.nextFeature( f ):
			# get x and y values
			a = f.attributeMap()
			x.append( QDate.fromString( a[ dateIdx ].toString(), "yyyyMMdd" ).toPyDate() )
			y.append( a[ valueIdx ].toDouble()[0] )

		return x, y

	def _askTStablename(self, ps_layer, default_tblname=None):
		# utility function used to ask to the user the name of the table
		# containing time series data
		if default_tblname is None:
			default_tblname = ""

		# ask a tablename to the user
		if ps_layer.id() != self.last_ps_layerid or not self.ts_tablename:
			tblname, ok = QInputDialog.getText( self.iface.mainWindow(), 
					"PS Time Series Viewer", 
					"Insert the name of the table containing time-series", 
					text=default_tblname )
			if not ok:
				return False

			self.ts_tablename = tblname
			self.last_ps_layerid = ps_layer.id()

		return True

	def _createTSlayer(self, uri, providerType, subset=None):
		# utility function used to create the vector layer containing time 
		# series data
		layer = QgsVectorLayer( uri, "time_series_layer", providerType )
		if not layer.isValid():
			QMessageBox.warning( self.iface.mainWindow(), 
					"PS Time Series Viewer", 
					u"The layer '%s' wasn't found." % self.ts_tablename )
			self.ts_tablename = None
			return

		if subset is not None:
			layer.setSubsetString( subset )

		return layer
Пример #6
0
	def _onPointClicked(self, ps_layer, point):
		# get the id of the point feature under the mouse click
		from .MapTools import FeatureFinder
		fid = FeatureFinder.findAtPoint(ps_layer, point, canvas=self.iface.mapCanvas(), onlyTheClosestOne=True, onlyIds=True)
		if fid is None:
			return

		# get the attribute map of the selected feature
		feat = QgsFeature()
		ps_layer.featureAtId( fid, feat, False )
		attrs = feat.attributeMap()

		x, y = [], []	# lists containg x,y values
		infoFields = {}	# hold the index->name of the fields containing info to be displayed

		ps_source = ps_layer.source()
		ps_fields = ps_layer.dataProvider().fields()

		providerType = ps_layer.providerType()
		uri = QString(ps_source)
		subset = ""

		if providerType == 'ogr' and ps_source.endsWith( ".shp", Qt.CaseInsensitive ):
			# Shapefile
			for idx, fld in ps_fields.iteritems():
				if QRegExp( "D\\d{8}", Qt.CaseInsensitive ).indexIn( fld.name() ) < 0:
					# info fields are all except those containing dates
					infoFields[ idx ] = fld
				else:
					x.append( QDate.fromString( fld.name()[1:], "yyyyMMdd" ).toPyDate() )
					y.append( attrs[ idx ].toDouble()[0] )

		elif providerType == 'ogr' and (ps_source.startsWith("OCI:", Qt.CaseInsensitive) or ps_source.endsWith(".vrt", Qt.CaseInsensitive)):	# Oracle Spatial

			# fields containing values
			dateField = "data_misura"
			valueField = "spost_rel_mm"
			infoFields = ps_fields

			# search for the id_dataset and code_target fields needed to join 
			# PS and TS tables
			idDataset = codeTarget = None
			for idx, fld in ps_fields.iteritems():
				if fld.name().toLower() == "id_dataset":
					idDataset = attrs[ idx ].toString()
				if fld.name().toLower() == "code_target":
					codeTarget = attrs[ idx ].toString()

			if idDataset is None or codeTarget is None:
				QgsMessageLog.logMessage( u"idDataset is %s, codeTarget is %s. Exiting" % (idDataset, codeTarget), "PSTimeSeriesViewer" )
				return
			subset = u"id_dataset='%s' AND code_target='%s'" % (idDataset, codeTarget)

			# create the uri
			if ps_source.startsWith( "OCI:", Qt.CaseInsensitive ):
				default_tbl_name = "RISKNAT.RNAT_TARGET_SSTO"
			elif ps_source.endsWith(".vrt", Qt.CaseInsensitive):
				default_tbl_name = "rnat_target_sso.vrt"
			else:
				default_tbl_name = ""
			if not self._askTStablename( ps_layer,  default_tbl_name ):
				return

			if ps_source.startsWith( "OCI:", Qt.CaseInsensitive ):
				# uri is like OCI:userid/password@database:table
				pos = uri.indexOf(':', 4)
				if pos >= 0:
					uri = uri[0:pos]
				uri = u"%s:%s" % (uri, self.ts_tablename)
			else:
				# it's a VRT file
				uri = u"%s/%s" % (QFileInfo(ps_source).path(), self.ts_tablename)
				uri = QDir.toNativeSeparators( uri )

			# load the layer containing time series
			ts_layer = self._createTSlayer( uri, providerType, subset )
			if ts_layer is None:
				return

			# get time series X and Y values
			try:
				x, y = self._getXYvalues( ts_layer, dateField, valueField )
			finally:
				ts_layer.deleteLater()
				del ts_layer

		elif providerType in ['postgres', 'spatialite']:# either PostGIS or SpatiaLite

			# fields containing values
			dateField = "dataripresa"
			valueField = "valore"
			infoFields = ps_fields

			# search for the id_dataset and code_target fields needed to join 
			# PS and TS tables
			code = None
			for idx, fld in ps_fields.iteritems():
				if fld.name().toLower() == "code":
					code = attrs[ idx ].toString()

			if code is None:
				QgsMessageLog.logMessage( u"code is None. Exiting" % code, "PSTimeSeriesViewer" )
				return
			subset = u"code='%s'" % code

			# create the uri
			dsuri = QgsDataSourceURI( ps_layer.source() )
			default_tbl_name = u"ts_%s" % dsuri.table()
			if not self._askTStablename( ps_layer,  default_tbl_name ):
				return
			dsuri.setDataSource( dsuri.schema(), self.ts_tablename, QString() )
			uri = dsuri.uri()

			# load the layer containing time series
			ts_layer = self._createTSlayer( uri, providerType, subset )
			if ts_layer is None:
				return

			# get time series X and Y values
			try:
				x, y = self._getXYvalues( ts_layer, dateField, valueField )
			finally:
				ts_layer.deleteLater()
				del ts_layer

		if len(x) * len(y) <= 0:
			QMessageBox.warning( self.iface.mainWindow(), 
					"PS Time Series Viewer", 
					u"No time series values found for the selected point." )
			QgsMessageLog.logMessage( u"provider: %s - uri: %s\nsubset: %s" % (providerType, uri, subset), "PSTimeSeriesViewer" )
			return
			
		# display the plot dialog
		from .pstimeseries_dlg import PSTimeSeries_Dlg
		dlg = PSTimeSeries_Dlg( ps_layer, infoFields )
		dlg.setFeatureId( fid )
		dlg.setData( x, y )
		return dlg