Hi,
I did some tests to try to figure this out and it seems like most of
the confusion was due to integer mathematics (though I am not sure that
the current behavior is the "correct" behavior). First, I created some
test rasters:
CREATE TEMP TABLE test_rasters ASSELECT 1 AS rid, ST_SetValues(
ST_AddBand( ST_MakeEmptyRaster(2, 2, 0, 0, 1, -1, 0, 0, 0),
1, '8BUI', 0), 1, 1, 1, ARRAY[[1,2],
[0,0]]::double precision[][] ) AS rastUNIONSELECT 2 AS rid,
ST_SetValues( ST_AddBand( ST_MakeEmptyRaster(2, 2, 0, 0,
1, -1, 0, 0, 0),1, '8BUI', 0), 1, 1, 1,
ARRAY[[1,0], [3,0]]::double precision[][] ) AS rastUNIONSELECT 3
AS rid, ST_SetValues( ST_AddBand( ST_MakeEmptyRaster(2,
2, 0, 0, 1, -1, 0, 0, 0), 1, '8BUI', 0),
1, 1, 1, ARRAY[[0,0], [3,0]]::double precision[][] ) AS rast;
This leads to the following rasters:
# SELECT rid, ST_DumpValues(rast) FROM test_rasters; rid
|st_dumpvalues-+- 3 |
(1,"{{0,0},{3,0}}") 1 | (1,"{{1,2},{0,0}}") 2 |
(1,"{{1,0},{3,0}}")(3 rows)
Then I did the following calculations on those rasters:
# SELECT ST_DumpValues(ST_Union(rast,1,'COUNT')) FROM
test_rasters;st_dumpvalues-
(1,"{{3,3},{3,3}}")
# SELECT ST_DumpValues(ST_Union(rast,1,'SUM')) FROM
test_rasters; st_dumpvalues --
-- (1,"{{2,2},{6,NULL}}")(1 row)
# SELECT ST_DumpValues(ST_Union(rast,1,'MEAN')) FROM
test_rasters; st_dumpvalues --
-- (1,"{{1,1},{2,NULL}}")(1 row)
# SELECT
ST_DumpValues(ST_MapAlgebra(ST_Union(rast,1,'SUM'),'8BUI','[rast] /
3')) FROM test_rasters; st_dumpvalues --
-- (1,"{{1,1},{2,NULL}}")(1 row)
# SELECT
ST_DumpValues(ST_MapAlgebra(ST_Union(rast,1,'SUM'),'64BF','[rast] /
3')) FROM
test_rasters; st_dumpvalues
-
--- (1,"{{0.667,0.667},{2,NULL}}")(1 row)
So ST_Union is counting the zero values, but when it calculates the
MEAN, it does integer mathematics that leads to unexpected results.
Whereas ST_MapAlgebra allows you to select the output raster pixel
type, ST_Union does not, so I don't think there is a good work around
for this. Is there a way to "cast" a raster from one pixel type to
another? I imagine that with appropriate calls to ST_DumpValues and
ST_SetValues one could make it happen.
One could argue whether or not the current behavior is correct. Based
on my experience with the standard avg() aggregate function, I expected
ST_Union to select an output pixel type that is appropriate for the
calculation being carried out, i.e., that it would output a '32BF' or
'64BF' raster as integer means are a bit unusual. Perhaps ST_Union
should have an output pixel type argument or by default return '64BF'?
On a related note, I noticed that ST_SetBandNoDataValue has somewhat
unexpected behavior when you set the no data value to something that is
outside the range of the pixel type, basically setting the no data
value to the max or min of the data range:
# SELECT (ST_BandMetadata(ST_SetBandNoDataValue(rast,1,-
99))).nodatavalue,#ST_DumpValues(ST_SetBandNoDataValue(rast,1,-
99)) AS values# FROM test_rasters WHERE rid=1; nodatavalue
| values -+
--- 0 | (1,"{{1,2},{NULL,NULL}}")(1 row)
# SELECT
(ST_BandMetadata(ST_SetBandNoDataValue(rast,1,99))).nodatavalue,#
ST_DumpValues(ST_SetBandNoDataValue(rast,1,99)) AS values# FROM
test_rasters WHERE rid=1; nodatavalue | values---
--+- 99 | (1,"{{1,2},{0,0}}")(1 row)
# SELECT
(ST_BandMetadata(ST_SetBandNoDataValue(rast,1,999))).nodatavalue,#
ST_DumpValues(ST_SetBandNoDataValue(rast,1,999)) AS values# FROM
test_rasters WHERE rid=1; nodatavalue | values---
--+- 255 | (1,"{{1,2},{0,0}}")(1 row)
I would have expected it to return an error when the demanded no data
value was outside the range. Should this behavior be changed?
Thanks,David
---
On Sat, 2018-03-10 at 12:00 -0800, postgis-users-requ...@lists.osgeo.or
g wrote:
> Message: 1
> Date: Fri, 9 Mar 2018 23:22:56 -0500
> From: "Regina Obe"
> To: "'PostGIS Users Discussion'"
> Subject: Re: [postgis-users] Aggregating rasters by adding and other
> confusions
> Message-ID: <000301d3b827$77f497b0$67ddc710$@pcorp.us>
> Content-Type: text/plain; charset="utf-8"
>
> David,
>
>
>
> I took a cursory glance at the union code we have in place.
>
> What it seems to do is two passes
>
>
>
> 1 pass does an ST_Union using 'COUNT' (so in your case you'd get
> numbers between 0 and 3, 0 being no rasters considered having any
> data)
>
> 2nd pass does an