-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtut_gettingstarted.html
268 lines (246 loc) · 20.1 KB
/
tut_gettingstarted.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Getting Started — PyGeode 1.4.1-rc2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/pygtheme.css" />
<link rel="stylesheet" type="text/css" href="_static/plot_directive.css" />
<link rel="stylesheet" type="text/css" href="_static/sg_gallery.css" />
<link rel="stylesheet" type="text/css" href="_static/sg_gallery-binder.css" />
<link rel="stylesheet" type="text/css" href="_static/sg_gallery-dataframe.css" />
<link rel="stylesheet" type="text/css" href="_static/sg_gallery-rendered-html.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<link rel="shortcut icon" href="_static/pygeode_icon.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Basic Operations" href="tut_basics.html" />
<link rel="prev" title="Tutorial" href="tutorial.html" />
<link href="http://fonts.googleapis.com/css?family=Ubuntu:300,300italic,regular,italic,500,500italic,bold,bolditalic" rel="stylesheet" type="text/css">
<link href='http://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700' rel='stylesheet' type='text/css'>
</head><body>
<div class="header" role="banner"><img class="logo" src="_static/pygeode_logo.png" width=79px alt="Logo"/>
<h1 class="heading"><a href="index.html">
<span>PyGeode 1.4.1-rc2 documentation</span></a></h1>
<h2 class="heading"><span>Getting Started</span></h2>
</div>
<div class="topnav" role="navigation" aria-label="top navigation">
<p>
«  <a href="tutorial.html">Tutorial</a>
  ::  
<a class="uplink" href="reference.html">Reference</a>
  ::  
<a class="uplink" href="tutorial.html">Tutorial</a>
  ::  
<a class="uplink" href="gallery/index.html">Gallery</a>
  ::  
<a href="tut_basics.html">Basic Operations</a>  »
</p>
</div>
<div class="content">
<div class="section" id="getting-started">
<h1>Getting Started<a class="headerlink" href="#getting-started" title="Permalink to this headline">¶</a></h1>
<p>We’ll start by taking a look at a couple of synthetic datasets defined in the
tutorial module of PyGeode. The first such dataset can be imported as follows:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [1]: </span><span class="kn">import</span> <span class="nn">pygeode</span> <span class="k">as</span> <span class="nn">pyg</span>
<span class="gp">In [2]: </span><span class="kn">from</span> <span class="nn">pygeode.tutorial</span> <span class="kn">import</span> <span class="n">t1</span>
<span class="gp">In [3]: </span><span class="nb">print</span><span class="p">(</span><span class="n">t1</span><span class="p">)</span>
<span class="go"><Dataset>:</span>
<span class="go">Vars:</span>
<span class="go"> Temp (lat,lon) (31,60)</span>
<span class="go">Axes:</span>
<span class="go"> lat <Lat> : 90 S to 90 N (31 values)</span>
<span class="go"> lon <Lon> : 0 E to 354 E (60 values)</span>
<span class="go">Global Attributes:</span>
<span class="go"> history : Synthetic Temperature data generated by pygeode</span>
</pre></div>
</div>
<p>The dataset <code class="docutils literal notranslate"><span class="pre">t1</span></code> contains one pygeode variable object, <code class="docutils literal notranslate"><span class="pre">Temp</span></code>, which is
defined on a two dimensional grid of 31 latitudes and 60 longitudes. The grid
is defined by the two pygeode axes objects, <code class="docutils literal notranslate"><span class="pre">lat</span></code> and <code class="docutils literal notranslate"><span class="pre">lon</span></code>, which span
from 85 S to 85 N, and from 0 E to 354 E. respectively.</p>
<p>We can take a closer look at our variable <code class="docutils literal notranslate"><span class="pre">Temp</span></code>:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [4]: </span><span class="nb">print</span><span class="p">(</span><span class="n">t1</span><span class="o">.</span><span class="n">Temp</span><span class="p">)</span>
<span class="go"><Var 'Temp'>:</span>
<span class="go"> Units: K Shape: (lat,lon) (31,60)</span>
<span class="go"> Axes:</span>
<span class="go"> lat <Lat> : 90 S to 90 N (31 values)</span>
<span class="go"> lon <Lon> : 0 E to 354 E (60 values)</span>
<span class="go"> Attributes:</span>
<span class="go"> {}</span>
<span class="go"> Type: Add_Var (dtype="float64")</span>
</pre></div>
</div>
<p>Again, we see both physical and numerical details of the grid on which this
variable is defined, as well that the temperatures are defined in degrees
Kelvin.</p>
<p>Finally, we can look as well at one of our axes:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [5]: </span><span class="nb">print</span><span class="p">(</span><span class="n">t1</span><span class="o">.</span><span class="n">lat</span><span class="p">)</span>
<span class="go">lat <Lat> : 90 S to 90 N (31 values)</span>
</pre></div>
</div>
<p>which we could also access as a member of the variable <code class="docutils literal notranslate"><span class="pre">Temp</span></code>: <code class="docutils literal notranslate"><span class="pre">t1.Temp.lat</span></code>.</p>
<p>These three types of objects, variables, axes, and datasets, are the core of
PyGeode. Variables (<a class="reference internal" href="var.html#pygeode.Var" title="pygeode.Var"><code class="xref py py-class docutils literal notranslate"><span class="pre">Var</span></code></a>) encapsulate a scalar field such as temperature
or one component of the wind field. Axes (<a class="reference internal" href="axes.html#pygeode.Axis" title="pygeode.Axis"><code class="xref py py-class docutils literal notranslate"><span class="pre">Axis</span></code></a>), which are in fact
special cases of variables, define the geophysical grid on which the scalar
field exists. Finally, datasets (<a class="reference internal" href="dataset.html#pygeode.Dataset" title="pygeode.Dataset"><code class="xref py py-class docutils literal notranslate"><span class="pre">Dataset</span></code></a>) are containers for variables.
These concepts match reasonably closely to their counterparts in NetCDF files
(and indeed PyGeode works very naturally with NetCDF files). We’ll learn more
about all three soon, but to get a quick feel of what PyGeode can do, let’s try
plotting the contents of our first variable:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="go"># Depending on what python interpreter you are using, you may need to run</span>
<span class="go"># these commands to access the plotting functionality of matplotlib</span>
<span class="gp">In [6]: </span><span class="kn">import</span> <span class="nn">pylab</span> <span class="k">as</span> <span class="nn">pyl</span><span class="p">;</span> <span class="n">pyl</span><span class="o">.</span><span class="n">ion</span><span class="p">();</span>
<span class="gp">In [7]: </span><span class="n">pyg</span><span class="o">.</span><span class="n">showvar</span><span class="p">(</span><span class="n">t1</span><span class="o">.</span><span class="n">Temp</span><span class="p">)</span>
<span class="gh">Out[7]: </span><span class="go"><pygeode.plot.wrappers.AxesWrapper at 0x7f37362c5070></span>
</pre></div>
</div>
<a class="reference internal image-reference" href="_images/t1Temp.png"><img alt="_images/t1Temp.png" src="_images/t1Temp.png" style="width: 5in;" /></a>
<p>PyGeode annotates the axes automatically, and if the Cartopy package is
installed, data on a lat-lon grid is plotted over the outline of the continents
using a cylindrical projection. All plots generated by PyGeode are in fact
generated using the matplotlib library; the plotvar command simply makes many
educated guesses about the type of plot you might want to generate based on the
variable you’ve passed in. Many aspects of the plot can be customized through
the plotvar interface (which we’ll get into later on in this tutorial), but if
you find you can’t tweak things just so, the plot can always be manipulated
using the matplotlib library itself which gives you full control.</p>
<p>Now let’s take a look at a second dataset:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [8]: </span><span class="kn">from</span> <span class="nn">pygeode.tutorial</span> <span class="kn">import</span> <span class="n">t2</span>
<span class="gp">In [9]: </span><span class="nb">print</span><span class="p">(</span><span class="n">t2</span><span class="p">)</span>
<span class="go"><Dataset>:</span>
<span class="go">Vars:</span>
<span class="go"> Temp (time,pres,lat,lon) (3650,20,31,60)</span>
<span class="go"> U (time,pres,lat,lon) (3650,20,31,60)</span>
<span class="go">Axes:</span>
<span class="go"> time <ModelTime365>: Jan 1, 2011 00:00:00 to Dec 31, 2020 00:00:00 (3650 values)</span>
<span class="go"> pres <Pres> : 1000 hPa to 50 hPa (20 values)</span>
<span class="go"> lat <Lat> : 90 S to 90 N (31 values)</span>
<span class="go"> lon <Lon> : 0 E to 354 E (60 values)</span>
<span class="go">Global Attributes:</span>
<span class="go"> history : Synthetic Temperature and Wind data generated by pygeode</span>
</pre></div>
</div>
<p>This is a somewhat more complicated temperature field, now defined on four
dimensions: time, pressure, latitude and longitude. Note this grid has over 350
million data points–enough that the 2010-era laptop this tutorial was first
written on would complain if we attempted to load all of it into memory at once.
This brings us to one of the major guiding assumptions of pygeode - that since
we haven’t done anything that needs the data itself, none of it has yet been
loaded or computed. We can, nonetheless, manipulate this variable as if it has:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [10]: </span><span class="n">Tc</span> <span class="o">=</span> <span class="n">pyg</span><span class="o">.</span><span class="n">climatology</span><span class="p">(</span><span class="n">t2</span><span class="o">.</span><span class="n">Temp</span><span class="p">)</span> <span class="c1"># Compute the climatology</span>
<span class="gp">In [11]: </span><span class="n">Tcz</span> <span class="o">=</span> <span class="n">Tc</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="s1">'lon'</span><span class="p">)</span> <span class="c1"># Compute the zonal mean</span>
<span class="gp">In [12]: </span><span class="nb">print</span><span class="p">(</span><span class="n">Tcz</span><span class="p">)</span>
<span class="go"><Var 'Temp_clim_mean'>:</span>
<span class="go"> Shape: (time,pres,lat) (365,20,31)</span>
<span class="go"> Axes:</span>
<span class="go"> time <ModelTime365>: Jan 1, 00:00:00 to Dec 31, 00:00:00 (365 values)</span>
<span class="go"> pres <Pres> : 1000 hPa to 50 hPa (20 values)</span>
<span class="go"> lat <Lat> : 90 S to 90 N (31 values)</span>
<span class="go"> Attributes:</span>
<span class="go"> {}</span>
<span class="go"> Type: MeanVar (dtype="float64")</span>
<span class="gp">In [13]: </span><span class="n">Tcp</span> <span class="o">=</span> <span class="n">Tc</span> <span class="o">-</span> <span class="n">Tcz</span> <span class="c1"># Compute anomaly from the zonal mean</span>
<span class="gp">In [14]: </span><span class="n">Tcp</span> <span class="o">=</span> <span class="n">Tcp</span><span class="o">.</span><span class="n">rename</span><span class="p">(</span><span class="s2">"T'"</span><span class="p">)</span> <span class="c1"># Rename variable</span>
<span class="gp">In [15]: </span><span class="nb">print</span><span class="p">(</span><span class="n">Tcp</span><span class="p">)</span>
<span class="go"><Var 'T''>:</span>
<span class="go"> Shape: (time,pres,lat,lon) (365,20,31,60)</span>
<span class="go"> Axes:</span>
<span class="go"> time <ModelTime365>: Jan 1, 00:00:00 to Dec 31, 00:00:00 (365 values)</span>
<span class="go"> pres <Pres> : 1000 hPa to 50 hPa (20 values)</span>
<span class="go"> lat <Lat> : 90 S to 90 N (31 values)</span>
<span class="go"> lon <Lon> : 0 E to 354 E (60 values)</span>
<span class="go"> Attributes:</span>
<span class="go"> {}</span>
<span class="go"> Type: RenamedVar (dtype="float64")</span>
</pre></div>
</div>
<p>We’ve now computed (at least an abstract sense) the climatolgical anomaly from
the zonal mean. Note that <code class="docutils literal notranslate"><span class="pre">Tcz</span></code> is defined on a reduced grid (we’ve lost the
<code class="docutils literal notranslate"><span class="pre">Lon</span></code> axis), and it looks and behaves just like any other PyGeode variable;
PyGeode has some automatic logic for properly aligning <code class="docutils literal notranslate"><span class="pre">Tc</span></code> and <code class="docutils literal notranslate"><span class="pre">Tcz</span></code> when
taking their difference. However, no data has yet been loaded, no actual
averages have been taken, and no differences computed, since we haven’t done
anything that needs the data. If we now go and plot the near-surface,
high-latitude anomaly of our synthetic dataset:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [16]: </span><span class="n">pyg</span><span class="o">.</span><span class="n">showvar</span><span class="p">(</span><span class="n">Tcp</span><span class="p">(</span><span class="n">pres</span><span class="o">=</span><span class="mi">1000</span><span class="p">,</span> <span class="n">time</span><span class="o">=</span><span class="s1">'15 Jun 00'</span><span class="p">))</span>
<span class="gh">Out[16]: </span><span class="go"><pygeode.plot.wrappers.AxesWrapper at 0x7f37341da700></span>
</pre></div>
</div>
<a class="reference internal image-reference" href="_images/Tcp.png"><img alt="_images/Tcp.png" src="_images/Tcp.png" style="width: 6in;" /></a>
<p>We now actually need to perform these operations (though only on one pressure
level and one latitude), so PyGeode goes back and accesses the required data
(only), then carries out all of our operations before sending the data off to
matplotlib to produce a nice contour plot.</p>
<p>Implied in the operations above is another principle of PyGeode. Note that
nowhere did we need to remember which dimension of an array corresponded to
time and which corresponded to longitude; nor did we need to know what index
described the 1000 hPa pressure level, or which corresponded to the 15th of
June. Moreover, we could take the difference between two fields (<code class="docutils literal notranslate"><span class="pre">Tc</span></code> and
<code class="docutils literal notranslate"><span class="pre">Tcz</span></code>) which weren’t defined on the same grid–PyGeode takes care of the
broadcasting and alignment of the underlying numpy arrays for us, leaving us to
think about the problem we’re trying to solve in the physical coordinate space
of our data. The underlying mapping is of course still there, and if it’s ever
more convenient to think in the space of the data arrays, you are still free to
do so; the relevant syntax and commands are described later in this tutorial.</p>
<p>‘This is all fine and good,’ you may be thinking, ‘but how do I work with my
own data?’ PyGeode supports a number of data formats, though it works most
naturally with NetCDF (or HDF5) files. As an example, the synthetic dataset
used above can be written out to a NetCDF file (this assumes that a
subdirectory called ‘sample_data’ already exists in your working directory):</p>
<div class="highlight-ipython notranslate" id="tutsavefile"><div class="highlight"><pre><span></span><span class="gp">In [17]: </span><span class="n">pyg</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s1">'sample_data/file.nc'</span><span class="p">,</span> <span class="n">t1</span><span class="p">)</span>
</pre></div>
</div>
<p>and then read back in using:</p>
<div class="highlight-ipython notranslate"><div class="highlight"><pre><span></span><span class="gp">In [18]: </span><span class="n">ds</span> <span class="o">=</span> <span class="n">pyg</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">'sample_data/file.nc'</span><span class="p">)</span>
<span class="gp">In [19]: </span><span class="nb">print</span><span class="p">(</span><span class="n">ds</span><span class="p">)</span>
<span class="go"><Dataset>:</span>
<span class="go">Vars:</span>
<span class="go"> Temp (lat,lon) (31,60)</span>
<span class="go">Axes:</span>
<span class="go"> lat <Lat> : 90 S to 90 N (31 values)</span>
<span class="go"> lon <Lon> : 0 E to 354 E (60 values)</span>
<span class="go">Global Attributes:</span>
<span class="go">{}</span>
</pre></div>
</div>
<p>PyGeode is aware of the metadata in the file and constructs variables and axes
accordingly, following the CF metadata standard used for climate data. Datasets
that span multiple files can be handled as well, and one can tailor these calls
so that PyGeode properly recognizes your data regardless of the metadata in the
file.</p>
<p>This concludes the introductory tutorial. We’ve seen the three basic objects in
PyGeode: variables (<a class="reference internal" href="var.html#pygeode.Var" title="pygeode.Var"><code class="xref py py-class docutils literal notranslate"><span class="pre">Var</span></code></a>), axes (<a class="reference internal" href="axes.html#pygeode.Axis" title="pygeode.Axis"><code class="xref py py-class docutils literal notranslate"><span class="pre">Axis</span></code></a>) and datasets
(<a class="reference internal" href="dataset.html#pygeode.Dataset" title="pygeode.Dataset"><code class="xref py py-class docutils literal notranslate"><span class="pre">Dataset</span></code></a>). We’ve seen examples of how PyGeode carries out all
operations in a ‘lazy’ fashion, delaying all loading and processing of data
until the output is explicitly required. We’ve seen a few examples of the
automatic annotation of plots that PyGeode takes care of for you, and finally
we’ve seen how to save and load data to a file. The next part of these
tutorials gives a deeper introduction to the <a class="reference internal" href="tut_basics.html"><span class="doc">Basic Operations</span></a> that one can
perform on PyGeode variables.</p>
</div>
</div>
<div class="bottomnav" role="navigation" aria-label="bottom navigation">
<p>
«  <a href="tutorial.html">Tutorial</a>
  ::  
<a class="uplink" href="reference.html">Reference</a>
  ::  
<a class="uplink" href="tutorial.html">Tutorial</a>
  ::  
<a class="uplink" href="gallery/index.html">Gallery</a>
  ::  
<a href="tut_basics.html">Basic Operations</a>  »
</p>
</div>
<div class="footer" role="contentinfo">
© Copyright 2020, Mike Neish, Peter Hitchcock.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.3.2.
</div>
</body>
</html>