Name

ST_MapAlgebraFct — 2 band version - Creates a new one band raster formed by applying a valid PostgreSQL function on the 2 input raster bands and of pixeltype prodived. Band 1 is assumed if no band is specified. Extent type defaults to INTERSECTION if not specified.

Synopsis

raster ST_MapAlgebraFct(raster rast1, raster rast2, regprocedure tworastuserfunc, text pixeltype=same_as_rast1, text extenttype=INTERSECTION, text[] VARIADIC userargs);

raster ST_MapAlgebraFct(raster rast1, integer band1, raster rast2, integer band2, regprocedure tworastuserfunc, text pixeltype=same_as_rast1, text extenttype=INTERSECTION, text[] VARIADIC userargs);

Description

[Warning]

ST_MapAlgebraFct is deprecated as of 2.1.0. Use ST_MapAlgebra instead.

Creates a new one band raster formed by applying a valid PostgreSQL function specified by the tworastuserfunc on the input raster rast1, rast2. If no band1 or band2 is specified, band 1 is assumed. The new raster will have the same georeference, width, and height as the original rasters but will only have one band.

If pixeltype is passed in, then the new raster will have a band of that pixeltype. If pixeltype is passed NULL or left out, then the new raster band will have the same pixeltype as the input rast1 band.

The tworastuserfunc parameter must be the name and signature of an SQL or PL/pgSQL function, cast to a regprocedure. An example PL/pgSQL function example is:

CREATE OR REPLACE FUNCTION simple_function_for_two_rasters(pixel1 FLOAT, pixel2 FLOAT, pos INTEGER[], VARIADIC args TEXT[])
    RETURNS FLOAT
    AS $$ BEGIN
        RETURN 0.0;
    END; $$
    LANGUAGE 'plpgsql' IMMUTABLE;

The tworastuserfunc may accept three or four arguments: a double precision value, a double precision value, an optional integer array, and a variadic text array. The first argument is the value of an individual raster cell in rast1 (regardless of the raster datatype). The second argument is an individual raster cell value in rast2. The third argument is the position of the current processing cell in the form '{x,y}'. The fourth argument indicates that all remaining parameters to ST_MapAlgebraFct shall be passed through to the tworastuserfunc.

Passing a regprodedure argument to a SQL function requires the full function signature to be passed, then cast to a regprocedure type. To pass the above example PL/pgSQL function as an argument, the SQL for the argument is:

'simple_function(double precision, double precision, integer[], text[])'::regprocedure

Note that the argument contains the name of the function, the types of the function arguments, quotes around the name and argument types, and a cast to a regprocedure.

The fourth argument to the tworastuserfunc is a variadic text array. All trailing text arguments to any ST_MapAlgebraFct call are passed through to the specified tworastuserfunc, and are contained in the userargs argument.

[Note]

For more information about the VARIADIC keyword, please refer to the PostgreSQL documentation and the "SQL Functions with Variable Numbers of Arguments" section of Query Language (SQL) Functions.

[Note]

The text[] argument to the tworastuserfunc is required, regardless of whether you choose to pass any arguments to your user function for processing or not.

Availability: 2.0.0

Example: Overlaying rasters on a canvas as separate bands

-- define our user defined function --
CREATE OR REPLACE FUNCTION raster_mapalgebra_union(
	rast1 double precision,
	rast2 double precision,
    pos integer[],
	VARIADIC userargs text[]
)
	RETURNS double precision
	AS $$
	DECLARE
	BEGIN
		CASE
			WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
				RETURN ((rast1 + rast2)/2.);
			WHEN rast1 IS NULL AND rast2 IS NULL THEN
				RETURN NULL;
			WHEN rast1 IS NULL THEN
				RETURN rast2;
			ELSE
				RETURN rast1;
		END CASE;

		RETURN NULL;
	END;
	$$ LANGUAGE 'plpgsql' IMMUTABLE COST 1000;

-- prep our test table of rasters
DROP TABLE IF EXISTS map_shapes;
CREATE TABLE map_shapes(rid serial PRIMARY KEY, rast raster, bnum integer, descrip text);
INSERT INTO map_shapes(rast,bnum, descrip)
WITH mygeoms 
    AS ( SELECT 2 As bnum, ST_Buffer(ST_Point(90,90),30) As geom, 'circle' As descrip
            UNION ALL
            SELECT 3 AS bnum, 
                ST_Buffer(ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'), 15) As geom, 'big road' As descrip
            UNION ALL
            SELECT 1 As bnum, 
                ST_Translate(ST_Buffer(ST_GeomFromText('LINESTRING(60 50,150 150,150 50)'), 8,'join=bevel'), 10,-6) As geom, 'small road' As descrip
            ),
   -- define our canvas to be 1 to 1 pixel to geometry
   canvas
    AS ( SELECT ST_AddBand(ST_MakeEmptyRaster(250, 
        250, 
        ST_XMin(e)::integer, ST_YMax(e)::integer, 1, -1, 0, 0 ) , '8BUI'::text,0) As rast
        FROM (SELECT ST_Extent(geom) As e,
                    Max(ST_SRID(geom)) As srid 
                    from mygeoms 
                    ) As foo
            )
-- return our rasters aligned with our canvas
SELECT ST_AsRaster(m.geom, canvas.rast, '8BUI', 240) As rast, bnum, descrip
                FROM mygeoms AS m CROSS JOIN canvas
UNION ALL 
SELECT canvas.rast, 4, 'canvas'
FROM canvas;

-- Map algebra on single band rasters and then collect with ST_AddBand
INSERT INTO map_shapes(rast,bnum,descrip)
SELECT ST_AddBand(ST_AddBand(rasts[1], rasts[2]),rasts[3]), 4, 'map bands overlay fct union (canvas)'
	FROM (SELECT ARRAY(SELECT ST_MapAlgebraFct(m1.rast, m2.rast, 
			'raster_mapalgebra_union(double precision, double precision, integer[], text[])'::regprocedure, '8BUI', 'FIRST')
                FROM map_shapes As m1 CROSS JOIN map_shapes As m2
                	WHERE m1.descrip = 'canvas' AND m2.descrip <> 'canvas' ORDER BY m2.bnum) As rasts) As foo;
					

map bands overlay (canvas) (R: small road, G: circle, B: big road)

User Defined function that takes extra args

	
CREATE OR REPLACE FUNCTION raster_mapalgebra_userargs(
	rast1 double precision,
	rast2 double precision,
    pos integer[],
	VARIADIC userargs text[]
)
	RETURNS double precision
	AS $$
	DECLARE
	BEGIN
		CASE
			WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
				RETURN least(userargs[1]::integer,(rast1 + rast2)/2.);
			WHEN rast1 IS NULL AND rast2 IS NULL THEN
				RETURN userargs[2]::integer;
			WHEN rast1 IS NULL THEN
				RETURN greatest(rast2,random()*userargs[3]::integer)::integer;
			ELSE
				RETURN greatest(rast1, random()*userargs[4]::integer)::integer;
		END CASE;

		RETURN NULL;
	END;
	$$ LANGUAGE 'plpgsql' VOLATILE COST 1000;
	
SELECT ST_MapAlgebraFct(m1.rast, 1, m1.rast, 3,
			'raster_mapalgebra_userargs(double precision, double precision, integer[], text[])'::regprocedure,
				'8BUI', 'INTERSECT', '100','200','200','0') 
                FROM map_shapes As m1
                	WHERE m1.descrip = 'map bands overlay fct union (canvas)'; 
					

user defined with extra args and different bands from same raster

See Also

ST_MapAlgebraExpr, ST_BandPixelType, ST_GeoReference, ST_SetValue