[Qgis-developer] Re: Raster layer display control from Plugin

Peter Ersts ersts at amnh.org
Tue Sep 7 09:42:13 EDT 2010


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/acd4225e/attachment-0001.html


More information about the Qgis-developer mailing list