Advanced Mapping Library for Geocomputational Research

 
P
r
o
n
t
o
 
R
a
s
t
e
r
:
 
A
 
C
+
+
 
l
i
b
r
a
r
y
f
o
r
 
M
a
p
 
A
l
g
e
b
r
a
 
Alex Hagen-Zanker
a.hagen-zanker@surrey.ac.uk
 
Map algebra
Local operations
Focal operations
Zonal operations
 
+
 
=
 
Σ
 
=
 
Σ
 
=
 
https://github.com/ahhz/raster
 
That is basic! Don’t we have tools?
 
Geodata management: GDAL, Proj, GeoTIFF, etc.
Image processing: OpenCV, GIL, etc.
Linear algebra: Eigen, Blitz, UBLAS, etc.
Scripting languages: ArcGIS Python, PC Raster, R -
raster, Geotrellis
GIS software: Raster Calculator and specific tools in
QGIS, SAGA ArcGIS
All of these facilitate Map Algebra operations,
but none meets all (my) requirements
 
https://github.com/ahhz/raster
 
Expected user and requirements
 
https://github.com/ahhz/raster
Researcher / consultant working
in geocomputational domain who
does not like being constrained by
built-in methods
 
Design: Raster and Raster View
concepts
Range
*
Gives access to a sequence of values
through iterator access. Unlike a
Container does not have to store its
own values
Range View
A Range that can be copied O(1) and is
meant to be passed to functions by
value
Raster
A Range of which we know the
number of rows and columns. And,
must also give access to sub-raster .
 
Raster View
A Raster that is also a View.
 
 
https://github.com/ahhz/raster
*Official proposal to C++ standard, see also https://ericniebler.github.io/range-v3/
 
Design: Raster and Raster View
concepts
 
https://github.com/ahhz/raster
 
Using the Raster concept (1)
 
#include <pronto/raster/io.h>
namespace pr = pronto::raster;
 
int main()
{
  auto ras = pr::open<int>("my_file.tif")
  int sum = 0;
  for(auto&& v : ras)
  {
    sum += v;
  }
}
Use GDAL to open a raster
dataset as a model of the
Raster View concept
Use range-based for-loop
to iterate over all values in
the raster
 
https://github.com/ahhz/raster
 
Using the Raster concept (2)
 
#include <pronto/raster/io.h>
namespace pr = pronto::raster;
 
int main()
{
  auto ras = pr::open<int>("my_file.tif")
  int sum = 0;
  for(auto&& v : ras.sub_raster(2,3,10,20))
  {
    sum += v;
  }
}
Iterate over subset of the
raster. First cell at (2,3)
then 10 rows and 20
columns
 
https://github.com/ahhz/raster
 
Design: Expression Templates (ET) for
local operations
 
Local operations take Raster Views as input and
produce an ET as output that also is a Raster View.
Cell values of the ET are only calculated once they
are iterated over
No need to allocate memory
Input and output conform to the same concept:
highly composable
A generic function, 
transform
, is implemented,
other local functions can be implemented in terms
of 
transform
 
 
 
https://github.com/ahhz/raster
 
Using local operations(1)
 
#include <pronto/raster/io.h>
#include <pronto/raster/transform_raster_view.h>
#include <functional>
namespace pr = pronto::raster;
 
int main()
{
  auto a = pr::open<int>("a.tif");
  auto b = pr::open<int>("b.tif");
 
  auto sum = pr::transform(std::plus<int>, a, b);
  for(auto&& v : sum.sub_raster(2,3,10,20))
  {
    // do something
  }
}
 
Open two datasets
Create a Raster View
that applies std::plus to
each cell of both input
datasets
Iterate over a sub-raster of the
Raster View  and calculate the
required values only
 
https://github.com/ahhz/raster
 
Using local operations(2)
 
auto a = pr::open<int>("a.tif");
auto b = pr::open<int>("b.tif");
 
auto diff = pr::transform(std::minus<int>, a, b);
auto sqr_lambda = [](int x){return x*x;};
auto sqr_diff = pr::transform(sqr_lambda, diff);
int sum_of_squared_diff = 0;
for(auto&& v : square_diff)
{
    sum_of_squared_diff += v;
}
Create a RasterView of
square of differences in
two steps
Iterate over values,
without allocating extra
memory, or creating
temporary dataset.
 
https://github.com/ahhz/raster
 
Using local operations(3)
 
#include <pronto/raster/io.h>
#include <pronto/raster/raster_algebra_operators.h>
#include <pronto/raster/raster_algebra_wrapper.h>
namespace pr = pronto::raster;
int main()
{
  auto a = pr::raster_algebra_wrap(br::open<int>("a.tif"));
  auto b = pr::raster_algebra_wrap(br::open<int>("b.tif"));
  auto square_diff = (a – b) * (a – b);
  for(auto&& v : square_diff)
  {
    // do something
  }
}
Wrap a and b in raster_algebra_wrapper
to allow use of overloaded operators
Iterate over values.
 
https://github.com/ahhz/raster
 
Design: use optional<T> for flagging
and processing nodata values
 
https://github.com/ahhz/raster
#include <pronto/raster/io.h>
#include <pronto/raster/nodata_transform.h>
#include <pronto/raster/plot_raster.h>
 
namespace pr = pronto::raster;
 
int main()
{
  auto in = pr::open<int>("demo.tif");
  auto nodata = pr::nodata_to_optional(in, 6);
  auto un_nodata = pr::optional_to_nodata(nodata,
    
 -99);
}
Value type: int
0       3       6       2       5
1       4       0       3       6
2       5       1       4       0
3       6       2       5       1
Value type: std::optional<int>
0       3       -       2       5
1       4       0       3       -
2       5       1       4       0
3       -       2       5       1
Value type: int
0       3       -99     2       5
1       4       0       3       -99
2       5       1       4       0
3       -99     2       5       1
Providing an idiomatic way for functions to
skip over missing values or to leave cells
unspecified
 
Design: fundamental spatial
operators avoid copying data
 
 
https://github.com/ahhz/raster
 
Design: moving windows as
Expression Templates
 
Moving window analysis
is a common type of Focal
Operation
Each cell obtains the
value of a summary
statistics calculated for
cells in a surrounding
window
Efficient implementations
exploit overlap in
windows of adjacent cells
(especially for large
windows)
 
https://github.com/ahhz/raster
 
Circular window of cells
 
Circular window of edges
 
Square window of edges
 
Square window of cells
 
Moving window schemes
 
O(r x n)
r = radius
n = raster size
 
O(n)
n = raster size
 
https://github.com/ahhz/raster
Hagen-Zanker, AH (2016) 
A computational framework for generalized moving windows and its application to landscape
pattern analysis
 International Journal of Applied Earth Observation and Geoinformation.
 
Design: Indicator concept
 
Implement statistics in terms of a few functions
add(element, weight)
subtract(element, weight)
add(subtotal, weight)
subtract(subtotal, weight)
extract()
Can be used with moving window methods
Can be used for zonal statistics
 
https://github.com/ahhz/raster
 
Using moving window indicators
 
 
#include <pronto/raster/moving_window_indicator.h>
#include <pronto/raster/indicator/mean.h>
 
namespace pr = pronto::raster;
int main()
{
  auto in = pr::open<int>("my_file.tif");
  
auto window = pr::circle(2);
  auto indicator = pr::mean_generator<int>{};
  
auto out = pr::moving_window_indicator(in, window, indicator);
 
  
for(auto&&
 v : out)
  {
    // do something
  }
}
Specify circular window with
radius of 2 cells.
Specify to use the mean statistic.
"out" is a Raster View, satisfying
all the same requirements as "in".
 
https://github.com/ahhz/raster
 
The assign function forces evaluation
of lazy Expression Templates
 
#include <pronto/raster/assign.h>
#include <pronto/raster/io.h>
#include <cmath>
 
namespace pr = pronto::raster;
 
int main()
{
  auto in = pr::open<int>("my_file.tif");
  auto sqrt = pr::transform([](int x){return std::sqrt(x);}, in);
 
  auto out = pr::create_from_model<float>("sqrt.tif", in);
  pr::assign(b, out);
}
Cheap: Create ET  for the sqrt of
values in “my_file.tif”
 
https://github.com/ahhz/raster
Expensive: Create “sqrt.tif” and
write values
 
Design: Runtime polymorphism
through type erasure
 
Runtime polymorphism is sometimes required
operations specified by user (e.g. Raster Calculator)
value type of raster dataset unknown at compile time
 
https://github.com/ahhz/raster
 
Using any_raster<T>
 
pr::any_raster<int> plus_or_minus(bool do_plus)
{
  auto a = pr::open<int>("a.tif");
  auto b = pr::open<int>("b.tif");
  if(do_plus) {
    auto x = pr::transform(std::plus<int>, a, b));
    return pr::make_any_raster(x);
  } else {
    auto y = pr::transform(std::minus<int>, a, b));
    return pr::make_any_raster(y);
  }
}
Runtime decision
x and y are different types;
but both are Raster Views
with int as value type
 
https://github.com/ahhz/raster
 
Using any_blind_raster
 
pr::any_blind_raster a_in= pr::open_any("a.tif");
pr::any_blind_raster b_in= pr::open_any("b.tif");
 
auto a = pr::raster_algebra_wrap(a_in);
auto b = pr::raster_algebra_wrap(b_in);
auto c = (b-a) * (b-a);
 
pr::export_any("out.tif", c.unwrap());
 
Raster algebra made to work
with any_blind_raster
Exported to the
appropriate value type
Opened as the appropriate
value type
Unwrap from
raster_algebra_wrapper
 
https://github.com/ahhz/raster
 
Future music: Parallel processing
 
The sub_raster() requirement of Raster Views
combined with the Expression Template design
allows doing calculation for only a part of the raster
For local operations and moving window indicators
only the assign function needs to be parallelized
Split the rasters into sub-raster blocks
Assign all blocks asynchronously
And… rest of library needs to be thread safe
 
https://github.com/ahhz/raster
Scale dependent landscape
metrics
 
Applications
Cellular Automata land use
model
 
Fuzzy set map comparison
 
https://github.com/ahhz/raster
 
Conclusions
 
Thank you!
 
https://github.com/ahhz/raster
 
github.com/ahhz/raster
 
a.hagen-zanker@surrey.ac.uk
Slide Note
Embed
Share

A new C++ library, Pronto Raster, offers extensive support for map algebra, local, focal, and zonal operations on raster data. Aimed at researchers and consultants in geocomputational fields, it addresses key challenges like customization, scalability, efficiency, flexibility, and usability with its idiomatic interface. The design includes concepts of Raster and Raster View for efficient data handling. Compatible with other libraries, it provides a robust solution for working with large raster datasets.

  • Geocomputational Research
  • Map Algebra
  • Raster Data
  • C++ Library
  • Customizable Operations

Uploaded on Sep 13, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. Pronto Raster: A C++ library Pronto Raster: A C++ library for Map Algebra for Map Algebra Alex Hagen-Zanker a.hagen-zanker@surrey.ac.uk

  2. Map algebra Local operations Focal operations Zonal operations A B B B 5 3 A B A B 1 3 2 A A A B 2 + = 1 2 1 2 4 2 2 4 4 3 4 3 2 13 = = Zone 7 A 17 B 13 https://github.com/ahhz/raster

  3. That is basic! Dont we have tools? Geodata management: GDAL, Proj, GeoTIFF, etc. Image processing: OpenCV, GIL, etc. Linear algebra: Eigen, Blitz, UBLAS, etc. Scripting languages: ArcGIS Python, PC Raster, R - raster, Geotrellis GIS software: Raster Calculator and specific tools in QGIS, SAGA ArcGIS All of these facilitate Map Algebra operations, but none meets all (my) requirements https://github.com/ahhz/raster

  4. Expected user and requirements Researcher / consultant working in geocomputational domain who does not like being constrained by built-in methods Requirement Key challenge Customizable Be able to apply custom local, focal and zonal functions on any number of layers Scalable Work with large raster data sets that exceed available memory Efficient Minimal creation of temporary datasets for intermediary results Flexible Work with wide range of data types with no need for data preprocessing Usable Idiomatic interface, minimal use of boiler plate code Compatible Be able to use in conjunction with other libraries (e.g. for optimization, simulation control, etc.) https://github.com/ahhz/raster

  5. Design: Raster and Raster View concepts Range* Raster A Range of which we know the number of rows and columns. And, must also give access to sub-raster . Gives access to a sequence of values through iterator access. Unlike a Container does not have to store its own values Range View Raster View A Raster that is also a View. A Range that can be copied O(1) and is meant to be passed to functions by value *Official proposal to C++ standard, see also https://ericniebler.github.io/range-v3/ https://github.com/ahhz/raster

  6. Design: Raster and Raster View concepts Concept Main requirements iterator_type begin(); iterator_type end(); Range size_type size(); Sized copy-constructor O(1) View sub_type sub_raster(start_row, start_col, rows, cols); size_type rows(); size_type cols(); Raster https://github.com/ahhz/raster

  7. Using the Raster concept (1) Use GDAL to open a raster dataset as a model of the Raster View concept #include <pronto/raster/io.h> namespace pr = pronto::raster; int main() { auto ras = pr::open<int>("my_file.tif") int sum = 0; for(auto&& v : ras) { sum += v; } } Use range-based for-loop to iterate over all values in the raster https://github.com/ahhz/raster

  8. Using the Raster concept (2) #include <pronto/raster/io.h> namespace pr = pronto::raster; int main() { auto ras = pr::open<int>("my_file.tif") int sum = 0; for(auto&& v : ras.sub_raster(2,3,10,20)) { sum += v; } } Iterate over subset of the raster. First cell at (2,3) then 10 rows and 20 columns https://github.com/ahhz/raster

  9. Design: Expression Templates (ET) for local operations Local operations take Raster Views as input and produce an ET as output that also is a Raster View. Cell values of the ET are only calculated once they are iterated over No need to allocate memory Input and output conform to the same concept: highly composable A generic function, transform, is implemented, other local functions can be implemented in terms of transform https://github.com/ahhz/raster

  10. Using local operations(1) #include <pronto/raster/io.h> #include <pronto/raster/transform_raster_view.h> #include <functional> namespace pr = pronto::raster; Open two datasets int main() { auto a = pr::open<int>("a.tif"); auto b = pr::open<int>("b.tif"); Create a Raster View that applies std::plus to each cell of both input datasets auto sum = pr::transform(std::plus<int>, a, b); for(auto&& v : sum.sub_raster(2,3,10,20)) { // do something } } Iterate over a sub-raster of the Raster View and calculate the required values only https://github.com/ahhz/raster

  11. Using local operations(2) Create a RasterView of square of differences in two steps auto a = pr::open<int>("a.tif"); auto b = pr::open<int>("b.tif"); auto diff = pr::transform(std::minus<int>, a, b); auto sqr_lambda = [](int x){return x*x;}; auto sqr_diff = pr::transform(sqr_lambda, diff); Iterate over values, without allocating extra memory, or creating temporary dataset. int sum_of_squared_diff = 0; for(auto&& v : square_diff) { sum_of_squared_diff += v; } https://github.com/ahhz/raster

  12. Using local operations(3) #include <pronto/raster/io.h> #include <pronto/raster/raster_algebra_operators.h> #include <pronto/raster/raster_algebra_wrapper.h> namespace pr = pronto::raster; Wrap a and b in raster_algebra_wrapper to allow use of overloaded operators int main() { auto a = pr::raster_algebra_wrap(br::open<int>("a.tif")); auto b = pr::raster_algebra_wrap(br::open<int>("b.tif")); auto square_diff = (a b) * (a b); for(auto&& v : square_diff) { Iterate over values. // do something } } https://github.com/ahhz/raster

  13. Design: use optional<T> for flagging and processing nodata values Value type: int 0 3 6 2 5 1 4 0 3 6 2 5 1 4 0 3 6 2 5 1 #include <pronto/raster/io.h> #include <pronto/raster/nodata_transform.h> #include <pronto/raster/plot_raster.h> namespace pr = pronto::raster; int main() { auto in = pr::open<int>("demo.tif"); auto nodata = pr::nodata_to_optional(in, 6); auto un_nodata = pr::optional_to_nodata(nodata, -99); } Value type: std::optional<int> 0 3 - 2 5 1 4 0 3 - 2 5 1 4 0 3 - 2 5 1 Value type: int 0 3 -99 2 5 1 4 0 3 -99 2 5 1 4 0 3 -99 2 5 1 Providing an idiomatic way for functions to skip over missing values or to leave cells unspecified https://github.com/ahhz/raster

  14. Design: fundamental spatial operators avoid copying data Function Effect add const-valued leading and trailing rows and columns with a unmutable value pad as required by the Raster concept sub_raster returns value found at a fixed spatial offset in the input RasterView offset iterate over all pairs of horizontally / vertically adjacent cell pairs h_edge / v_edge https://github.com/ahhz/raster

  15. Design: moving windows as Expression Templates Moving window analysis is a common type of Focal Operation Each cell obtains the value of a summary statistics calculated for cells in a surrounding window Efficient implementations exploit overlap in windows of adjacent cells (especially for large windows) https://github.com/ahhz/raster

  16. Moving window schemes Circular window of edges Circular window of cells O(r x n) r = radius n = raster size Square window of cells Square window of edges O(n) n = raster size Hagen-Zanker, AH (2016) A computational framework for generalized moving windows and its application to landscape pattern analysis International Journal of Applied Earth Observation and Geoinformation. https://github.com/ahhz/raster

  17. Design: Indicator concept Implement statistics in terms of a few functions add(element, weight) subtract(element, weight) add(subtotal, weight) subtract(subtotal, weight) extract() Can be used with moving window methods Can be used for zonal statistics https://github.com/ahhz/raster

  18. Using moving window indicators #include <pronto/raster/moving_window_indicator.h> #include <pronto/raster/indicator/mean.h> Specify circular window with radius of 2 cells. Specify to use the mean statistic. namespace pr = pronto::raster; int main() { auto in = pr::open<int>("my_file.tif"); auto window = pr::circle(2); auto indicator = pr::mean_generator<int>{}; auto out = pr::moving_window_indicator(in, window, indicator); for(auto&& v : out) { // do something } } "out" is a Raster View, satisfying all the same requirements as "in". https://github.com/ahhz/raster

  19. The assign function forces evaluation of lazy Expression Templates #include <pronto/raster/assign.h> #include <pronto/raster/io.h> #include <cmath> Cheap: Create ET for the sqrt of values in my_file.tif namespace pr = pronto::raster; int main() { auto in = pr::open<int>("my_file.tif"); auto sqrt = pr::transform([](int x){return std::sqrt(x);}, in); auto out = pr::create_from_model<float>("sqrt.tif", in); pr::assign(b, out); } Expensive: Create sqrt.tif and write values https://github.com/ahhz/raster

  20. Design: Runtime polymorphism through type erasure Runtime polymorphism is sometimes required operations specified by user (e.g. Raster Calculator) value type of raster dataset unknown at compile time Type erased class Holds Is a Raster View? any_raster<T> Raster View object with value type T Yes any_blind_raster any_raster<T>, where T is a supported type Has: rows(), cols(), sub_raster( ) Lacks: begin(), end() https://github.com/ahhz/raster

  21. Using any_raster<T> pr::any_raster<int> plus_or_minus(bool do_plus) { auto a = pr::open<int>("a.tif"); Runtime decision auto b = pr::open<int>("b.tif"); if(do_plus) { auto x = pr::transform(std::plus<int>, a, b)); return pr::make_any_raster(x); } else { auto y = pr::transform(std::minus<int>, a, b)); return pr::make_any_raster(y); } x and y are different types; but both are Raster Views with int as value type } https://github.com/ahhz/raster

  22. Using any_blind_raster pr::any_blind_raster a_in= pr::open_any("a.tif"); pr::any_blind_raster b_in= pr::open_any("b.tif"); Opened as the appropriate value type auto a = pr::raster_algebra_wrap(a_in); auto b = pr::raster_algebra_wrap(b_in); auto c = (b-a) * (b-a); Raster algebra made to work with any_blind_raster pr::export_any("out.tif", c.unwrap()); Exported to the appropriate value type Unwrap from raster_algebra_wrapper https://github.com/ahhz/raster

  23. Future music: Parallel processing The sub_raster() requirement of Raster Views combined with the Expression Template design allows doing calculation for only a part of the raster For local operations and moving window indicators only the assign function needs to be parallelized Split the rasters into sub-raster blocks Assign all blocks asynchronously And rest of library needs to be thread safe https://github.com/ahhz/raster

  24. Scale dependent landscape metrics Applications Cellular Automata land use model Fuzzy set map comparison https://github.com/ahhz/raster

  25. Conclusions Requirement Key challenge Solution Transform function Indicator concept Generic moving windows Uses GDAL buffering and LRU Customizable Be able to apply custom local, focal and zonal functions on any number of layers Scalable Work with large raster data sets that exceed available memory Efficient Minimal creation of temporary datasets for intermediary results Using expression template Using non-copying spatial operations Potential for parallelization Flexible Work with wide range of data types with no need for data preprocessing Uses GDAL for data access Usable Idiomatic interface, minimal use of boiler plate code Range based for-loop std::optional Compatible Be able to use in conjunction with other libraries (e.g. for optimization, simulation control, etc.) C++ Simple concepts

  26. Thank you! github.com/ahhz/raster a.hagen-zanker@surrey.ac.uk https://github.com/ahhz/raster

Related


More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#