[GRASS-dev] Question on C API and GRASS raster/region

Dear devs,

I'm trying to clarify the behavior of the C API of grass concerning
the interaction between raster and region, since I'm more confortable
with Python, I've just open an ipython interpreter inside a GRASS
session, the mapset is the North Carolina.

I've imported some libraries and define two function to make the process easier:

{{{

%paste

from __future__ import print_function
import ctypes
import fnmatch
from pprint import pprint

import grass.lib.gis as libgis
import grass.lib.raster as libraster

def attributes(obj):
    return sorted(fnmatch.filter(dir(obj), '[!_]*'))

def struct2items(struct):
    struct = struct.contents if hasattr(struct, 'contents') else struct
    return [(attr, getattr(struct, attr)) for attr in attributes(struct)]
## -- End pasted text --
}}}

Let's start I create an empty region structure with:

{{{

c_region = ctypes.pointer(libgis.Cell_head())
pprint(struct2items(c_region))

[('bottom', 0.0),
('cols', 0),
('cols3', 0),
('compressed', 0),
('depths', 0),
('east', 0.0),
('ew_res', 0.0),
('ew_res3', 0.0),
('format', 0),
('north', 0.0),
('ns_res', 0.0),
('ns_res3', 0.0),
('proj', 0),
('rows', 0),
('rows3', 0),
('south', 0.0),
('tb_res', 0.0),
('top', 0.0),
('west', 0.0),
('zone', 0)]
}}}

get the current region:

{{{

libgis.G_get_set_window(c_region)
pprint(struct2items(c_region))

[('bottom', 0.0),
('cols', 1500),
('cols3', 1500),
('compressed', -1),
('depths', 1),
('east', 645000.0),
('ew_res', 10.0),
('ew_res3', 10.0),
('format', 0),
('north', 228500.0),
('ns_res', 10.0),
('ns_res3', 10.0),
('proj', 99),
('rows', 1350),
('rows3', 1350),
('south', 215000.0),
('tb_res', 1.0),
('top', 1.0),
('west', 630000.0),
('zone', 0)]

print('rows:', libraster.Rast_window_rows(),

... 'cols:', libraster.Rast_window_cols())
rows: 1350 cols: 1500
}}}

Now I change some region attributes and I adjust/update the struct values with

{{{

print('Change region extent and set as current')

Change region extent and set as current

# change region attributes
c_region.contents.west = 644530.0
c_region.contents.south = 228070.0
# adjust accordingly the number of rows and columns
libgis.G_adjust_Cell_head(c_region, False, False)
libgis.G_set_window(c_region)
pprint(struct2items(c_region))

[('bottom', 0.0),
('cols', 47),
('cols3', 1500),
('compressed', -1),
('depths', 1),
('east', 645000.0),
('ew_res', 10.0),
('ew_res3', 10.0),
('format', 0),
('north', 228500.0),
('ns_res', 10.0),
('ns_res3', 10.0),
('proj', 99),
('rows', 43),
('rows3', 1350),
('south', 228070.0),
('tb_res', 1.0),
('top', 1.0),
('west', 644530.0),
('zone', 0)]

print('rows:', libraster.Rast_window_rows(),

... 'cols:', libraster.Rast_window_cols())
rows: 1350 cols: 1500
}}}

As you can see the region struct has now 43 rows and 47 columns, but
still the Rast_window_rows and the Rast_window_cols return still the
'old' one.
The Rast_window_[rows|cols] functions are described in the
documentation () as "Number of [rows|cols] in active window." with
active here we mean current, aren't we?
http://grass.osgeo.org/programming7/raster_2window_8c.html#ac2ce884f9f92cf60e28850c705ba8175

Therefore why they are not returning 43 and 47?

Creating a new struct and asking for the current region provide me the
expected result.

{{{

c_region_new = ctypes.pointer(libgis.Cell_head())
libgis.G_get_set_window(c_region_new)
pprint(struct2items(c_region_new))

[('bottom', 0.0),
('cols', 47),
('cols3', 1500),
('compressed', -1),
('depths', 1),
('east', 645000.0),
('ew_res', 10.0),
('ew_res3', 10.0),
('format', 0),
('north', 228500.0),
('ns_res', 10.0),
('ns_res3', 10.0),
('proj', 99),
('rows', 43),
('rows3', 1350),
('south', 228070.0),
('tb_res', 1.0),
('top', 1.0),
('west', 644530.0),
('zone', 0)]
}}}

Probably I misunderstood something... Someone can help to understand
this point better?
Thank you very much

Pietro

(attachments)

test_region.py (1.29 KB)

Pietro wrote:

As you can see the region struct has now 43 rows and 47 columns, but
still the Rast_window_rows and the Rast_window_cols return still the
'old' one.
The Rast_window_[rows|cols] functions are described in the
documentation () as "Number of [rows|cols] in active window." with
active here we mean current, aren't we?
http://grass.osgeo.org/programming7/raster_2window_8c.html#ac2ce884f9f92cf60e28850c705ba8175

Therefore why they are not returning 43 and 47?

You need to use Rast_set_window() (or Rast_set_input_window() and/or
Rast_set_ouput_window()) to change the window(s) used by the raster
library.

libgis functions (e.g. G_set_window()) can't do this because libgis is
at a lower level than libraster.

Creating a new struct and asking for the current region provide me the
expected result.

Bear in mind that this won't affect the raster I/O functions. The
raster windows are initialised from the libgis window at startup, but
won't change thereafter unless changed via the libraster functions.

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