1 | |
---|
2 | # FlexpartErrors |
---|
3 | |
---|
4 | |
---|
5 | ## Overview |
---|
6 | |
---|
7 | This is a class intended to provide comparisons between two FLEXPART outputs, presumably a control and a test. It is assumed that both outputs come from the same problem domain so that, essentially, output structure is identical. Users may compare specified horizontal slices and volumes or sub-volumes, at a single timestep or over a time series. Users may also select deposition fields, releases, species and ageclass. The routines necessarily have a number of parameter options, but one can use these with minimal options by accepting default parameters. The following is a simple example of usage. It starts with the creation of *FlexpartOutput* objects for the control and test outputs, and then creating a *FlexpartErrors* object from these. The object can then be used to perform a large number of comparisons between the two datasets. |
---|
8 | |
---|
9 | Before running these sample Python programs, it's necessary to add the flextest directory to your PYTHONPATH - for example |
---|
10 | |
---|
11 | $ export PYTHONPATH=~/git/ctbto/flexpart-testing/flextest |
---|
12 | |
---|
13 | |
---|
14 | This first sample code shows output comparisons using a test and control set of FLEXPART outputs: |
---|
15 | |
---|
16 | import FlexpartErrors |
---|
17 | import flexread.FlexpartOutput as FlexpartOutput |
---|
18 | |
---|
19 | # Location of the control and test Flexpart output directories |
---|
20 | CONTROL = 'output_ecmwf' |
---|
21 | TEST = 'output_ecmwf_unified' |
---|
22 | |
---|
23 | # Create flexpart output objects for control and test |
---|
24 | control_obj = FlexpartOutput.FlexpartOutput(output_dir=CONTROL) |
---|
25 | test_obj = FlexpartOutput.FlexpartOutput(output_dir=TEST) |
---|
26 | |
---|
27 | # Create an errors object for comparing the two output objects |
---|
28 | errors_obj = FlexpartErrors.FlexpartErrors(control=control_obj, |
---|
29 | test=test_obj) |
---|
30 | |
---|
31 | # Calculate the RMSE for the default slice - horizontal slice at level 1, |
---|
32 | # for the approximately "midway" timestep |
---|
33 | RMSE = errors_obj.rmse() |
---|
34 | print 'RMSE for level 1: ' + str(RMSE) |
---|
35 | |
---|
36 | # Calculate max error for the full timeseries of the full volume |
---|
37 | maxerr = errors_obj.max_error(volume=True, timeseries=True) |
---|
38 | print 'Max error for full volume, full timeseries: ' + str(maxerr) |
---|
39 | |
---|
40 | |
---|
41 | |
---|
42 | The FlexpartErrors class expects the following arguments |
---|
43 | |
---|
44 | * *control* - a *FlexpartOutput* object containing data from a control output |
---|
45 | * *test* - a *FlexpartOutput* object containing data from a test output |
---|
46 | |
---|
47 | >Please note that a *FlexpartOutput* object is not able to store data for both a mother domain and a nest. In order to compare nests, it would be necessary to create additional *FlexpartOutput* objects with the **nest=True** flag |
---|
48 | |
---|
49 | It is important to note that deposition grids and concentration grids are compared separately. This next example is lengthy, but tries to illustrate ways that various grids can be extracted and compared. |
---|
50 | |
---|
51 | import FlexpartErrors |
---|
52 | import flexread.FlexpartOutput as FlexpartOutput |
---|
53 | |
---|
54 | # Location of the control and test Flexpart output directories |
---|
55 | CONTROL = 'fp9.02/rundir/output' |
---|
56 | TEST = 'fpwo8/rundir/output' |
---|
57 | |
---|
58 | # Create flexpart output object for the control case |
---|
59 | control_obj = FlexpartOutput.FlexpartOutput(output_dir=CONTROL) |
---|
60 | |
---|
61 | # Demonstration of extracting a default horizontal slice |
---|
62 | hslice = control_obj.get_horiz_slice() |
---|
63 | print 'hslice: ', hslice |
---|
64 | print hslice.shape |
---|
65 | |
---|
66 | # Demonstration of extracting a default dry deposition slice |
---|
67 | dslice = control_obj.get_deposition(depo_type='dry') |
---|
68 | print 'dslice: ', dslice |
---|
69 | print dslice.shape |
---|
70 | print dslice.sum() |
---|
71 | |
---|
72 | # Demonstration of extracting the full timeseries of dry deposition slices |
---|
73 | dtslice = control_obj.get_deposition_timeseries(depo_type='dry') |
---|
74 | print 'dtslice: ', dtslice |
---|
75 | print dtslice.shape |
---|
76 | print dtslice.sum() |
---|
77 | |
---|
78 | # Demonstration of extracting a default wet deposition slice |
---|
79 | wslice = control_obj.get_deposition(depo_type='wet') |
---|
80 | print 'wslice: ', wslice |
---|
81 | print wslice.shape |
---|
82 | print wslice.sum() |
---|
83 | |
---|
84 | |
---|
85 | # Create flexpart output object for the test case |
---|
86 | test_obj = FlexpartOutput.FlexpartOutput(output_dir=TEST) |
---|
87 | |
---|
88 | # Demonstration of extracting a default dry deposition slice |
---|
89 | dslice = test_obj.get_deposition(depo_type='dry') |
---|
90 | print 'dslice: ', dslice |
---|
91 | print dslice.shape |
---|
92 | print dslice.sum() |
---|
93 | |
---|
94 | # Demonstration of extracting a default wet deposition slice |
---|
95 | wslice = test_obj.get_deposition(depo_type='wet') |
---|
96 | print 'wslice: ', wslice |
---|
97 | print wslice.shape |
---|
98 | print wslice.sum() |
---|
99 | |
---|
100 | # Create an errors object for comparing the two output objects |
---|
101 | errors_obj = FlexpartErrors.FlexpartErrors(control=control_obj, |
---|
102 | test=test_obj) |
---|
103 | |
---|
104 | |
---|
105 | # Note that errors_obj (as well as control_obj and test_obj, above) contain |
---|
106 | # EVERYTHING - concentrations, wet/dry depositions, etc. |
---|
107 | |
---|
108 | |
---|
109 | # Looking at diff grid for dry depo |
---|
110 | diff_grid = errors_obj.get_diff_grid(dry=True) |
---|
111 | print 'dry depo diff grid...' |
---|
112 | print diff_grid |
---|
113 | print diff_grid.shape |
---|
114 | print 'sum: ', diff_grid.sum() |
---|
115 | |
---|
116 | # Looking at diff grid for wet depo |
---|
117 | diff_grid = errors_obj.get_diff_grid(wet=True) |
---|
118 | print 'wet depo diff grid...' |
---|
119 | print diff_grid |
---|
120 | print diff_grid.shape |
---|
121 | print 'sum: ', diff_grid.sum() |
---|
122 | |
---|
123 | # Calculate the RMSE for the default conc slice - horizontal slice at level 1, |
---|
124 | # for the approximately "midway" timestep |
---|
125 | RMSE = errors_obj.rmse() |
---|
126 | print 'RMSE for level 1: ' + str(RMSE) |
---|
127 | |
---|
128 | # Calculate max error for the full timeseries of the full concentration volume |
---|
129 | maxerr = errors_obj.max_error(volume=True, timeseries=True) |
---|
130 | print 'Max error for full volume, full timeseries: ' + str(maxerr) |
---|
131 | |
---|
132 | # Calculate max error for the full timeseries of the dry deposition |
---|
133 | maxerr = errors_obj.max_error(timeseries=True, dry=True) |
---|
134 | print 'Max error for wet depo, full timeseries: ' + str(maxerr) |
---|
135 | |
---|
136 | # Calculate max error for the full timeseries of the wet deposition |
---|
137 | maxerr = errors_obj.max_error(timeseries=True, wet=True) |
---|
138 | print 'Max error for wet depo, full timeseries: ' + str(maxerr) |
---|
139 | |
---|
140 | |
---|
141 | |
---|
142 | |
---|
143 | |
---|
144 | |
---|
145 | |
---|
146 | The pydoc representation: |
---|
147 | |
---|
148 | class FlexpartErrors(__builtin__.object) |
---|
149 | | A class that takes two FlexpartOutput objects as input and provides |
---|
150 | | methods for calculation of errors on slices, volumes and timeseries. |
---|
151 | | |
---|
152 | | The following arguments are included in most of the calls to methods, |
---|
153 | | so are described here rather than in each method. There are a variety |
---|
154 | | of combinations, which might get confusing, as not all arguments are |
---|
155 | | used in all cases. |
---|
156 | | |
---|
157 | | timestamp : If it has a value, and if this is not a timeseries, then |
---|
158 | | the indicated timestamp is used |
---|
159 | | |
---|
160 | | timestamp_list : if timeseries is True, then this will be used to provide |
---|
161 | | the list of timestamps to use. |
---|
162 | | |
---|
163 | | level : specifies the level to use for a slice. Indexed from 1. |
---|
164 | | |
---|
165 | | level_list : if volume is True, then this will be used to provide the |
---|
166 | | list of levels to use. |
---|
167 | | |
---|
168 | | species : species number to use. Indexed from 1 |
---|
169 | | |
---|
170 | | release : release number to use. Indexed from 1 |
---|
171 | | |
---|
172 | | age_class : age_class number to use. Indexed from 1 |
---|
173 | | |
---|
174 | | wet : if True, use the wet deposition. If dry is also True, the returned value will be None |
---|
175 | | |
---|
176 | | |
---|
177 | | dry : if True, use the dry deposition. If wet is also True, the returned value will be None |
---|
178 | | |
---|
179 | | timeseries : if True, then it will use a timeseries as defined in |
---|
180 | | timestamp_list. If timestamp_list is None, then a timeseries of |
---|
181 | | all available timestamps will be used |
---|
182 | | |
---|
183 | | volume : if True, then it will use a volume as defined in level_list. |
---|
184 | | If level_list is None, then a volume of all available levels will be |
---|
185 | | used. |
---|
186 | | |
---|
187 | | Methods defined here: |
---|
188 | | |
---|
189 | | __init__(self, control=None, test=None) |
---|
190 | | Constructor |
---|
191 | | control: a FlexpartOutput object to be used as control data |
---|
192 | | test: a FlexpartOutput object to be used as test data |
---|
193 | | |
---|
194 | | get_diff_grid(self, timestamp=None, timestamp_list=None, level=1, level_list=None, species=1, release=1, age_class=1, wet=False, dry=False, timeseries=False, volume=False) |
---|
195 | | Gets the difference grid as specified by the parameters. |
---|
196 | | |
---|
197 | | Note the True/False values of the last parameters: |
---|
198 | | |
---|
199 | | max_absolute_error(self, timestamp=None, timestamp_list=None, level=1, level_list=None, species=1, release=1, age_class=1, wet=False, dry=False, timeseries=False, volume=False) |
---|
200 | | Returns the max absolute error of the test and control grid, as |
---|
201 | | defined by the parameters |
---|
202 | | |
---|
203 | | max_error(self, timestamp=None, timestamp_list=None, level=1, level_list=None, species=1, release=1, age_class=1, wet=False, dry=False, timeseries=False, volume=False) |
---|
204 | | Returns the max magnitude error of the test and control grid, as |
---|
205 | | defined by the parameters |
---|
206 | | |
---|
207 | | mean_absolute_error(self, timestamp=None, timestamp_list=None, level=1, level_list=None, species=1, release=1, age_class=1, wet=False, dry=False, timeseries=False, volume=False) |
---|
208 | | Returns the mean absolute error of the test and control grid, as |
---|
209 | | defined by the parameters |
---|
210 | | |
---|
211 | | mean_bias(self, timestamp=None, timestamp_list=None, level=1, level_list=None, species=1, release=1, age_class=1, wet=False, dry=False, timeseries=False, volume=False) |
---|
212 | | Returns the mean of the biases of the test and control grid, as |
---|
213 | | defined by the parameters |
---|
214 | | |
---|
215 | | rmse(self, timestamp=None, timestamp_list=None, level=1, level_list=None, species=1, release=1, age_class=1, wet=False, dry=False, timeseries=False, volume=False) |
---|
216 | | Returns the max absolute error of the test and control grid, as |
---|
217 | | defined by the parameters |
---|
218 | |
---|
219 | |
---|
220 | |
---|
221 | |
---|
222 | |
---|
223 | ## Issues |
---|
224 | |
---|
225 | * If wet or dry deposition is specified in the arguments, and there is no deposition in the dataset, I think this may crash |
---|
226 | * There is now checking whether both dry and wet deposition arguments are set to True. If this is the case, the returned grid will be None, and something will end up crashing. |
---|
227 | * See the issues in [FlexpartOutput](FlexpartOutput.md) that describe the ability to create customised timeseries and volumes - this flexibility allows the user to get into trouble if not careful |
---|
228 | |
---|
229 | |
---|
230 | |
---|
231 | |
---|
232 | |
---|