Skip to content

Commit f62c7da

Browse files
zklausKlaus Zimmermann
andauthored
Add debugging help (#2638)
Co-authored-by: Klaus Zimmermann <klaus.zimmermann@smhi.se>
1 parent ce86017 commit f62c7da

1 file changed

Lines changed: 182 additions & 0 deletions

File tree

doc/sphinx/source/faq.rst

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,185 @@ high-level interface to the `Seaborn <https://seaborn.pydata.org>`__ package
134134
which can also be used to create a large variety of different plots.
135135

136136
See also :ref:`general_purpose_diags`.
137+
138+
Debugging FAQ
139+
=============
140+
141+
Something's going wrong in preprocessing, how can I find out where?
142+
-------------------------------------------------------------------
143+
144+
Sometimes there is a problem in the preprocessing, often because of faulty data.
145+
146+
To locate the problem, the first step is to edit your `config-user.yml` to set
147+
148+
.. code-block:: yaml
149+
150+
log_level: debug
151+
152+
Then run `esmvaltool` again and try to understand the error message. Don't
153+
forget that you can open the error log in the run directory instead of working
154+
only with the terminal output. Usually, the error log ends in a python
155+
traceback. See for example `here <https://realpython.com/python-traceback/>`_
156+
for an introduction to understanding tracebacks.
157+
158+
It can also be helpful to look in the error log directly above the traceback for
159+
more information on what caused the problem.
160+
161+
If the error message is not enough to diagnose the problem, you can "spread out"
162+
the effects of the different preprocessors. For that, edit again
163+
`config-user.yml` to set
164+
165+
.. code-block:: yaml
166+
167+
save_intermediary_cubes: true
168+
remove_preproc_dir: false
169+
170+
This way, you can inspect the output of every preprocessing step individually by
171+
looking at the individual outputs in the `preproc` directory. Usually, the last
172+
existing file can give you a clue on what went wrong.
173+
174+
.. warning::
175+
176+
This can be costly both in storage space and computing time, so be careful to
177+
use as small a dataset as possible to diagnose your problem and to deactivate
178+
the setting when you are done debugging!
179+
180+
I get a `iris.exceptions.ConcatenateError`. What's the problem?
181+
---------------------------------------------------------------
182+
183+
Broadly speaking, the problem is that data that was spread over different files
184+
was supposed to be part of one dataset, but doesn't follow the same conventions.
185+
This can be due to different coordinates, different attributes, or a number of
186+
other differences. Unfortunately, it can be difficult to understand what exactly
187+
is the difference between the data.
188+
189+
To diagnose the problem, first, figure out which netcdf files cause the
190+
issue. If it happens in the preprocessing, refer to `this FAQ
191+
<somethings-going-wrong-in-preprocessing-how-can-I-find-out-where>`_ for some
192+
pointers.
193+
194+
Next, try to understand the differences between the two files. Perhaps the error
195+
message already pointed to the area of difference, for example some attributes
196+
or particular coordinates. In that case you can focus on those first.
197+
198+
How can I compare two (or more) netcdf files?
199+
---------------------------------------------
200+
201+
There are three popular tools/methods to understand the differences between
202+
netcdf files. The first two, `looking at the metadata of the individual files
203+
<inspecting-the-netcdf-file-headers>`_ and `visualizing their data
204+
<visualizing-the-data>`_, are almost always possible and can give you a quick
205+
idea of what's going on. They are, however, often not suited to detailed
206+
comparisons, for example when the actual data contains subtle problems or when
207+
the problem is in the values of coordinates. In those cases, turn to `a more
208+
in-depth look <comparing-data-with-iris>`_ at the data. This last method also
209+
works better when you have a larger collection of files and are not sure where
210+
exactly the problem lies.
211+
212+
Inspecting the netcdf file headers
213+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
214+
215+
You can use the `ncdump` utility to look at the metadata of netcdf files. More
216+
specifically, `ncdump -h my_file.nc` will output the so-called header of the
217+
file that contains information about all the variables present in the file,
218+
along with their units, etc. This includes the coordinate variables. It also
219+
will give you all the global, ie file level, and local, ie variable level
220+
attributes. It will, however, not give you the coordinate values or the data
221+
values itself. It will also not help you with comparison, so you can only
222+
compare the output for two files manually.
223+
224+
Nevertheless, when you want to get a quick overview, or when you have some idea
225+
what to look for, or when the other methods don't work, this is a good starting
226+
point.
227+
228+
Visualizing the data
229+
~~~~~~~~~~~~~~~~~~~~
230+
231+
Often a quick look at the data can reveal the most glaring problems, like
232+
missing or wrong masks, or wrong units. There are a number of tools that can be
233+
used for this, but one of the most basic and almost universally available ones
234+
is `ncview`. This can also be installed with conda from conda-forge.
235+
236+
Just do a quick `ncview my_file.nc` to open the gui. Then select the variable
237+
and use the navigation buttons to flip through the timesteps and, in the case of
238+
3d data, the levels.
239+
240+
Again, this tool doesn't help you with comparison, but you can open two
241+
instances to compare two files in side-by-side.
242+
243+
Comparing data with iris
244+
~~~~~~~~~~~~~~~~~~~~~~~~
245+
246+
`Iris <https://scitools.org.uk/iris/docs/latest/>`_ is a powerful python
247+
framework for working with `CF <http://cfconventions.org/>`_ compliant netcdf
248+
files. It also includes some support for other formats like grib, and pp files.
249+
Iris is the foundation for esmvaltool, but it can also be used on its own. Two
250+
convenient ways to do that are `ipython <https://ipython.org/>`_ and `jupyter
251+
notebooks <https://jupyter.org/>`_. This FAQ cannot cover any of these tools in
252+
great detail, so please refer to their respective documentation for an overview
253+
and in-depth questions. Instead, here we will give just a quick way to
254+
understand differences in a set of netcdf files with iris.
255+
256+
Iris loads data with one of several functions whose names start with
257+
`load`. These functions take a single string or a list of strings that are
258+
interpreted as filenames. They may also contain directories and globs, like
259+
`./my_data/tas_*.nc` to load all surface temperature data from the `my_data`
260+
subdirectory of the current working directory. The iris function will return
261+
either a single `Cube
262+
<https://scitools.org.uk/iris/docs/latest/iris/iris/cube.html#iris.cube.Cube>`_,
263+
or a list of cubes in the form of a `CubeList
264+
<https://scitools.org.uk/iris/docs/latest/iris/iris/cube.html#iris.cube.CubeList>`_.
265+
266+
Often, we want to combine different parts of dataset to form the whole dataset
267+
again. This is accomplished in iris using either a `merge` or a
268+
`concatenate`. Refer to `the iris user guide
269+
<https://scitools.org.uk/iris/docs/latest/userguide/merge_and_concat.html>`_ to
270+
understand the difference.
271+
272+
In fact, it is this `concatenate` that has failed you when you are reading this
273+
FAQ entry.
274+
275+
To find out what went wrong, let's assume we have boiled down the problem to the
276+
two files `tas_1969.nc` and `tas_1970.nc`. Then one way to learn more about the
277+
issue is the following.
278+
279+
.. code-block:: python
280+
281+
import iris
282+
cube_list = iris.load('tas_19*.nc')
283+
cube_list.concatenate_cube()
284+
285+
This will likely produce the exact same error that we started with. While we do
286+
want to do a concatenation, since both files contain several timesteps each, the
287+
output of the corresponding merge function is often more illuminating. So let's
288+
give that a try.
289+
290+
.. code-block:: python
291+
292+
cube_list.merge_cube()
293+
294+
Hopefully, that gives you a better idea of the problem.
295+
296+
If you are dealing with more than two files it can be difficult to figure out
297+
which files are actually the culprits. In that case try
298+
299+
.. code-block:: python
300+
301+
import iris
302+
cube_list = iris.load('tas_*.nc')
303+
concatenated_cube_list = cube_list.concatenate()
304+
print(concatenated_cube_list)
305+
306+
This will concatenate all the consecutive bits it can manage and keep only those
307+
parts separate, that cannot be merged. This way, you can often boil down the
308+
problem to only two or a few cubes. Then you can diagnose those in the same way
309+
as discussed above, eg
310+
311+
.. code-block:: python
312+
313+
concatenated_cube_list.concatenate_cube() # or
314+
concatenated_cube_list.merge_cube()
315+
316+
You can also inspect the attributes and coordinates of the resulting cubes with
317+
a particular focus on the areas of problems pointed to by the output of
318+
`merge_cube`.

0 commit comments

Comments
 (0)