[GRASS-dev] r.reclass only for int maps

On Oct 9, 2011, at 9:00 AM, <grass-dev-request@lists.osgeo.org> wrote:

Date: Sun, 9 Oct 2011 03:36:53 +0100
From: Glynn Clements <glynn@gclements.plus.com>
Subject: Re: [GRASS-dev] r.reclass only for int maps
To: Martin Landa <landa.martin@gmail.com>
Cc: GRASS developers list <grass-dev@lists.osgeo.org>
Message-ID: <20113.2245.545837.762166@cerise.gclements.plus.com>
Content-Type: text/plain; charset=us-ascii

Martin Landa wrote:

is there any reason why r.reclass does not support FP raster maps?

The immediate reason is that the underlying functionality in libgis
doesn't support it. r.reclass merely creates the tables; it's libgis
which uses them.

It would be a relatively simple matter to extend the existing
functionality to allow reclassing an integer map to an FP map (i.e.
the reclass table could contain FP values instead of integers).

It would be somewhat more complex to support "reclassing" an FP map. I
use quotes because the term implies that the data consists of discrete
classes (categories). Ultimately, a reclass table is just that: a
table, i.e. an array, and you can't use floats as array indices.

While there's no fundamental issue with defining a mapping whose
domain is floating-point numbers (we already do this for colour
tables), it is bound to be significantly slower than the integer case.

And probably less useful.

A mapping from integers to integers can be described by a look-up
table, but a mapping from floats to either integers or floats can't be
(at least, not realistically). So you have to decide upon the nature
of the approximation: piecewise linear, cubic spline, rational spline,
or something else entirely? Or do we merge r.mapcalc into libraster so
that maps can be "reclassed" by arbitrary algebraic expressions?

--
Glynn Clements <glynn@gclements.plus.com>

I originally raised this question with regard to discrete values maps whose values are floating point numbers, not maps in which floating point numbers represent a continuous field (e.g., as in an elevation map).

An example might be a soil map with a limited number of discrete values for K-factor.

Whether integers or floating point numbers are used, r.reclass only makes sense in the context of a map with a small number of discrete values. In that case questions about approximations do not really apply. It should just be a simple 1 to 1 mapping like we have for integers.

Are the limitations you mention a function of the data type itself or more about what the cell values represent?

Michael
____________________
C. Michael Barton
Director, Center for Social Dynamics & Complexity
Professor of Anthropology, School of Human Evolution & Social Change
Arizona State University

voice: 480-965-6262 (SHESC), 480-727-9746 (CSDC)
fax: 480-965-7671 (SHESC), 480-727-0709 (CSDC)
www: http://www.public.asu.edu/~cmbarton, http://csdc.asu.edu

Michael Barton wrote:

I originally raised this question with regard to discrete values maps
whose values are floating point numbers, not maps in which floating
point numbers represent a continuous field (e.g., as in an elevation
map).

An example might be a soil map with a limited number of discrete values
for K-factor.

Whether integers or floating point numbers are used, r.reclass only
makes sense in the context of a map with a small number of discrete
values. In that case questions about approximations do not really apply.
It should just be a simple 1 to 1 mapping like we have for integers.

Are the limitations you mention a function of the data type itself or
more about what the cell values represent?

They're mostly an issue of the nature of the cell values themselves.

Realistically, a look-up table requires that the values are integers,
and cover a relatively small range.

The actual code (from lib/raster/get_row.c) which performs the reclass
does:

    struct fileinfo *fcb = &R__.fileinfo[fd];
    CELL *c = cell;
    CELL *reclass_table = fcb->reclass.table;
    CELL min = fcb->reclass.min;
    CELL max = fcb->reclass.max;
    int i;

    for (i = 0; i < R__.rd_window.cols; i++) {
  ...
  c[i] = reclass_table[c[i] - min];

IOW, the number of entries in the reclass table is (max-min+1), i.e.
it contains entries covering the range of values, including any gaps.
So if you have an integer map consisting of two values, 1000000000 and
2000000000, then the look-up table needs 1000000001 entries.

Floating-point values can't be used as array indices directly, and
converting them to integers for use as array indices would require a
scale factor chosen such that distinct floating-point values map to
distinct integers. Given that a set of floating point values can
include both very small values and very large values, it wouldn't be
hard to come up with data which required an infeasibly large look-up
table.

For "category" data such as:

An example might be a soil map with a limited number of discrete values
for K-factor.

the ideal solution would be to allow reclassing an integer map *to* a
floating-point map (i.e. the look-up table could contain float/double
values). The underlying map would contain integer category numbers,
while a reclassed version would contain the corresponding
floating-point "factor" values.

Some modules support this by allowing category labels to be parsed as
floating-point values (e.g. r.mapcalc's '@' modifier, r.statistics' -c
flag, etc). But allowing reclassing to floating-point would work for
all modules.

Extending the reclass feature to support "on-the-fly r.recode"
functionality would be a much bigger issue.

--
Glynn Clements <glynn@gclements.plus.com>