FLEXPART Testing Environment CTBTO WO8
 All Classes Namespaces Files Functions Variables Pages
FlexpartErrors.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 """
3 Created on Mon May 4 15:50:42 2015
4 
5 @author: morton
6 """
7 
8 
9 import logging
10 import numpy as np
11 
12 class FlexpartErrors(object):
13 
14 
15  """
16  A class that takes two FlexpartOutput objects as input and provides
17  methods for calculation of errors on slices, volumes and timeseries.
18 
19  The following arguments are included in most of the calls to methods,
20  so are described here rather than in each method. There are a variety
21  of combinations, which might get confusing, as not all arguments are
22  used in all cases.
23 
24  timestamp : If it has a value, and if this is not a timeseries, then
25  the indicated timestamp is used
26 
27  timestamp_list : if timeseries is True, then this will be used to provide
28  the list of timestamps to use.
29 
30  level : specifies the level to use for a slice. Indexed from 1.
31 
32  level_list : if volume is True, then this will be used to provide the
33  list of levels to use.
34 
35  species : species number to use. Indexed from 1
36 
37  release : release number to use. Indexed from 1
38 
39  age_class : age_class number to use. Indexed from 1
40 
41  wet : if True, use the wet deposition. If dry is also True, the
42  result is non-deterministic
43 
44  dry : if True, use the dry deposition. If wet is also True, the result
45  is non-deterministic
46 
47  timeseries : if True, then it will use a timeseries as defined in
48  timestamp_list. If timestamp_list is None, then a timeseries of
49  all available timestamps will be used
50 
51  volume : if True, then it will use a volume as defined in level_list.
52  If level_list is None, then a volume of all available levels will be
53  used.
54  """
55 
56 
57 
58 
59 
60 
61  def __init__(self, control=None, test=None):
62 
63  """
64  Constructor
65  control: a FlexpartOutput object to be used as control data
66  test: a FlexpartOutput object to be used as test data
67  """
68 
69  # Let's do a bit of a sanity check on equal dimensions. Get
70  # a default volume from each and compare
71  # the dimensions. Also check that timestamps are the same.
72 
73 
74  control_volume_shape = control.get_volume().shape
75  test_volume_shape = test.get_volume().shape
76 
77  control_timestamps = control.get_timestamp_list()
78  test_timestamps = test.get_timestamp_list()
79 
80  if control_volume_shape == test_volume_shape and \
81  control_timestamps == test_timestamps:
82 
83  self._control_output = control
84  self._test_output = test
85 
86  else:
87 
88  self._control_output = None
89  self._test_output = None
90 
91 
92 
93 
94  def get_diff_grid(self, timestamp=None,
95  timestamp_list=None,
96  level=1,
97  level_list=None,
98  species=1,
99  release=1,
100  age_class=1,
101  wet=False,
102  dry=False,
103  timeseries=False,
104  volume=False):
105 
106  """
107  Gets the difference grid as specified by the parameters.
108 
109  Note the True/False values of the last parameters:
110 
111 
112  """
113 
114 
115  # Extract grids from the control and test FlexpartOutput objects.
116  # The grid is defined by the various parameters.
117  control_grid = self._get_grid(flexout_obj=self._control_output,
118  timestamp=timestamp,
119  timestamp_list=timestamp_list,
120  level=level,
121  level_list=level_list,
122  species=species,
123  release=release,
124  age_class=age_class,
125  wet=wet,
126  dry=dry,
127  timeseries=timeseries,
128  volume=volume)
129 
130 
131  test_grid = self._get_grid(flexout_obj=self._test_output,
132  timestamp=timestamp,
133  timestamp_list=timestamp_list,
134  level=level,
135  level_list=level_list,
136  species=species,
137  release=release,
138  age_class=age_class,
139  wet=wet,
140  dry=dry,
141  timeseries=timeseries,
142  volume=volume)
143 
144  diff_grid = test_grid - control_grid
145 
146 
147  return diff_grid
148 
149 
150  def mean_absolute_error(self, timestamp=None,
151  timestamp_list=None,
152  level=1,
153  level_list=None,
154  species=1,
155  release=1,
156  age_class=1,
157  wet=False,
158  dry=False,
159  timeseries=False,
160  volume=False):
161  """
162  Returns the mean absolute error of the test and control grid, as
163  defined by the parameters
164  """
165 
166  diff_grid = self.get_diff_grid(timestamp=timestamp,
167  timestamp_list=timestamp_list,
168  level=level,
169  level_list=level_list,
170  species=species,
171  release=release,
172  age_class=age_class,
173  wet=wet,
174  dry=dry,
175  timeseries=timeseries,
176  volume=volume)
177 
178  return np.absolute(diff_grid).mean()
179 
180 
181  def max_absolute_error(self, timestamp=None,
182  timestamp_list=None,
183  level=1,
184  level_list=None,
185  species=1,
186  release=1,
187  age_class=1,
188  wet=False,
189  dry=False,
190  timeseries=False,
191  volume=False):
192  """
193  Returns the max absolute error of the test and control grid, as
194  defined by the parameters
195  """
196 
197  diff_grid = self.get_diff_grid(timestamp=timestamp,
198  timestamp_list=timestamp_list,
199  level=level,
200  level_list=level_list,
201  species=species,
202  release=release,
203  age_class=age_class,
204  wet=wet,
205  dry=dry,
206  timeseries=timeseries,
207  volume=volume)
208 
209  return np.absolute(diff_grid).max()
210 
211 
212  def max_error(self, timestamp=None,
213  timestamp_list=None,
214  level=1,
215  level_list=None,
216  species=1,
217  release=1,
218  age_class=1,
219  wet=False,
220  dry=False,
221  timeseries=False,
222  volume=False):
223  """
224  Returns the max error of the test and control grid, as
225  defined by the parameters.
226  NOTE - I "think" this is the same as max_abs_error as written,
227  and maybe shouldn't have the key=abs...
228  """
229 
230  diff_grid = self.get_diff_grid(timestamp=timestamp,
231  timestamp_list=timestamp_list,
232  level=level,
233  level_list=level_list,
234  species=species,
235  release=release,
236  age_class=age_class,
237  wet=wet,
238  dry=dry,
239  timeseries=timeseries,
240  volume=volume)
241 
242  return max(diff_grid.max(), diff_grid.min(), key=abs)
243 
244 
245  def mean_bias(self, timestamp=None,
246  timestamp_list=None,
247  level=1,
248  level_list=None,
249  species=1,
250  release=1,
251  age_class=1,
252  wet=False,
253  dry=False,
254  timeseries=False,
255  volume=False):
256  """
257  Returns the mean of the biases of the test and control grid, as
258  defined by the parameters
259  """
260 
261  diff_grid = self.get_diff_grid(timestamp=timestamp,
262  timestamp_list=timestamp_list,
263  level=level,
264  level_list=level_list,
265  species=species,
266  release=release,
267  age_class=age_class,
268  wet=wet,
269  dry=dry,
270  timeseries=timeseries,
271  volume=volume)
272 
273  return diff_grid.mean()
274 
275 
276  def rmse(self, timestamp=None,
277  timestamp_list=None,
278  level=1,
279  level_list=None,
280  species=1,
281  release=1,
282  age_class=1,
283  wet=False,
284  dry=False,
285  timeseries=False,
286  volume=False):
287  """
288  Returns the root mean square error of the test and control grid, as
289  defined by the parameters
290  """
291 
292  diff_grid = self.get_diff_grid(timestamp=timestamp,
293  timestamp_list=timestamp_list,
294  level=level,
295  level_list=level_list,
296  species=species,
297  release=release,
298  age_class=age_class,
299  wet=wet,
300  dry=dry,
301  timeseries=timeseries,
302  volume=volume)
303 
304  return np.sqrt( ( diff_grid**2).mean() )
305 
306 
307  return diff_grid.max()
308 
309 
310 
311 
312 
313 
314 
315 
316  def _get_grid(self, flexout_obj=None,
317  timestamp=None,
318  timestamp_list=None,
319  level=1,
320  level_list=None,
321  species=1,
322  release=1,
323  age_class=1,
324  wet=False,
325  dry=False,
326  timeseries=False,
327  volume=False):
328 
329 
330 
331  """
332  Gets the grid as specified by the parameters. This is a private
333  method and flexout_obj is intended to be the control or test grid
334  that this class contains.
335 
336  Note the True/False values of the last parameters. They will
337  dictate the flow of this routine.
338  """
339 
340  if not timeseries and not volume:
341  # horiz slices
342 
343  if not wet and not dry:
344  the_grid = flexout_obj.get_horiz_slice(
345  timestamp=timestamp,
346  level=level,
347  species=species,
348  release=release,
349  age_class=age_class)
350 
351  else:
352 
353  if wet and dry:
354  logging.error("Bad options - cannot specify both wet and dry")
355  the_grid = None
356  else:
357  if wet: depo_type = 'wet'
358  if dry: depo_type = 'dry'
359 
360  the_grid = flexout_obj.get_deposition(
361  timestamp=timestamp,
362  species=species,
363  release=release,
364  age_class=age_class,
365  depo_type=depo_type)
366 
367 
368  elif volume and not timeseries:
369  # Volume grid
370  the_grid = flexout_obj.get_volume(
371  timestamp=timestamp,
372  level_list=level_list,
373  species=species,
374  release=release,
375  age_class=age_class)
376 
377 
378  elif timeseries and not volume:
379  # Timeseries of horiz slices
380 
381  if not wet and not dry:
382  the_grid = flexout_obj.get_horiz_timeseries(
383  timestamp_list=timestamp_list,
384  level=level,
385  species=species,
386  release=release,
387  age_class=age_class)
388 
389 
390  else:
391 
392  if wet and dry:
393  logging.error("Bad options - cannot specify both wet and dry")
394  the_grid = None
395  else:
396  if wet: depo_type = 'wet'
397  if dry: depo_type = 'dry'
398 
399  the_grid = flexout_obj.get_deposition_timeseries(
400  timestamp_list=timestamp_list,
401  species=species,
402  release=release,
403  age_class=age_class,
404  depo_type=depo_type)
405 
406 
407  elif timeseries and volume:
408  # Timeseries of volumes
409  the_grid = flexout_obj.get_volume_timeseries(
410  timestamp_list=timestamp_list,
411  level_list=level_list,
412  species=species,
413  release=release,
414  age_class=age_class)
415 
416  else:
417  # If we made it here, we have bad combination of options
418  # and can't select a routine to generate the the_grid
419  logging.error("Bad options - cannot generate a the_grid")
420  the_grid = None
421 
422  return the_grid
423 
424 
425 
426