Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r.recode results in integer when floating numbers are expected [Bug] #3720

Open
ecodiv opened this issue May 18, 2024 · 6 comments
Open

r.recode results in integer when floating numbers are expected [Bug] #3720

ecodiv opened this issue May 18, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@ecodiv
Copy link
Contributor

ecodiv commented May 18, 2024

Describe the bug

I have a map with data type Float, with values between 0 and 18.7. I use r.recode to rescale the layer to values between 0 and 1 using the steps below. I expect the output to be a float raster. But it is converted to an integer map instead.

To reproduce

  1. Take a raster of data type Float
  2. Run the following (replace the old min and max for min and max value of your input raster layer).
echo "0.0:18.7:0.0:1.0" | r.recode input=myinput output=myoutput rules=-
  1. Check data type
r.info -g myoutput

The resulting output layer is an integer raster.

Expected behavior

I would expect the output layer to be a float raster. Using the -d flag will force the output layer to be of type DCELL.

System description

  • Operating System: Linux, Ubuntu 22.04
  • GRASS GIS version: 8.3.2
@ecodiv ecodiv added the bug Something isn't working label May 18, 2024
@dhdeangelis
Copy link
Contributor

You need to add the -d flag to your command to achieve your expected results:

-d Force output to 'double' raster map type (DCELL)

Try:

echo "0.0:18.7:0.0:1.0" | r.recode -d input=myinput output=myoutput rules=-

@ecodiv
Copy link
Contributor Author

ecodiv commented May 19, 2024

You need to add the -d flag to your command to achieve your expected results:

-d Force output to 'double' raster map type (DCELL)

Try:

echo "0.0:18.7:0.0:1.0" | r.recode -d input=myinput output=myoutput rules=-

Thanks. I know you can use the -d flag (and I wrote that in the bug report), but the point I was trying to make is that based on the manual, I would not necessarily expect r.recode to convert the floating map to an integer map, as I used decimal numbers for the new minimum and maximum value. I think that either the behavior should be changed, or the behavior (when does the function change the data type) should be explained more explicitly.

@dhdeangelis
Copy link
Contributor

I know you can use the -d flag (and I wrote that in the bug report)

I see, I missed that.

based on the manual, I would not necessarily expect r.recode to convert the floating map to an integer map, as I used decimal numbers for the new minimum and maximum value. I think that either the behavior should be changed, or the behavior (when does the function change the data type) should be explained more explicitly.

I agree with this. I also find the manual confusing on this regard. The manual first states that r.recode is for recoding categorical maps, which it seems to be made for, but then gives an example of rescaling, for which r.mapcalc is more convenient.

@ninsbl
Copy link
Member

ninsbl commented May 19, 2024

This seems like a bug to me.

r.recode appears to be intended to produce FCELL results too. See e.g.: https://github.com/OSGeo/grass/blob/25961a86c26765f293d582900b00bb37403a780d/raster/r.recode/read_rules.c#L143C25-L143C29

@dhdeangelis
Copy link
Contributor

dhdeangelis commented May 20, 2024

It seems that the problem lies in parsing or managing the input, as numbers ending in zero are not interpreted as float.

Example:
echo "0.0:18.7:0.0:1.0" | r.recode input=r output=test rules=- --overwrite
produces a raster of type CELL
while
echo "0.0:18.7:0.01:1.0" | r.recode input=r output=test rules=- --overwrite
or
echo "0.0:18.7:0.0:1.01" | r.recode input=r output=test rules=- --overwrite
produce rasters of type FCELL

Edit: deleted reference to rules, as I could not trace the exact source of the problem.

@dhdeangelis
Copy link
Contributor

It seems to me that this part in read_rules.c is not working as intended:

int update_type(RASTER_MAP_TYPE *map_type, DCELL val)
{
/* check if val is not an integer number */
if (make_dcell)
*map_type = DCELL_TYPE;
else {
if ((DCELL)((CELL)val) != val)
*map_type = FCELL_TYPE;
}
return 0;
}

Perhaps line 142 could be replaced with a call to a function to tell if val is a float or integer. . I am not so fluent in C but it seems that is not so straightforward.

A simple work around could be to default output to integer, unless it is forced to double using the -d switch, or to float using a new switch, for example: -f. This I just tested and works. But it is perhaps not the expected behaviour? Also it adds a new switch and may break backwards compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants