[Qgis-developer] Re: Raster layer display control from Plugin
Peter Ersts
ersts at amnh.org
Tue Sep 7 11:49:01 EDT 2010
JP,
In version 1.5 the python bindings were not correct. Python could not
use the computeMinMaxFormLastExtent(int, double*) so the new method
computeMinMaxFromLastExtent(int, double, double) was added.
Since you are running on windows, you could install the "nighly-build"
QGIS package which would give you the developers version 1.6 and would
not require you or your professor to compile manually. This would have
all of the updated python bindings and newest methods mentioned in the
responses.
-pete
On 09/07/2010 11:04 AM, JP Glutting wrote:
> No, sorry, my mistake, I was mixing up the documentation.
> computeMinMaxFromLastExtent doesn't seem to be available at all in 1.5.
>
> However, when I use computeMinMaxFromLastExtent(int), the interpreter
> does not complain, but does nothing. When I
> try computeMinMaxFromLastExtent(int, double), I get the following error:
>
> TypeError: QgsRasterLayer.computeMinimumMaximumFromLastExtent():
> arguments did not match any overloaded call:
> overload 1: too many arguments
> overload 2: argument 1 has unexpected type 'int'
>
>
> In any case, it appears that I am out of my depth with this, and
> should probably avoid using this function until it makes it into the
> stable version.
>
>
> Cheers,
>
> JP
>
>
> On Tue, Sep 7, 2010 at 4:51 PM, JP Glutting <jpglutting at gmail.com
> <mailto:jpglutting at gmail.com>> wrote:
>
> Hi Pete,
>
> Thanks for the clarification. I am doing a bit of creative
> interpretation of the QGIS API for python, as I am only passingly
> familiar with C++. It never occurred to me that passing a
> parameter to a function would change change its value (or declare
> it). If I am interpreting you correctly, by passing minVal to
> computeMinimumMaximumFromLastExtent (in QGIS 1.6), that variable
> would be created with the actual minimum value of the extent.
> Interesting. (When I said "set", I meant register them in some
> place, where they could be accessed by something like
> resultsLayer.minimumValue(). My understanding was that the actual
> minimum and maximum values were not calculated initially to save
> computing power, so that computeMinimumMaximumFromLastExtent was
> actually determining a value, which was then recorded ("set")
> somewhere.
>
> I was aware of setMinimumMaximumFromLastExtent() and how it works,
> so the error was mine in muddling the two terms.
>
> I am using QGIS 1.5 (on OS X and Win7) using python 2.6, so these
> may not work for me. Since I am submitting this project for a
> class, and we are encouraged to make our plugin with the basic
> functionality of the packages involved, I would guess that asking
> my professors to compile from the SVN trunk in order to grade my
> assignment would not make a very good impression on them. So I
> will just stick to the 1.5 functionality, I guess.
>
> To see if I have my ideas clear, my understanding from the
> documentation is that the only version
> of computeMinimumMaximumFromLastExtent which is new to 1.6
> is computeMinimumMaximumFromLastExtent(int band, double min,
> double max) [the one you are talking about]. A similar
> function computeMinimumMaximumFromLastExtent(int, double
> theMinMax) seems to be available, although I was under the
> impression that the function accepted a parameter of the
> *estimated* minmax from another function. I am guessing that the
> correct idea is that, after calling this function, "theMinMax"
> holds the two values (or estimates, according to the
> documentation), although I am also unclear on how a single double
> holds two values, exactly.
>
> I am going to fiddle around with the code a little and see if I
> can understand this better.
>
> Thanks for all the info,
> JP
>
> On Tue, Sep 7, 2010 at 3:42 PM, Peter Ersts <ersts at amnh.org
> <mailto:ersts at amnh.org>> wrote:
>
> JP,
>
> the computeMinimumMaximumFromLastExtent() methods _do not set_
> minimum and maximum values, they return them for you to use
> how you want. Using your variables names from below, you would
> want to use:
>
> resultsLayer.computeMinimumMaximumFromLastExtent( band,
> minVal, maxVal )
>
> After this call, your local variables minVal and maxVal would
> have values of 0 and 1 respectively. There is another
> convenience function called
> setMinimumMaximumUsingLastExtent(). This will _set_ the
> internal minimum maximum values of the band(s) currently being
> displayed.
>
> However, you have not indicated which version of QGIS you are
> using, so both of these functions that I have mentioned may no
> be available to you. You would need to be compiling QGIS from
> the svn trunk (v1.6) to have access to these two functions.
>
> -pete
>
>
> On 09/07/2010 08:33 AM, JP Glutting wrote:
>> Hi Peter,
>>
>> Thanks for the response. Sorry if I wasn't clear - there was
>> no real question at this point, I was just following up on my
>> previous question with the resolution of the problem, mostly
>> for the users list, and I copied the message to the
>> developers list as well, just for completeness.
>>
>> However, the information about when and how Mins and Maxes
>> can be calculated is interesting. I am not sure
>> that computeMinimumMaximumFromLastExtent is what I want - I
>> was using code form a plugin that was adjusting the color
>> scheme for the visible extent, not the whole layer (which is
>> what I want to do). Where does it store the result? This code:
>>
>> QgsMapLayerRegistry.instance().addMapLayer(resultsLayer)
>> resultsLayer.triggerRepaint()
>> band =
>> resultsLayer.bandNumber(resultsLayer.grayBandName()) #Should be 1
>> minVal = resultsLayer.minimumValue(band)
>> maxVal = resultsLayer.maximumValue(band)
>> QtGui.QMessageBox.information(self, self.tr
>> <http://self.tr>("MinMax"), self.tr <http://self.tr>("Min: %s
>> Max %s:" %(minVal, maxVal)))
>> resultsLayer.computeMinimumMaximumFromLastExtent(band)
>> minVal = resultsLayer.minimumValue(band)
>> maxVal = resultsLayer.maximumValue(band)
>> QtGui.QMessageBox.information(self, self.tr
>> <http://self.tr>("MinMax"), self.tr <http://self.tr>("Min: %s
>> Max %s:" %(minVal, maxVal)))
>>
>> Produces the same values (0.0 and 255.0) for a raster with
>> values of 0 and 1 before and after
>> calling computeMinimumMaximumFromLastExtent.
>>
>> Calling this next:
>>
>> resultsLayer.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum)
>> minVal = resultsLayer.minimumValue(band)
>> maxVal = resultsLayer.maximumValue(band)
>> QtGui.QMessageBox.information(self, self.tr
>> <http://self.tr>("MinMax"), self.tr <http://self.tr>("Min: %s
>> Max %s:" %(minVal, maxVal)))
>>
>> stretches the grayscale colormap to 0 and 1, with the layer
>> properties (from the GUI) Min and Max set to 0 and 1, so I
>> assume that it is computing the real values itself, I can't
>> quite follow the internals. Without this call, the properties
>> window in the GUI shows 0 and 255 for min and max, even after
>> calling computeMinimumMaximumFromLastExtent (I can't seem to
>> find a way to figure out if this call does anything at all -
>> I can't find any values or results that indicate any effect,
>> although I am probably looking in the wrong place).
>>
>> Of course, the MessageBox continues to report 0 and 255, so I
>> not sure where the correct information is stored.
>>
>> The tip on using the PseudoColorShader was exactly what I
>> needed, thank you. I knew it was just something simple I was
>> going at wrong.
>>
>> Anyway, my plug-in works very nicely now, and I will add it
>> to the QGIS repository here in a few weeks when I hand in my
>> assignment.
>>
>> Cheers,
>> JP
>>
>> On Tue, Sep 7, 2010 at 3:12 AM, Peter Ersts <ersts at amnh.org
>> <mailto:ersts at amnh.org>> wrote:
>>
>> Howdy JP,
>>
>> Not quite sure what the question is at this stage.
>> However, here are some general comments.
>>
>> When the raster is first loaded, the min max values for
>> each band are provided by GDAL but are estimates. You
>> will not get the exact min max values until the band
>> statistics are generated, which depending on the size of
>> the image can take be slow. The raster has to be rendered
>> at least once for computeMinimumMaximumFromLastExtent()
>> to provide meaningful values.
>>
>> Re:
>>
>> "On the other hand,
>> resultsLayer.setColorShadingAlgorithm("PseudoColorShader")
>> Doesn't seem to do anything at all. Strange."
>>
>> Pseudo color shading does not just use the minimum and
>> maximum values, it requires you to define the number of
>> standard deviations to apply. Also the pseudo color
>> shader has to be used with the correct drawing style,
>> i.e., QgsRasterLayer.SingleBandPseudoColor
>>
>>
>> -pete
>>
>>
>> On 09/05/2010 10:52 AM, JP Glutting wrote:
>>> Ok, I figured this out. It was as simple as:
>>>
>>> *resultsLayer.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum)*
>>>
>>> That computes the min and max, and stretches the
>>> grayscale (to black and white for boolean rasters).
>>>
>>> In the mean time I was futzing around with:
>>>
>>> * band =
>>> resultsLayer.bandNumber(resultsLayer.grayBandName()) *
>>> * minVal = resultsLayer.minimumValue(band)*
>>> * maxVal = resultsLayer.maximumValue(band)*
>>>
>>> and
>>>
>>> * resultsLayer.setMinimumValue(band, minVal,
>>> generateLookupTableFlag)*
>>> * resultsLayer.setMaximumValue(band, maxVal,
>>> generateLookupTableFlag)*
>>>
>>> but it turns out that
>>> *resultsLayer.**setMaximumValue(band) *returns the
>>> theoretical maximum (255) rather than the real maximum
>>> (1), which is not what I wanted. You can get the correct
>>> value with
>>>
>>> * maxVal =
>>> resultsLayer.bandStatistics(band).maximumValue*
>>>
>>> However, it says that calling bandStatistics is very CPU
>>> intensive, since it also calculates a lot of other
>>> stuff. As it turns out, the StretchToMinimumMaximum
>>> algorithm seems to calculate the minmax anyway, so none
>>> of that is needed.
>>>
>>> My big mistake, as I was rushing through this, was to
>>> confuse extent and values, as I was trying to copy from
>>> a tutorial and wasn't paying close attention. Once I
>>> figured that out, it was easy.
>>>
>>> On the other hand,
>>>
>>> *resultsLayer.setColorShadingAlgorithm("PseudoColorShader")*
>>>
>>> Doesn't seem to do anything at all. Strange.
>>>
>>> Cheers,
>>> JP
>>>
>>> On Sat, Sep 4, 2010 at 6:35 PM, Benoit de Cabissole
>>> <benoit at exigesa.com <mailto:benoit at exigesa.com>> wrote:
>>>
>>> Hi JP,
>>> I would suggest asking your question on the
>>> Qgis-developer list instead of this one.
>>> Below is what I've done to display a custom colormap
>>> on a raster. Could it be adapted to your problem?
>>> # Display the raster with the selected colour table:
>>> #
>>> # - tell the layer to use a QgsColorRampShader
>>> function
>>> theLayer.setColorShadingAlgorithm(
>>> QgsRasterLayer.ColorRampShader )
>>> # - get a pointer to the raster shader function
>>> (QgsColorRampShader)
>>> myColorRampShader =
>>> theLayer.rasterShader().rasterShaderFunction()
>>> # - set parameters for the QgsColorRampShader function
>>> myColorRampShader.setColorRampType(
>>> QgsColorRampShader.DISCRETE )
>>> myColorRampShader.setColorRampItemList( theTBL )
>>> theLayer.setDrawingStyle(
>>> QgsRasterLayer.SingleBandPseudoColor )
>>> # - refresh map & legend
>>> if hasattr(theLayer, "setCacheImage"):
>>> theLayer.setCacheImage( None )
>>> theLayer.triggerRepaint()
>>>
>>> self.iface.legendInterface().refreshLayerSymbology(
>>> theLayer )
>>> # - tell QGIS that it needs to ask user to save changes
>>> self.iface.mapCanvas().setDirty( True )
>>> Cheers,
>>> Benoit
>>>
>>> -----Original Message-----
>>> *From:* qgis-user-bounces at lists.osgeo.org
>>> <mailto:qgis-user-bounces at lists.osgeo.org>
>>> [mailto:qgis-user-bounces at lists.osgeo.org
>>> <mailto:qgis-user-bounces at lists.osgeo.org>]*On
>>> Behalf Of *JP Glutting
>>> *Sent:* Saturday, 04 September 2010 17:47
>>> *To:* Qgis-user at lists.osgeo.org
>>> <mailto:Qgis-user at lists.osgeo.org>
>>> *Subject:* [Qgis-user] Re: Raster layer display
>>> control from Plugin
>>>
>>> No takers? No hints? I have been looking all
>>> over the place, and I am stuck. If it is
>>> something absurdly simple, just point me in the
>>> right direction.
>>>
>>> Any ideas?
>>>
>>> Thanks,
>>> JP
>>>
>>> On Fri, Sep 3, 2010 at 7:50 AM, JP Glutting
>>> <jpglutting at gmail.com
>>> <mailto:jpglutting at gmail.com>> wrote:
>>>
>>> Although here (http://blog.qgis.org/node/94)
>>> it seems to indicate that
>>> SingleBandPseudoColor is a constant:
>>>
>>> mypLayer->setColorRampingType(QgsRasterLayer::BLUE_GREEN_RED);
>>> mypLayer->setDrawingStyle(QgsRasterLayer::SINGLE_BAND_PSEUDO_COLOR);
>>> std::deque myLayerSet;
>>>
>>> which is what I was thinking in the first
>>> place, and here (
>>> http://doc.qgis.org/stable/classQgsRasterLayer.html#36796f1a303dac9848ba3dce3e5527dc7b7c9814c053986846b579119d2e5be9 )
>>> DrawingStyle is described as an enumerator,
>>> which seems coherent. I am not sure how to
>>> do this from Python.
>>>
>>> Cheers,
>>> JP
>>>
>>> On Fri, Sep 3, 2010 at 7:43 AM, JP Glutting
>>> <jpglutting at gmail.com
>>> <mailto:jpglutting at gmail.com>> wrote:
>>>
>>> Actually, I am not even sure that first
>>> part is the way to do it. I tried this:
>>>
>>>
>>> resultsLayer.setDrawingStyle(QtCore.QString('SingleBandPseudoColor'))
>>> resultsLayer.setCacheImage(None)
>>> resultsLayer.triggerRepaint()
>>>
>>> (passing the 'SingleBandPseudoColor'
>>> style as a string) and it makes the
>>> raster invisible. It still shows up
>>> black in the Layers Panel, but it
>>> doesn't show in the main window until
>>> you change the properties manually (and
>>> it is Grayscale when you do). It feels
>>> like I am pretty close, but I am not
>>> sure how to interpret this code from the
>>> QGIS documentation:
>>>
>>> myRasterLayer->setDrawingStyle
>>> <http://classQgsRasterLayer.html#3a923f732bedd87d0b920c5552215434>(QgsRasterLayer::SingleBandPseudoColor
>>> <http://classQgsRasterLayer.html#36796f1a303dac9848ba3dce3e5527dc7b7c9814c053986846b579119d2e5be9>);
>>>
>>> (I never learned more than the basics of
>>> C++, and that was a long time ago). The
>>> source code seems to indicate that the
>>> format needs to be passed as a string
>>> (of course, when the layer is generated):
>>>
>>> 00204QgsRasterLayer <http://classQgsRasterLayer.html>(int dummy,
>>> 00205const QString& baseName = QString(),
>>> 00206const QString& path = QString(),
>>> 00207const QString& providerLib = QString(),
>>> 00208const QStringList& layers = QStringList(),
>>> 00209const QStringList& styles = QStringList(),
>>> 00210const QString& format = QString(),
>>>
>>> 00211 const QString & crs = QString() );
>>>
>>> Thanks,
>>> JP
>>>
>>> On Fri, Sep 3, 2010 at 3:04 AM, JP
>>> Glutting <jpglutting at gmail.com
>>> <mailto:jpglutting at gmail.com>> wrote:
>>>
>>> Hello,
>>>
>>> I am working on a plugin (I
>>> mentioned it on the list earlier,
>>> but it isn't relevant to the
>>> question I have now). I have the
>>> results written to a raster file,
>>> and I need to display it. I am using
>>> this code:
>>>
>>> resultsLayer =
>>> qgis.core.QgsRasterLayer(self.query.results_file,
>>> QtCore.QFileInfo(self.query.results_file).baseName())
>>>
>>> qgis.core.QgsMapLayerRegistry.instance().addMapLayer(resultsLayer)
>>>
>>>
>>> which works fine for opening the
>>> file, but I would like to fine-tune
>>> the display so the user doesn't have
>>> to reset the properties (in my test
>>> exaple the values are 0 and 1 and
>>> the display is essentially all
>>> black). I would like to either
>>> display the results in pseudocolor
>>> directly, or in grayscale with the
>>> scale stretched to the min and max
>>> extent of the raster.
>>>
>>> I tried the psuedocolor with this code:
>>>
>>>
>>> resultsLayer.setDrawingStyle(qgis.core.QgsRasterLayer.SingleBandPseudoColor)
>>> resultsLayer.setCacheImage(None)
>>> resultsLayer.triggerRepaint()
>>>
>>> which doesn't seem to do anything at
>>> all, and I am just guessing, really.
>>>
>>> I found a nice tutorial about how to
>>> calculate the min and max extent of
>>> a raster and adjust the display here:
>>>
>>> http://linfiniti.com/2010/08/a-simple-qgis-python-tutorial/
>>>
>>> and I tried the following code:
>>>
>>> band =
>>> resultsLayer.bandNumber(resultsLayer.grayBandName())
>>> extentMin = 0.0
>>> extentMax = 0.0
>>> generateLookupTableFlag = False
>>> extentMin, extentMax =
>>> resultsLayer.computeMinimumMaximumFromLastExtent(band)
>>>
>>> resultsLayer.setMinimumValue(band,
>>> extentMin, generateLookupTableFlag)
>>>
>>> resultsLayer.setMaximumValue(band,
>>> extentMax, generateLookupTableFlag)
>>>
>>> resultsLayer.setStandardDeviations(0.0)
>>>
>>> resultsLayer.setUserDefinedGrayMinimumMaximum(
>>> True )
>>> resultsLayer.setCacheImage(None)
>>> resultsLayer.triggerRepaint()
>>>
>>> but that fails with the following error:
>>>
>>> Traceback (most recent call last):
>>> File
>>> "/Users//.qgis/python/plugins/mcelite/MCELiteDialog.py",
>>> line 361, in accept
>>> extentMin, extentMax =
>>> resultsLayer.computeMinimumMaximumFromLastExtent(band)
>>> TypeError: 'float' object is not
>>> iterable
>>>
>>>
>>> and I don't understand what the
>>> float object is, exactly.
>>>
>>>
>>> Any help or suggestions much
>>> appreciated.
>>>
>>>
>>> Cheers,
>>>
>>> JP
>>>
>>>
>>>
>>>
>>>
--
====================================
Peter J. Ersts, Software Developer
American Museum of Natural History
Center for Biodiversity and Conservation
Central Park West at 79th Street
New York, New York 10024
Web: http://biodiversityinformatics.amnh.org
Web: http://cbc.amnh.org
Open Source,
...evolving through community cooperation to change the world bit by bit
Quantum GIS Raster Development Team.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/qgis-developer/attachments/20100907/639f3e3e/attachment-0001.html
More information about the Qgis-developer
mailing list