1Using rio-calc
2==============
3
4Simple raster data processing on the command line is possible using Rasterio's
5rio-calc command. It uses the `snuggs <https://github.com/mapbox/snuggs>`__
6Numpy S-expression engine. The `snuggs README
7<https://github.com/mapbox/snuggs/blob/master/README.rst>`__ explains how
8expressions are written and evaluated in general. This document explains
9Rasterio-specific details of rio-calc and offers some examples.
10
11Expressions
12-----------
13
14Rio-calc expressions look like
15
16.. code-block:: console
17
18    (func|operator arg [*args])
19
20where ``func`` may be the name of any function in the module ``numpy`` or
21one of the rio-calc builtins: ``read``, ``fillnodata``, or ``sieve``; and
22``operator`` may be any of the standard Python arithmetic or logical operators.
23The arguments may themselves be expressions.
24
25Copying a file
26--------------
27
28Here's a trivial example of copying a dataset. The expression ``(read 1)``
29evaluates to all bands of the first input dataset, an array with shape
30``(3, 718, 791)`` in this case.
31
32Note: rio-calc's indexes start at ``1``.
33
34.. code-block:: console
35
36    $ rio calc "(read 1)" tests/data/RGB.byte.tif out.tif
37
38Reversing the band order of a file
39----------------------------------
40
41The expression ``(read i j)`` evaluates to the j-th band of the i-th input
42dataset. The ``asarray`` function collects bands read in reverse order into
43an array with shape ``(3, 718, 791)`` for output.
44
45.. code-block:: console
46
47    $ rio calc "(asarray (read 1 3) (read 1 2) (read 1 1))" tests/data/RGB.byte.tif out.tif
48
49Stacking bands of multiple files
50--------------------------------
51
52Bands can be read from multiple input files. This example is another (slower)
53way to copy a file.
54
55.. code-block:: console
56
57    $ rio calc "(asarray (read 1 1) (read 2 2) (read 3 3))" \
58    > tests/data/RGB.byte.tif tests/data/RGB.byte.tif tests/data/RGB.byte.tif \
59    > out.tif
60
61Named datasets
62--------------
63
64Datasets can be referenced in expressions by name and single bands picked out
65using the ``take`` function.
66
67.. code-block:: console
68
69    $ rio calc "(asarray (take a 3) (take a 2) (take a 1))" \
70    > --name "a=tests/data/RGB.byte.tif" out.tif
71
72The third example, re-done using names, is:
73
74.. code-block:: console
75
76    $ rio calc "(asarray (take a 1) (take b 2) (take b 3))" \
77    > --name "a=tests/data/RGB.byte.tif" --name "b=tests/data/RGB.byte.tif" \
78    > --name "c=tests/data/RGB.byte.tif" out.tif
79
80Read and take
81-------------
82
83The functions ``read`` and ``take`` overlap a bit in the previous examples but
84are rather different. The former involves I/O and the latter does not. You may
85also ``take`` from any array, as in this example.
86
87.. code-block:: console
88
89    $ rio calc "(take (read 1) 1)" tests/data/RGB.byte.tif out.tif
90
91Arithmetic operations
92---------------------
93
94Arithmetic operations can be performed as with Numpy. Here is an example of
95scaling all three bands of a dataset by the same factors.
96
97.. code-block:: console
98
99    $ rio calc "(+ 2 (* 0.95 (read 1)))" tests/data/RGB.byte.tif out.tif
100
101
102Here is a more complicated example of scaling bands by different factors.
103
104
105.. code-block:: console
106
107    $ rio calc "(asarray (+ 2 (* 0.95 (read 1 1))) (+ 3 (* 0.9 (read 1 2))) (+ 4 (* 0.85 (read 1 3))))" tests/data/RGB.byte.tif out.tif
108
109Logical operations
110------------------
111
112Logical operations can be used in conjunction with arithemtic operations. In
113this example, the output values are 255 wherever the input values are greater
114than or equal to 40.
115
116.. code-block:: console
117
118    $ rio calc "(* (>= (read 1) 40) 255)" tests/data/RGB.byte.tif out.tif
119
120