1
- Basic Variable Operations
2
- =========================
1
+ ================
2
+ Basic Operations
3
+ ================
3
4
4
5
.. currentmodule:: pygeode
5
6
6
7
Much of the functionality of PyGeode is found in the operations you can perform
7
8
on Var objects. We'll start with the basics of slicing variables, then move on
8
- to more complicated operations. One important thing to keep in mind, as
9
- discussed in :doc:`gettingstarted `, is that these operations all delayed until
9
+ to more complicated operations. An important thing to keep in mind, as
10
+ discussed in :doc:`tut_gettingstarted `, is that these operations all delayed until
10
11
the data is specifically requested. For instance, one can compute an average
11
12
over longitude as follows:
12
13
13
14
.. ipython::
14
15
16
+ @suppress
17
+ In [6]: import pylab as pyl; pyl.ion();
18
+
15
19
In [1]: import pygeode as pyg
16
20
17
21
In [2]: from pygeode.tutorial import t1
@@ -166,30 +170,33 @@ axes are removed in this unlike numpy slicing, degenerate axes are removed.
166
170
That is, ``t1.Temp[0, 1]`` returns a scalar, while ``t1.Temp(i_lat=0, i_lon=1)``
167
171
returns a two dimensional variable.
168
172
169
- Arithmetic operations
170
- ---------------------
173
+ Arithmetic operations and broadcasting rules
174
+ --------------------------------------------
171
175
172
176
Reference: :doc:`ufunc` and :doc:`var.arith`
173
177
174
- Arithmetic and mathematical operations are also supported by PyGeode. The
178
+ Arithmetic and other mathematical operations are also supported by PyGeode. The
175
179
simplest are unary operations, which are performed elementwise. Most standard
176
- mathematical functions (powers, exponentials, trigonometric functions, etc.) are
177
- supported, and can be found in the main ``pygeode`` module:
180
+ mathematical functions (powers, exponentials, trigonometric functions, etc.)
181
+ are supported, and can be found in the main ``pygeode`` module:
178
182
179
183
.. ipython::
180
184
181
185
@suppress
182
186
In [6]: import pylab as pyl; pyl.ion()
183
187
184
- @showfig log_t1Temp.png width=4in
188
+ @suppress
189
+ In [6]: import matplotlib as mpl; mpl.rc('figure', figsize=(5, 3))
190
+
191
+ @savefig log_t1Temp.png width=4in
185
192
In [8]: pyg.showvar(pyg.log(t1.Temp)) # Plot the natural logarithm of Temp
186
193
187
194
There are some convenience functions included, for instance, most trig functions
188
195
have a version which takes arguments in degrees rather than radians:
189
196
190
197
.. ipython::
191
198
192
- @showfig sind_t1lat.png width=4in
199
+ @savefig sind_t1lat.png width=4in
193
200
In [10]: pyg.showvar(pyg.sind(t1.lat)) # Compute the sine of latitude
194
201
195
202
In most cases the underlying operation is performed by the numpy equivalent,
@@ -199,13 +206,23 @@ variables, so one should get accustomed to including the ``pyg`` prefix. This
199
206
is also a good reason to import pygeode into its own namespace, rather than
200
207
into the top-level namespace itself.
201
208
202
- Standard Python arithmetic operations (``+``, ``-``, ``*``, ``/``, ``**``,
203
- etc.) are also supported and work as one would expect if all the variables are
204
- defined on the same axes. If the variables do not share the same axes, PyGeode
205
- follows a set of rules for automatically broadcasting them so that the
206
- operations behave as one might typically desire - it's important to be aware of
207
- these rules as you can sometimes end up with some unexpected results, so they
208
- are described here in some detail.
209
+ Standard Python binary arithmetic operations (``+``, ``-``, ``*``, ``/``,
210
+ ``**``, etc.) are supported and work as one would expect if all the
211
+ variables are defined on the same axes. Comparison operators (``>``, ``<``, etc.)
212
+ are also supported and produce a boolean variable on the same axes with the result of
213
+ the operation performed elementwise. This can be very useful for masking data,
214
+ since when cast to scalar values, ``True`` is equal to 1 and ``False`` is equal to 0:
215
+
216
+ .. ipython::
217
+
218
+ @savefig t1mask.png width=4in
219
+ In [11]: pyg.showvar(2 + 3 * (t1.Temp > 280.))
220
+
221
+ If the variables do not share the same axes, PyGeode follows a set of rules for
222
+ automatically broadcasting them so that the operations behave as one might
223
+ typically desire - it's important to be aware of these rules as you can
224
+ sometimes end up with some unexpected results, so they are described here in
225
+ some detail.
209
226
210
227
.. _broadcasting:
211
228
@@ -343,18 +360,17 @@ be specified; those that are not will be appended in their present order.
343
360
344
361
.. ipython::
345
362
346
- In[8]: t2.Temp.axes
363
+ In [8]: t2.Temp.axes
347
364
348
- In[9]: print t2.Temp.transpose('lon', 'lat', 'pres', 'time').axes
365
+ In [9]: print t2.Temp.transpose('lon', 'lat', 'pres', 'time').axes
349
366
350
367
:func:`Var.replace_axes()` replaces any or all axes of a variable. The new
351
368
axes must have the same length as those they are replacing.
352
369
353
370
.. ipython::
354
371
355
372
# The logPAxis method returns a log-pressure axis with a given scale height
356
- In[8]: print t2.Temp.replace_axes(pres=t2.pres.logPAxis(H=7000)).axes
357
-
373
+ In [8]: print t2.Temp.replace_axes(pres=t2.pres.logPAxis(H=7000)).axes
358
374
359
375
:func:`Var.squeeze()` removes degenerate axes (those with one or fewer elements).
360
376
As mentioned above, the default selection behaviour is to always return a
@@ -365,11 +381,17 @@ all degenerate axes. Several other methods of calling are also available:
365
381
366
382
.. ipython::
367
383
368
- In[8]: print t2.Temp(time = 4, lon = 20).squeeze().axes
384
+ # Squeeze all degenerate axes
385
+ In [8]: print t2.Temp(time = 4, lon = 20).squeeze()
386
+
387
+ # Squeeze only the time axis (if it is degenerate)
388
+ In [8]: print t2.Temp(time = 4, lon = 20).squeeze('time')
369
389
370
- In[8]: print t2.Temp(time = 4, lon = 20).squeeze('time').axes
390
+ # Select a single value then squeeze the time axis
391
+ In [8]: print t2.Temp.squeeze(time = 4)
371
392
372
- In[8]: print t2.Temp.squeeze(i_time = 3, lon = (20, 40))
393
+ # Select a single value and sqeeze the time axis using a selection prefix
394
+ In [8]: print t2.Temp(s_time = 4, lon = (20, 40))
373
395
374
396
There are also commands to rename variables and their axes
375
397
(:func:`Var.rename()`, :func:`Var.rename_axes()`), for adding axes to a
0 commit comments