PostGIS raster has so so many functions and probably at least 10 ways of doing something some much much slower than others. Suppose
you have a raster, or you have a raster area of interest — say elevation raster for example, and you want to know the distinct pixel values in the area.
The temptation is to reach for
ST_Value function in raster, but there is a much much more efficient function to use, and that is the
ST_ValueCount function is one of many statistical raster functions available with PostGIS 2.0+. It is a set returning function that returns 2 values for each row: a pixel value (value), and a count of pixels (count) in the raster that have that value. It also has variants that allow you to filter for certain pixel values.
This tip was prompted by the question on stackexchange How can I extract all distinct values from a PostGIS Raster?
Get a distinct pixel value list for band 1 of all raster tiles
Specifying the band number is optional and defaults to 1 if not specified. I like to specify it just cause I work a lot with multi-band rasters. In this case I just have digital elevation data table called dem.
SELECT DISTINCT (pvc).value FROM (SELECT ST_ValueCount(dem.rast,1) AS pvc FROM dem) AS f ORDER BY (pvc).value;
Now if you are using PostgreSQL 9.3+, you can make this even shorter by using the LATERAL clause (since LATERAL keyword is optional in most cases, you can skip saying LATERAL and write it like this)
SELECT DISTINCT (pvc).value FROM dem, ST_ValueCount(dem.rast,1) AS pvc ORDER BY (pvc).value;
Get a pixel value list for band 1 and total pixels for an area of interest
Now if you have a huge coverage, chances are you only care about a particular area, not the 3 million tiles you have.
You might want to also know
how many times the value appears just for your area of interest
So you really want to combine your arsenal with
Here I am using the 9.3 LATERAL short-hand
SELECT (pvc).value, SUM((pvc).count) AS tot_pix FROM dem INNER JOIN ST_GeomFromText('LINESTRING(-87.627 41.8819, -87.629 41.8830)' , 4326) AS geom ON ST_Intersects(dem.rast, geom), ST_ValueCount(ST_Clip(dem.rast,geom),1) AS pvc GROUP BY (pvc).value ORDER BY (pvc).value;
As of PostGIS 2.3, the postgis extension was changed to no longer allow relocation. All function calls within the extension are now schema qualified.
While this change fixed some issues with database restore, it created the issue of if you installed PostGIS in a schema other than the one you wanted to it is not intuitive how to move it to a different schema. Luckily there is a way to do this.
For this exercise, I will install PostGIS in the default schema and then demonstrate how to move it into another schema location.
You can run these steps using psql or pgAdmin or any other PostgreSQL tool you want.
The error ‘postgis.backend’ is already set comes up every so often in PostGIS mailing list. The issue arises often during or after an upgrade. I’ll go over causes for this I am aware of and how to fix.
The question goes something like this
After upgrading to Postgis 2.3 from 2.1, my server log is filled with these messages :
“WARNING ‘postgis.backend’ is already set and cannot be changed until you reconnect”
This raster question comes up quite a bit on PostGIS mailing lists and stack overflow and the best answer often involves
the often forgotten
ST_Reclass function that has existed since PostGIS 2.0.
People often resort to the much slower though more flexible
ST_MapAlgebra or dumping out
their rasters as Pixel valued polygons they then filter
with WHERE val > 90,
ST_Reclass does the same thing but orders of magnitude faster.