105 error.append(SpecWarning('Dimension {0} should be unlimited but it is not.'.format(dimension_name))) |
107 error.append(SpecWarning('Dimension {0} should be unlimited but it is not.'.format(dimension_name))) |
106 else: |
108 else: |
107 check_passed = True |
109 check_passed = True |
108 else: |
110 else: |
109 check_passed = True |
111 check_passed = True |
110 error.append(SpecError('Dimension {0} should be unlimited, but was not found in the file.'.format(dimension_name))) |
112 error.append( |
111 |
113 SpecError('Dimension {0} should be unlimited, but was not found in the file.'.format(dimension_name))) |
|
114 |
112 self.check_passed = check_passed |
115 self.check_passed = check_passed |
113 self.error = error |
116 self.error = error |
114 |
117 |
115 return check_passed, error |
118 return check_passed, error |
116 |
119 |
117 |
120 |
118 class VariableMandatory(GenericSpecification): |
121 class VariableMandatory(GenericSpecification): |
119 def __init__(self, is_mandatory = True): |
122 def __init__(self, is_mandatory=True): |
120 self.block_next = True # if true the next checks for this variable will not be performed. |
123 self.block_next = True # if true the next checks for this variable will not be performed. |
121 self.is_mandatory = is_mandatory |
124 self.is_mandatory = is_mandatory |
122 |
125 |
123 def check(self, netcdf_file, variable_name): |
126 def check(self, netcdf_file, variable_name): |
124 the_variable = netcdf_file.variables.get(variable_name, None) |
127 the_variable = netcdf_file.variables.get(variable_name, None) |
125 error = [] |
128 error = [] |
126 |
129 |
127 if the_variable != None: |
130 if the_variable != None: |
128 # If the variable is found in the file |
131 # If the variable is found in the file |
129 self.variable_exists = True |
132 self.variable_exists = True |
130 check_passed = True |
133 check_passed = True |
131 |
134 |
132 else: |
135 else: |
133 self.variable_exists = False |
136 self.variable_exists = False |
134 if self.is_mandatory: |
137 if self.is_mandatory: |
135 # If a mandatory variable is not found in the file |
138 # If a mandatory variable is not found in the file |
136 check_passed = False |
139 check_passed = False |
137 error.append(SpecError('The variable {0} is obligatory but was not found in the file.'.format(variable_name))) |
140 error.append( |
|
141 SpecError('The variable {0} is obligatory but was not found in the file.'.format(variable_name))) |
138 else: |
142 else: |
139 check_passed = True |
143 check_passed = True |
140 error.append(SpecNotification('The optional variable {0} was not found in the file.'.format(variable_name))) |
144 error.append( |
141 |
145 SpecNotification('The optional variable {0} was not found in the file.'.format(variable_name))) |
|
146 |
142 self.check_passed = check_passed |
147 self.check_passed = check_passed |
143 self.error = error |
148 self.error = error |
144 |
149 |
145 return check_passed, error |
150 return check_passed, error |
146 |
151 |
147 @property |
152 @property |
148 def continue_check(self): |
153 def continue_check(self): |
149 if (not self.variable_exists) and (self.block_next): |
154 if (not self.variable_exists) and (self.block_next): |
150 return False |
155 return False |
151 else: |
156 else: |
152 return True |
157 return True |
153 |
158 |
|
159 |
154 class VariableDimensions(GenericSpecification): |
160 class VariableDimensions(GenericSpecification): |
155 def __init__(self, dimensions): |
161 def __init__(self, dimensions): |
156 self.dimensions = dimensions |
162 self.dimensions = dimensions |
157 |
163 |
158 def check(self, netcdf_file, variable_name): |
164 def check(self, netcdf_file, variable_name): |
159 the_variable = netcdf_file.variables.get(variable_name, None) |
165 the_variable = netcdf_file.variables.get(variable_name, None) |
160 |
166 |
161 if the_variable != None: |
167 if the_variable != None: |
162 variable_dimensions = list(the_variable.dimensions) |
168 variable_dimensions = list(the_variable.dimensions) |
163 error = [] |
169 error = [] |
164 check_passed = True |
170 check_passed = True |
165 for dimension in self.dimensions: |
171 for dimension in self.dimensions: |
166 if not (dimension in variable_dimensions): |
172 if not (dimension in variable_dimensions): |
167 check_passed = False |
173 check_passed = False |
168 error.append(SpecError("Variable {0} does not have dimension {1}.".format(variable_name, dimension))) |
174 error.append( |
169 |
175 SpecError("Variable {0} does not have dimension {1}.".format(variable_name, dimension))) |
|
176 |
170 # If all dimensions are present, check if the variables are in the |
177 # If all dimensions are present, check if the variables are in the |
171 # correct order. |
178 # correct order. |
172 if check_passed: |
179 if check_passed: |
173 if list(self.dimensions) != variable_dimensions: |
180 if list(self.dimensions) != variable_dimensions: |
174 check_passed = False |
181 check_passed = False |
175 error.append(SpecError("Variable {0} has wrong dimension order: {1} instead of {2}.".format(variable_name, |
182 error.append( |
176 variable_dimensions, |
183 SpecError("Variable {0} has wrong dimension order: {1} instead of {2}.".format(variable_name, |
177 list(self.dimensions)))) |
184 variable_dimensions, |
|
185 list( |
|
186 self.dimensions)))) |
178 for dimension in variable_dimensions: |
187 for dimension in variable_dimensions: |
179 if dimension not in self.dimensions: |
188 if dimension not in self.dimensions: |
180 error.append(SpecWarning('Dimension {0} found in variable {1} but is not defined in the specifications'.format(dimension, variable_name))) |
189 error.append(SpecWarning( |
181 |
190 'Dimension {0} found in variable {1} but is not defined in the specifications'.format(dimension, |
|
191 variable_name))) |
|
192 |
182 else: |
193 else: |
183 check_passed = False |
194 check_passed = False |
184 error = [SpecError('Variable {0} should be checked for dimensions, but was not found in the file.'.format(variable_name)),] |
195 error = [SpecError('Variable {0} should be checked for dimensions, but was not found in the file.'.format( |
185 |
196 variable_name)), ] |
|
197 |
186 self.check_passed = check_passed |
198 self.check_passed = check_passed |
187 self.error = error |
199 self.error = error |
188 |
200 |
189 return check_passed, error |
201 return check_passed, error |
190 |
202 |
191 |
203 |
192 class VariableType(GenericSpecification): |
204 class VariableType(GenericSpecification): |
193 def __init__(self, dtype): |
205 def __init__(self, dtype): |
194 self.dtype = dtype |
206 self.dtype = dtype |
195 |
207 |
196 def check(self, netcdf_file, variable_name): |
208 def check(self, netcdf_file, variable_name): |
197 the_variable = netcdf_file.variables.get(variable_name, None) |
209 the_variable = netcdf_file.variables.get(variable_name, None) |
198 error = [] |
210 error = [] |
199 |
211 |
200 if the_variable != None: |
212 if the_variable != None: |
201 # Get the internal python type and not the numpy.dtype. |
213 # Get the internal python type and not the numpy.dtype. |
202 # The conversions guarantee (?) that a single element is always returned |
214 # The conversions guarantee (?) that a single element is always returned |
203 variable_type_python = type(np.asscalar(np.asarray(np.asarray(the_variable[:]).item(0)))) |
215 variable_type_python = type(np.asscalar(np.asarray(np.asarray(the_variable[:]).item(0)))) |
204 |
216 |
205 if not (variable_type_python == self.dtype): |
217 if not (variable_type_python == self.dtype): |
206 check_passed = False |
218 check_passed = False |
207 error.append(SpecError('Variable {0} is of type {1} while it should be {2}'.format(variable_name, the_variable.dtype, self.dtype))) |
219 error.append(SpecError( |
|
220 'Variable {0} is of type {1} while it should be {2}'.format(variable_name, the_variable.dtype, |
|
221 self.dtype))) |
208 else: |
222 else: |
209 check_passed = True |
223 check_passed = True |
210 else: |
224 else: |
211 check_passed = False |
225 check_passed = False |
212 error.append(SpecError('Variable {0} should be checked for type, but was not found in the file.'.format(variable_name))) |
226 error.append(SpecError( |
213 |
227 'Variable {0} should be checked for type, but was not found in the file.'.format(variable_name))) |
|
228 |
214 self.check_passed = check_passed |
229 self.check_passed = check_passed |
215 self.error = error |
230 self.error = error |
216 |
231 |
217 return check_passed, error |
232 return check_passed, error |
218 |
233 |
219 |
234 |
220 class AttributeMandatory(GenericSpecification): |
235 class AttributeMandatory(GenericSpecification): |
221 def __init__(self, is_mandatory = True): |
236 def __init__(self, is_mandatory=True): |
222 self.block_next = True # if true the next checks for this variable will not be performed. |
237 self.block_next = True # if true the next checks for this variable will not be performed. |
223 self.is_mandatory = is_mandatory |
238 self.is_mandatory = is_mandatory |
224 |
239 |
225 def check(self, netcdf_file, attribute_name): |
240 def check(self, netcdf_file, attribute_name): |
226 the_attribute = getattr(netcdf_file, attribute_name, None) |
241 the_attribute = getattr(netcdf_file, attribute_name, None) |
227 error = [] |
242 error = [] |
228 |
243 |
229 if the_attribute: |
244 if the_attribute: |
230 # If the variable is found in the file |
245 # If the variable is found in the file |
231 self.attribute_exists = True |
246 self.attribute_exists = True |
232 check_passed = True |
247 check_passed = True |
233 |
248 |
234 else: |
249 else: |
235 self.attribute_exists = False |
250 self.attribute_exists = False |
236 if self.is_mandatory: |
251 if self.is_mandatory: |
237 # If a mandatory variable is not found in the file |
252 # If a mandatory variable is not found in the file |
238 check_passed = False |
253 check_passed = False |
239 error.append(SpecError('The attribute {0} is obligatory but was not found in the file.'.format(attribute_name))) |
254 error.append( |
|
255 SpecError('The attribute {0} is obligatory but was not found in the file.'.format(attribute_name))) |
240 else: |
256 else: |
241 check_passed = True |
257 check_passed = True |
242 error.append(SpecNotification('The optional attribute {0} was not found in the file.'.format(attribute_name))) |
258 error.append( |
243 |
259 SpecNotification('The optional attribute {0} was not found in the file.'.format(attribute_name))) |
|
260 |
244 self.check_passed = check_passed |
261 self.check_passed = check_passed |
245 self.error = error |
262 self.error = error |
246 |
263 |
247 return check_passed, error |
264 return check_passed, error |
248 |
265 |
249 @property |
266 @property |
250 def continue_check(self): |
267 def continue_check(self): |
251 if (not self.attribute_exists) and (self.block_next): |
268 if (not self.attribute_exists) and (self.block_next): |
252 return False |
269 return False |
253 else: |
270 else: |
254 return True |
271 return True |
255 |
272 |
256 |
273 |
257 class AttributeType(GenericSpecification): |
274 class AttributeType(GenericSpecification): |
258 def __init__(self, dtype, block_next = True): |
275 def __init__(self, dtype, block_next=True): |
259 self.block_next = block_next |
276 self.block_next = block_next |
260 self.dtype = dtype |
277 self.dtype = dtype |
261 |
278 |
262 def check(self, netcdf_file, attribute_name): |
279 def check(self, netcdf_file, attribute_name): |
263 the_attribute = getattr(netcdf_file, attribute_name, None) |
280 the_attribute = getattr(netcdf_file, attribute_name, None) |
264 error = [] |
281 error = [] |
265 |
282 |
266 if the_attribute: |
283 if the_attribute: |
267 # Get the internal python type and not the numpy.dtype. |
284 # Get the internal python type and not the numpy.dtype. |
268 # The conversions guarantee (?) that a single element is always returned |
285 # The conversions guarantee (?) that a single element is always returned |
269 try: |
286 try: |
270 attribute_type_python = type(np.asscalar(np.asarray(np.asarray(the_attribute[:]).item(0)))) |
287 attribute_type_python = type(np.asscalar(np.asarray(np.asarray(the_attribute[:]).item(0)))) |
271 except: |
288 except: |
272 attribute_type_python = type(np.asscalar(the_attribute)) |
289 attribute_type_python = type(np.asscalar(the_attribute)) |
273 |
290 |
274 if not (attribute_type_python == self.dtype): |
291 if not (attribute_type_python == self.dtype): |
275 check_passed = False |
292 check_passed = False |
276 error.append(SpecError('Attribute {0} is of type {1} while it should be {2}'.format(attribute_name, type(the_attribute).__name__, self.dtype.__name__))) |
293 error.append(SpecError('Attribute {0} is of type {1} while it should be {2}'.format(attribute_name, |
|
294 type( |
|
295 the_attribute).__name__, |
|
296 self.dtype.__name__))) |
277 else: |
297 else: |
278 error = None |
298 error = None |
279 check_passed = True |
299 check_passed = True |
280 else: |
300 else: |
281 check_passed = False |
301 check_passed = False |
282 error.append(SpecError('Attribute {0} should be checked for type, but was not found in the file.'.format(attribute_name))) |
302 error.append(SpecError( |
283 |
303 'Attribute {0} should be checked for type, but was not found in the file.'.format(attribute_name))) |
|
304 |
284 self.check_passed = check_passed |
305 self.check_passed = check_passed |
285 self.error = error |
306 self.error = error |
286 |
307 |
287 return check_passed, error |
308 return check_passed, error |
288 |
309 |
289 @property |
310 @property |
290 def continue_check(self): |
311 def continue_check(self): |
291 if (not self.check_passed) and (self.block_next): |
312 if (not self.check_passed) and (self.block_next): |
347 with FileChecker(filename, specs) as file_checker: |
369 with FileChecker(filename, specs) as file_checker: |
348 file_checker.run_checks() |
370 file_checker.run_checks() |
349 file_checker.print_report('error') |
371 file_checker.print_report('error') |
350 |
372 |
351 """ |
373 """ |
352 |
374 |
353 |
|
354 def __init__(self, filepath, specs): |
375 def __init__(self, filepath, specs): |
355 self.file = None |
376 self.file = None |
356 self.checks_run = False |
377 self.checks_run = False |
357 self.filepath = filepath |
378 self.filepath = filepath |
358 self.filename = os.path.basename(filepath) |
379 self.filename = os.path.basename(filepath) |
359 self.specs = specs |
380 self.specs = specs |
360 self.check_results = {} |
381 self.check_results = {} |
361 self.check_results['general'] = [] |
382 self.check_results['general'] = [] |
362 |
383 |
363 def __enter__(self): |
384 def __enter__(self): |
364 self.open_file() |
385 self.open_file() |
365 return self |
386 return self |
366 |
387 |
367 def __exit__(self, type, value, traceback): |
388 def __exit__(self, type, value, traceback): |
368 if self.file: |
389 if self.file: |
369 self.file.close() |
390 self.file.close() |
370 |
391 |
371 def open_file(self): |
392 def open_file(self): |
372 try: |
393 try: |
373 self.file = netcdf.Dataset(self.filepath) |
394 self.file = netcdf.Dataset(self.filepath) |
374 except: |
395 except: |
375 self.check_results['general'].append(SpecError('Could not open file {0}.'.format(self.filename))) |
396 self.check_results['general'].append(SpecError('Could not open file {0}.'.format(self.filename))) |
376 |
397 |
377 def close_file(self): |
398 def close_file(self): |
378 self.file.close() |
399 self.file.close() |
379 |
400 |
380 def run_checks(self): |
401 def run_checks(self): |
381 if self.file: |
402 if self.file: |
382 self.check_file() |
403 self.check_file() |
383 self.check_attributes() |
404 self.check_attributes() |
384 self.check_dimensions() |
405 self.check_dimensions() |
385 self.check_variables() |
406 self.check_variables() |
386 self.checks_run = True |
407 self.checks_run = True |
387 |
408 |
388 def check_file(self): |
409 def check_file(self): |
389 self.check_results['file'] = [] |
410 self.check_results['file'] = [] |
390 |
411 |
391 try: |
412 try: |
392 specs_file = self.specs['file'] |
413 specs_file = self.specs['file'] |
393 except: |
414 except: |
394 specs_file = [] |
415 specs_file = [] |
395 |
416 |
396 for file_spec in specs_file: |
417 for file_spec in specs_file: |
397 check_passed, error = file_spec.check(self.file, self.filename) |
418 check_passed, error = file_spec.check(self.file, self.filename) |
398 |
419 |
399 if error: |
420 if error: |
400 self.check_results['file'].extend(list(error)) |
421 self.check_results['file'].extend(list(error)) |
401 |
422 |
402 if not file_spec.continue_check: |
423 if not file_spec.continue_check: |
403 break |
424 break |
404 |
425 |
405 def check_attributes(self): |
426 def check_attributes(self): |
406 """ Check if attributes are according to specs """ |
427 """ Check if attributes are according to specs """ |
407 |
428 |
408 self.check_results['attributes'] = [] |
429 self.check_results['attributes'] = [] |
409 |
430 |
410 try: |
431 try: |
411 spec_attributes = self.specs['attributes'].keys() |
432 spec_attributes = self.specs['attributes'].keys() |
412 except: |
433 except: |
413 spec_attributes = [] |
434 spec_attributes = [] |
414 |
435 |
415 for attribute_name in spec_attributes: |
436 for attribute_name in spec_attributes: |
416 attribute_specs = self.specs['attributes'][attribute_name] |
437 attribute_specs = self.specs['attributes'][attribute_name] |
417 for attribute_spec in attribute_specs: |
438 for attribute_spec in attribute_specs: |
418 check_passed, error = attribute_spec.check(self.file, attribute_name) |
439 check_passed, error = attribute_spec.check(self.file, attribute_name) |
419 |
440 |
420 if error: |
441 if error: |
421 self.check_results['attributes'].extend(list(error)) |
442 self.check_results['attributes'].extend(list(error)) |
422 |
443 |
423 if not attribute_spec.continue_check: |
444 if not attribute_spec.continue_check: |
424 break # Don't continue checking specifications if a blocking check failed. |
445 break # Don't continue checking specifications if a blocking check failed. |
425 |
446 |
426 for attribute_name in self.file.ncattrs(): |
447 for attribute_name in self.file.ncattrs(): |
427 if attribute_name not in spec_attributes: |
448 if attribute_name not in spec_attributes: |
428 self.check_results['attributes'].append(SpecWarning('Attribute {0} found in the file but is not defined in the specifications'.format(attribute_name))) |
449 self.check_results['attributes'].append(SpecWarning( |
429 |
450 'Attribute {0} found in the file but is not defined in the specifications'.format(attribute_name))) |
|
451 |
430 def check_dimensions(self): |
452 def check_dimensions(self): |
431 """ Check if dimension are according to specs """ |
453 """ Check if dimension are according to specs """ |
432 self.check_results['dimensions'] = [] |
454 self.check_results['dimensions'] = [] |
433 |
455 |
434 try: |
456 try: |
435 spec_dimensions = self.specs['dimensions'].keys() |
457 spec_dimensions = self.specs['dimensions'].keys() |
436 except: |
458 except: |
437 spec_dimensions = [] |
459 spec_dimensions = [] |
438 |
460 |
439 |
|
440 for dimension_name in spec_dimensions: |
461 for dimension_name in spec_dimensions: |
441 dimension_specs = self.specs['dimensions'][dimension_name] |
462 dimension_specs = self.specs['dimensions'][dimension_name] |
442 for dimension_spec in dimension_specs: |
463 for dimension_spec in dimension_specs: |
443 check_passed, error = dimension_spec.check(self.file, dimension_name) |
464 check_passed, error = dimension_spec.check(self.file, dimension_name) |
444 |
465 |
445 if error: |
466 if error: |
446 self.check_results['dimensions'].extend(list(error)) |
467 self.check_results['dimensions'].extend(list(error)) |
447 |
468 |
448 if not dimension_spec.continue_check: |
469 if not dimension_spec.continue_check: |
449 break # Don't continue checking specifications if a blocking check failed. |
470 break # Don't continue checking specifications if a blocking check failed. |
450 |
471 |
451 for dimension in self.file.dimensions: |
472 for dimension in self.file.dimensions: |
452 if dimension not in spec_dimensions: |
473 if dimension not in spec_dimensions: |
453 self.check_results['dimensions'].append(SpecWarning('Dimension {0} found in the file but is not defined in the specifications'.format(dimension))) |
474 self.check_results['dimensions'].append(SpecWarning( |
454 |
475 'Dimension {0} found in the file but is not defined in the specifications'.format(dimension))) |
|
476 |
455 def check_variables(self): |
477 def check_variables(self): |
456 """ Check if variables are according to specs """ |
478 """ Check if variables are according to specs """ |
457 |
479 |
458 self.check_results['variables'] = [] |
480 self.check_results['variables'] = [] |
459 |
481 |
460 try: |
482 try: |
461 spec_variables = self.specs['variables'].keys() |
483 spec_variables = self.specs['variables'].keys() |
462 except: |
484 except: |
463 spec_variables = [] |
485 spec_variables = [] |
464 |
486 |
465 for variable_name in spec_variables: |
487 for variable_name in spec_variables: |
466 variable_specs = self.specs['variables'][variable_name] |
488 variable_specs = self.specs['variables'][variable_name] |
467 for variable_spec in variable_specs: |
489 for variable_spec in variable_specs: |
468 check_passed, error = variable_spec.check(self.file, variable_name) |
490 check_passed, error = variable_spec.check(self.file, variable_name) |
469 |
491 |
470 if error: |
492 if error: |
471 self.check_results['variables'].extend(list(error)) |
493 self.check_results['variables'].extend(list(error)) |
472 |
494 |
473 if not variable_spec.continue_check: |
495 if not variable_spec.continue_check: |
474 break # Don't continue checking specifications if a blocking check failed. |
496 break # Don't continue checking specifications if a blocking check failed. |
475 |
497 |
476 for variable_name in self.file.variables: |
498 for variable_name in self.file.variables: |
477 if variable_name not in spec_variables: |
499 if variable_name not in spec_variables: |
478 self.check_results['variables'].append(SpecWarning('Variable {0} found in the file but is not defined in the specifications'.format(variable_name))) |
500 self.check_results['variables'].append(SpecWarning( |
479 |
501 'Variable {0} found in the file but is not defined in the specifications'.format(variable_name))) |
480 def file_ok(self, level = 'error'): |
502 |
|
503 def file_ok(self, level='error'): |
481 """ Check if the file checked is ok. What ok means is defined by the level variable """ |
504 """ Check if the file checked is ok. What ok means is defined by the level variable """ |
482 |
505 |
483 status = None |
506 status = None |
484 if self.checks_run: |
507 if self.checks_run: |
485 status = True |
508 status = True |
486 for category, result_list in self.check_results.items(): |
509 for category, result_list in self.check_results.items(): |
487 for result in result_list: |
510 for result in result_list: |
488 if ERROR_ORDER[result.level] >= ERROR_ORDER[level]: |
511 if ERROR_ORDER[result.level] >= ERROR_ORDER[level]: |
489 status = False |
512 status = False |
490 |
513 |
491 return status |
514 return status |
492 |
515 |
493 def results_for_level(self, level): |
516 def results_for_level(self, level): |
494 """ Returns all the results of a specific level """ |
517 """ Returns all the results of a specific level """ |
495 results = None |
518 results = None |
496 if self.checks_run: |
519 if self.checks_run: |
497 results = [] |
520 results = [] |
498 for category, result_list in self.check_results.items(): |
521 for category, result_list in self.check_results.items(): |
499 for result in result_list: |
522 for result in result_list: |
500 if ERROR_ORDER[result.level] == ERROR_ORDER[level]: |
523 if ERROR_ORDER[result.level] == ERROR_ORDER[level]: |
501 results.append(result) |
524 results.append(result) |
502 |
525 |
503 return results |
526 return results |
504 |
527 |
505 def results_by_level(self): |
528 def results_by_level(self): |
506 """ Returns a dictionary with the results by level. """ |
529 """ Returns a dictionary with the results by level. """ |
507 |
530 |
508 results = {} |
531 results = {} |
509 for level, order in ERROR_ORDER.items(): |
532 for level, order in ERROR_ORDER.items(): |
510 results[level] = self.results_for_level(level) |
533 results[level] = self.results_for_level(level) |
511 |
534 |
512 return results |
535 return results |
513 |
536 |
514 def result_count(self): |
537 def result_count(self): |
515 """ Returns a dictionary with the number of results per category. """ |
538 """ Returns a dictionary with the number of results per category. """ |
516 |
539 |
517 result_number = {} |
540 result_number = {} |
518 results = self.results_by_level() |
541 results = self.results_by_level() |
519 |
542 |
520 for category, error_list in results.items(): |
543 for category, error_list in results.items(): |
521 if error_list is None: |
544 if error_list is None: |
522 result_number[category] = 0 |
545 result_number[category] = 0 |
523 else: |
546 else: |
524 result_number[category] = len(error_list) |
547 result_number[category] = len(error_list) |
525 return result_number |
548 return result_number |
526 |
549 |
527 def print_report(self, level): |
550 def print_report(self, level): |
528 """ Print a report for the given level. """ |
551 """ Print a report for the given level. """ |
529 |
552 |
530 print header_template.format(self, self.result_count()) |
553 print header_template.format(self, self.result_count()) |
531 |
554 |
532 results = self.results_by_level() |
555 results = self.results_by_level() |
533 |
556 |
534 for result_level in ['error', 'warning', 'notification']: |
557 for result_level in ['error', 'warning', 'notification']: |
535 if ERROR_ORDER[result_level] >= ERROR_ORDER[level]: |
558 if ERROR_ORDER[result_level] >= ERROR_ORDER[level]: |
536 print "\n{0} details".format(result_level.capitalize()) |
559 print "\n{0} details".format(result_level.capitalize()) |
537 print "----------------" |
560 print "----------------" |
538 for result in results[result_level]: |
561 for result in results[result_level]: |
539 print result |
562 print result |
540 |
563 |
541 |
564 |
542 # Sounding file specifications |
565 # Sounding file specifications |
543 sounding_specs = {'file': [FilenameShellPattern('rs_*.nc'),], |
566 |
544 'dimensions': {'points': [DimensionMandatory(True), |
567 |
545 DimensionUnlimited(False),], |
568 sounding_specs = {'file': [FilenameShellPattern('rs_*.nc'), ], |
|
569 'dimensions': {'points': [DimensionMandatory(True), |
|
570 DimensionUnlimited(False), ], |
|
571 }, |
|
572 'variables': {'Altitude': [VariableMandatory(True), |
|
573 VariableDimensions(['points', ]), |
|
574 VariableType(float)], |
|
575 'Temperature': [VariableMandatory(True), |
|
576 VariableDimensions(['points', ]), |
|
577 VariableType(float)], |
|
578 'Pressure': [VariableMandatory(True), |
|
579 VariableDimensions(['points', ]), |
|
580 VariableType(float)], |
|
581 'RelativeHumidity': [VariableMandatory(False), |
|
582 VariableDimensions(['points', ]), |
|
583 VariableType(float)], |
|
584 }, |
|
585 'attributes': {'Latitude_degrees_north': [AttributeMandatory(True), |
|
586 AttributeType(float), ], |
|
587 'Longitude_degrees_east': [AttributeMandatory(True), |
|
588 AttributeType(float), ], |
|
589 'Altitude_meter_asl': [AttributeMandatory(True), |
|
590 AttributeType(float), ], |
|
591 'Location': [AttributeMandatory(False), |
|
592 AttributeType(unicode), ], |
|
593 'Sounding_Station_Name': [AttributeMandatory(False), |
|
594 AttributeType(unicode), ], |
|
595 'WMO_Station_Number': [AttributeMandatory(False), |
|
596 AttributeType(unicode), ], |
|
597 'WBAN_Station_Number': [AttributeMandatory(False), |
|
598 AttributeType(unicode), ], |
|
599 'Sounding_Start_Date': [AttributeMandatory(True), |
|
600 AttributeType(unicode, block_next=True), |
|
601 AttributeStrLength(8)], |
|
602 'Sounding_Start_Time_UT': [AttributeMandatory(True), |
|
603 AttributeType(unicode, block_next=True), |
|
604 AttributeStrLength(6)], |
|
605 'Sounding_Stop_Time_UT': [AttributeMandatory(False), |
|
606 AttributeType(unicode, block_next=True), |
|
607 AttributeStrLength(6)], |
|
608 }, |
|
609 'name': "SCC Sounding file" |
|
610 } |
|
611 |
|
612 # Lidar ratio file specifications |
|
613 lidar_ratio_specs = {'file': [FilenameShellPattern('*.nc'), ], |
|
614 'dimensions': {'points': [DimensionMandatory(True), |
|
615 DimensionUnlimited(False), ], |
|
616 'products': [DimensionMandatory(True), |
|
617 DimensionUnlimited(False), ], |
|
618 }, |
|
619 'variables': {'Altitude': [VariableMandatory(True), |
|
620 VariableDimensions(['points', ]), |
|
621 VariableType(float)], |
|
622 'Lidar_Ratio': [VariableMandatory(True), |
|
623 VariableDimensions(['products', 'points']), |
|
624 VariableType(float)], |
|
625 'product_ID': [VariableMandatory(True), |
|
626 VariableDimensions(['products', ]), |
|
627 VariableType(int)], |
|
628 }, |
|
629 'attributes': {'Lidar_Station_Name': [AttributeMandatory(True), |
|
630 AttributeType(unicode), ], |
|
631 }, |
|
632 'name': "SCC Lidar ratio file" |
|
633 } |
|
634 |
|
635 # Overlap file specifications |
|
636 overlap_specs = {'file': [FilenameShellPattern('ov_*.nc'), ], |
|
637 'dimensions': {'points': [DimensionMandatory(True), |
|
638 DimensionUnlimited(False), ], |
|
639 'channels': [DimensionMandatory(True), |
|
640 DimensionUnlimited(False), ], |
|
641 }, |
|
642 'variables': {'Altitude': [VariableMandatory(True), |
|
643 VariableDimensions(['points', ]), |
|
644 VariableType(float)], |
|
645 'Overlap_Function': [VariableMandatory(True), |
|
646 VariableDimensions(['channels', 'points']), |
|
647 VariableType(float)], |
|
648 'channel_ID': [VariableMandatory(True), |
|
649 VariableDimensions(['channels', ]), |
|
650 VariableType(int)], |
546 }, |
651 }, |
547 'variables': {'Altitude': [VariableMandatory(True), |
|
548 VariableDimensions(['points',]), |
|
549 VariableType(float)], |
|
550 'Temperature': [VariableMandatory(True), |
|
551 VariableDimensions(['points',]), |
|
552 VariableType(float)], |
|
553 'Pressure': [VariableMandatory(True), |
|
554 VariableDimensions(['points',]), |
|
555 VariableType(float)], |
|
556 'RelativeHumidity': [VariableMandatory(False), |
|
557 VariableDimensions(['points',]), |
|
558 VariableType(float)], |
|
559 }, |
|
560 'attributes': {'Latitude_degrees_north': [AttributeMandatory(True), |
|
561 AttributeType(float),], |
|
562 'Longitude_degrees_east': [AttributeMandatory(True), |
|
563 AttributeType(float),], |
|
564 'Altitude_meter_asl': [AttributeMandatory(True), |
|
565 AttributeType(float),], |
|
566 'Location': [AttributeMandatory(False), |
|
567 AttributeType(unicode),], |
|
568 'Sounding_Station_Name': [AttributeMandatory(False), |
|
569 AttributeType(unicode),], |
|
570 'WMO_Station_Number': [AttributeMandatory(False), |
|
571 AttributeType(unicode),], |
|
572 'WBAN_Station_Number':[AttributeMandatory(False), |
|
573 AttributeType(unicode),], |
|
574 'Sounding_Start_Date':[AttributeMandatory(True), |
|
575 AttributeType(unicode, block_next = True), |
|
576 AttributeStrLength(8)], |
|
577 'Sounding_Start_Time_UT':[AttributeMandatory(True), |
|
578 AttributeType(unicode, block_next = True), |
|
579 AttributeStrLength(6)], |
|
580 'Sounding_Stop_Time_UT':[AttributeMandatory(False), |
|
581 AttributeType(unicode, block_next = True), |
|
582 AttributeStrLength(6)], |
|
583 }, |
|
584 'name': "SCC Sounding file" |
|
585 } |
|
586 |
|
587 # Lidar ratio file specifications |
|
588 lidar_ratio_specs = {'file': [FilenameShellPattern('*.nc'),], |
|
589 'dimensions': {'points': [DimensionMandatory(True), |
|
590 DimensionUnlimited(False),], |
|
591 'products': [DimensionMandatory(True), |
|
592 DimensionUnlimited(False),], |
|
593 }, |
|
594 'variables': {'Altitude': [VariableMandatory(True), |
|
595 VariableDimensions(['points',]), |
|
596 VariableType(float)], |
|
597 'Lidar_Ratio': [VariableMandatory(True), |
|
598 VariableDimensions(['products', 'points']), |
|
599 VariableType(float)], |
|
600 'product_ID': [VariableMandatory(True), |
|
601 VariableDimensions(['products',]), |
|
602 VariableType(int)], |
|
603 }, |
|
604 'attributes': {'Lidar_Station_Name': [AttributeMandatory(True), |
|
605 AttributeType(unicode),], |
|
606 }, |
|
607 'name': "SCC Lidar ratio file" |
|
608 } |
|
609 |
|
610 # Overlap file specifications |
|
611 overlap_specs = {'file': [FilenameShellPattern('ov_*.nc'),], |
|
612 'dimensions': {'points': [DimensionMandatory(True), |
|
613 DimensionUnlimited(False),], |
|
614 'channels': [DimensionMandatory(True), |
|
615 DimensionUnlimited(False),], |
|
616 }, |
|
617 'variables': {'Altitude': [VariableMandatory(True), |
|
618 VariableDimensions(['points',]), |
|
619 VariableType(float)], |
|
620 'Overlap_Function': [VariableMandatory(True), |
|
621 VariableDimensions(['channels', 'points']), |
|
622 VariableType(float)], |
|
623 'channel_ID': [VariableMandatory(True), |
|
624 VariableDimensions(['channels',]), |
|
625 VariableType(int)], |
|
626 }, |
|
627 'attributes': {'Lidar_Station_Name': [AttributeMandatory(True), |
652 'attributes': {'Lidar_Station_Name': [AttributeMandatory(True), |
628 AttributeType(unicode, block_next = True), |
653 AttributeType(unicode, block_next=True), |
629 AttributeStrLength(2)], |
654 AttributeStrLength(2)], |
630 'Overlap_Measurement_Date': [AttributeMandatory(True), |
655 'Overlap_Measurement_Date': [AttributeMandatory(True), |
631 AttributeType(unicode, block_next = True), |
656 AttributeType(unicode, block_next=True), |
632 AttributeStrLength(8)], |
657 AttributeStrLength(8)], |
633 }, |
658 }, |
634 'name': "SCC Overlap file" |
659 'name': "SCC Overlap file" |
635 } |
660 } |
636 |
661 |
637 # Raw data file specifications |
662 # Raw data file specifications |
638 data_specs = {'file': [FilenameShellPattern('*.nc'),], |
663 data_specs = {'file': [FilenameShellPattern('*.nc'), ], |
639 'dimensions': {'points': [DimensionMandatory(True), |
664 'dimensions': {'points': [DimensionMandatory(True), |
640 DimensionUnlimited(False),], |
665 DimensionUnlimited(False), ], |
641 'channels': [DimensionMandatory(True), |
666 'channels': [DimensionMandatory(True), |
642 DimensionUnlimited(False),], |
667 DimensionUnlimited(False), ], |
643 'nb_of_time_scales': [DimensionMandatory(True), |
668 'nb_of_time_scales': [DimensionMandatory(True), |
644 DimensionUnlimited(False),], |
669 DimensionUnlimited(False), ], |
645 'time': [DimensionMandatory(True), |
670 'time': [DimensionMandatory(True), |
646 DimensionUnlimited(True),], |
671 DimensionUnlimited(True), ], |
647 'time_bck': [DimensionMandatory(False), |
672 'time_bck': [DimensionMandatory(False), |
648 DimensionUnlimited(False),], |
673 DimensionUnlimited(False), ], |
649 'scan_angles': [DimensionMandatory(True), |
674 'scan_angles': [DimensionMandatory(True), |
650 DimensionUnlimited(False),], |
675 DimensionUnlimited(False), ], |
651 }, |
676 }, |
652 'variables': {'channel_ID': [VariableMandatory(True), |
677 'variables': {'channel_ID': [VariableMandatory(True), |
653 VariableDimensions(['channels',]), |
678 VariableDimensions(['channels', ]), |
654 VariableType(int)], |
679 VariableType(int)], |
655 'Laser_Repetition_Rate': [VariableMandatory(False), |
680 'Laser_Repetition_Rate': [VariableMandatory(False), |
656 VariableDimensions(['channels',]), |
681 VariableDimensions(['channels', ]), |
657 VariableType(int)], |
682 VariableType(int)], |
658 'Laser_Pointing_Angle': [VariableMandatory(True), |
683 'Laser_Pointing_Angle': [VariableMandatory(True), |
659 VariableDimensions(['scan_angles',]), |
684 VariableDimensions(['scan_angles', ]), |
|
685 VariableType(float)], |
|
686 'ID_Range': [VariableMandatory(False), |
|
687 VariableDimensions(['channels', ]), |
|
688 VariableType(int)], |
|
689 'Scattering_Mechanism': [VariableMandatory(False), |
|
690 VariableDimensions(['channels', ]), |
|
691 VariableType(int)], |
|
692 'Emitted_Wavelength': [VariableMandatory(False), |
|
693 VariableDimensions(['channels', ]), |
|
694 VariableType(float)], |
|
695 'Detected_Wavelength': [VariableMandatory(False), |
|
696 VariableDimensions(['channels', ]), |
|
697 VariableType(float)], |
|
698 'Raw_Data_Range_Resolution': [VariableMandatory(False), |
|
699 VariableDimensions(['channels', ]), |
|
700 VariableType(float)], |
|
701 'Background_Mode': [VariableMandatory(False), |
|
702 VariableDimensions(['channels', ]), |
|
703 VariableType(int)], |
|
704 'Background_Low': [VariableMandatory(True), |
|
705 VariableDimensions(['channels', ]), |
|
706 VariableType(float)], |
|
707 'Background_High': [VariableMandatory(True), |
|
708 VariableDimensions(['channels', ]), |
|
709 VariableType(float)], |
|
710 'Molecular_Calc': [VariableMandatory(True), |
|
711 VariableDimensions([]), |
|
712 VariableType(int)], |
|
713 'id_timescale': [VariableMandatory(True), |
|
714 VariableDimensions(['channels', ]), |
|
715 VariableType(int)], |
|
716 'Dead_Time_Corr_Type': [VariableMandatory(False), |
|
717 VariableDimensions(['channels', ]), |
|
718 VariableType(int)], |
|
719 'Dead_Time': [VariableMandatory(False), |
|
720 VariableDimensions(['channels', ]), |
|
721 VariableType(float)], |
|
722 'Acquisition_Mode': [VariableMandatory(False), |
|
723 VariableDimensions(['channels', ]), |
|
724 VariableType(int)], |
|
725 'Trigger_Delay': [VariableMandatory(False), |
|
726 VariableDimensions(['channels', ]), |
|
727 VariableType(float)], |
|
728 'Laser_Pointing_Angle_of_Profiles': [VariableMandatory(True), |
|
729 VariableDimensions(['time', 'nb_of_time_scales', ]), |
|
730 VariableType(int)], |
|
731 'Raw_Data_Start_Time': [VariableMandatory(True), |
|
732 VariableDimensions(['time', 'nb_of_time_scales', ]), |
|
733 VariableType(int)], |
|
734 'Raw_Data_Stop_Time': [VariableMandatory(True), |
|
735 VariableDimensions(['time', 'nb_of_time_scales', ]), |
|
736 VariableType(int)], |
|
737 'Laser_Shots': [VariableMandatory(True), |
|
738 VariableDimensions(['time', 'channels', ]), |
|
739 VariableType(int)], |
|
740 'Raw_Lidar_Data': [VariableMandatory(False), |
|
741 VariableDimensions(['time', 'channels', 'points']), |
|
742 VariableType(float)], |
|
743 'Depolarization_Factor': [VariableMandatory(False), |
|
744 VariableDimensions(['channels', ]), |
|
745 VariableType(float)], |
|
746 'LR_Input': [VariableMandatory(False), |
|
747 VariableDimensions(['channels', ]), |
|
748 VariableType(int)], |
|
749 'DAQ_Range': [VariableMandatory(False), |
|
750 VariableDimensions(['channels', ]), |
|
751 VariableType(float)], |
|
752 'Pressure_at_Lidar_Station': [VariableMandatory(False), |
|
753 VariableDimensions([]), |
|
754 VariableType(float)], |
|
755 'Temperature_at_Lidar_Station': [VariableMandatory(False), |
|
756 VariableDimensions([]), |
|
757 VariableType(float)], |
|
758 'Background_Profile': [VariableMandatory(False), |
|
759 VariableDimensions(['time_bck', 'channels', 'points']), |
|
760 VariableType(float)], |
|
761 'Raw_Bck_Start_Time': [VariableMandatory(False), |
|
762 VariableDimensions(['time_bck', 'nb_of_time_scales', ]), |
|
763 VariableType(int)], |
|
764 'Raw_Bck_Stop_Time': [VariableMandatory(False), |
|
765 VariableDimensions(['time_bck', 'nb_of_time_scales', ]), |
|
766 VariableType(int)], |
|
767 'Error_On_Raw_Lidar_Data': [VariableMandatory(False), |
|
768 VariableDimensions(['time', 'channels', 'points']), |
660 VariableType(float)], |
769 VariableType(float)], |
661 'ID_Range': [VariableMandatory(False), |
770 'First_Signal_Rangebin': [VariableMandatory(False), |
662 VariableDimensions(['channels',]), |
771 VariableDimensions(['channels', ]), |
663 VariableType(int)], |
|
664 'Scattering_Mechanism': [VariableMandatory(False), |
|
665 VariableDimensions(['channels',]), |
|
666 VariableType(int)], |
|
667 'Emitted_Wavelength': [VariableMandatory(False), |
|
668 VariableDimensions(['channels',]), |
|
669 VariableType(float)], |
|
670 'Detected_Wavelength': [VariableMandatory(False), |
|
671 VariableDimensions(['channels',]), |
|
672 VariableType(float)], |
|
673 'Raw_Data_Range_Resolution': [VariableMandatory(False), |
|
674 VariableDimensions(['channels',]), |
|
675 VariableType(float)], |
|
676 'Background_Mode': [VariableMandatory(False), |
|
677 VariableDimensions(['channels',]), |
|
678 VariableType(int)], |
|
679 'Background_Low': [VariableMandatory(True), |
|
680 VariableDimensions(['channels',]), |
|
681 VariableType(float)], |
|
682 'Background_High': [VariableMandatory(True), |
|
683 VariableDimensions(['channels',]), |
|
684 VariableType(float)], |
|
685 'Molecular_Calc': [VariableMandatory(True), |
|
686 VariableDimensions([]), |
|
687 VariableType(int)], |
|
688 'id_timescale': [VariableMandatory(True), |
|
689 VariableDimensions(['channels',]), |
|
690 VariableType(int)], |
|
691 'Dead_Time_Corr_Type': [VariableMandatory(False), |
|
692 VariableDimensions(['channels',]), |
|
693 VariableType(int)], |
|
694 'Dead_Time': [VariableMandatory(False), |
|
695 VariableDimensions(['channels',]), |
|
696 VariableType(float)], |
|
697 'Acquisition_Mode': [VariableMandatory(False), |
|
698 VariableDimensions(['channels',]), |
|
699 VariableType(int)], |
|
700 'Trigger_Delay': [VariableMandatory(False), |
|
701 VariableDimensions(['channels',]), |
|
702 VariableType(float)], |
|
703 'Laser_Pointing_Angle_of_Profiles': [VariableMandatory(True), |
|
704 VariableDimensions(['time','nb_of_time_scales',]), |
|
705 VariableType(int)], |
|
706 'Raw_Data_Start_Time': [VariableMandatory(True), |
|
707 VariableDimensions(['time','nb_of_time_scales',]), |
|
708 VariableType(int)], |
|
709 'Raw_Data_Stop_Time': [VariableMandatory(True), |
|
710 VariableDimensions(['time','nb_of_time_scales',]), |
|
711 VariableType(int)], |
772 VariableType(int)], |
712 'Laser_Shots': [VariableMandatory(True), |
773 }, |
713 VariableDimensions(['time','channels',]), |
774 'attributes': {'Measurement_ID': [AttributeMandatory(True), |
714 VariableType(int)], |
775 AttributeType(unicode, block_next=True), |
715 'Raw_Lidar_Data': [VariableMandatory(False), |
776 AttributeStrLength(12)], |
716 VariableDimensions(['time', 'channels', 'points']), |
777 'RawData_Start_Date': [AttributeMandatory(True), |
717 VariableType(float)], |
778 AttributeType(unicode, block_next=True), |
718 'Depolarization_Factor': [VariableMandatory(False), |
779 AttributeStrLength(8)], |
719 VariableDimensions(['channels',]), |
780 'RawData_Start_Time_UT': [AttributeMandatory(True), |
720 VariableType(float)], |
781 AttributeType(unicode, block_next=True), |
721 'LR_Input': [VariableMandatory(False), |
782 AttributeStrLength(6)], |
722 VariableDimensions(['channels',]), |
783 'RawData_Stop_Time_UT': [AttributeMandatory(True), |
723 VariableType(int)], |
784 AttributeType(unicode, block_next=True), |
724 'DAQ_Range': [VariableMandatory(False), |
785 AttributeStrLength(6)], |
725 VariableDimensions(['channels',]), |
786 'RawBck_Start_Date': [AttributeMandatory(False), |
726 VariableType(float)], |
787 AttributeType(unicode, block_next=True), |
727 'Pressure_at_Lidar_Station': [VariableMandatory(False), |
788 AttributeStrLength(8)], |
728 VariableDimensions([]), |
789 'RawBck_Start_Time_UT': [AttributeMandatory(False), |
729 VariableType(float)], |
790 AttributeType(unicode, block_next=True), |
730 'Temperature_at_Lidar_Station': [VariableMandatory(False), |
791 AttributeStrLength(6)], |
731 VariableDimensions([]), |
792 'RawBck_Stop_Time_UT': [AttributeMandatory(False), |
732 VariableType(float)], |
793 AttributeType(unicode, block_next=True), |
733 'Background_Profile': [VariableMandatory(False), |
794 AttributeStrLength(6)], |
734 VariableDimensions(['time_bck', 'channels', 'points']), |
795 'Sounding_File_Name': [AttributeMandatory(False), |
735 VariableType(float)], |
796 AttributeType(unicode), ], |
736 'Raw_Bck_Start_Time': [VariableMandatory(False), |
797 'LR_File_Name': [AttributeMandatory(False), |
737 VariableDimensions(['time_bck','nb_of_time_scales',]), |
798 AttributeType(unicode), ], |
738 VariableType(int)], |
799 'Overlap_File_Name': [AttributeMandatory(False), |
739 'Raw_Bck_Stop_Time': [VariableMandatory(False), |
800 AttributeType(unicode), ], |
740 VariableDimensions(['time_bck','nb_of_time_scales',]), |
801 'Location': [AttributeMandatory(False), |
741 VariableType(int)], |
802 AttributeType(unicode), ], |
742 'Error_On_Raw_Lidar_Data': [VariableMandatory(False), |
803 'System': [AttributeMandatory(False), |
743 VariableDimensions(['time','channels', 'points']), |
804 AttributeType(unicode), ], |
744 VariableType(float)], |
805 'Latitude_degrees_north': [AttributeMandatory(False), |
745 'First_Signal_Rangebin': [VariableMandatory(False), |
806 AttributeType(float), ], |
746 VariableDimensions(['channels',]), |
807 'Longitude_degrees_east': [AttributeMandatory(False), |
747 VariableType(int)], |
808 AttributeType(float), ], |
|
809 'Altitude_meter_asl': [AttributeMandatory(False), |
|
810 AttributeType(float), ], |
748 }, |
811 }, |
749 'attributes': {'Measurement_ID': [AttributeMandatory(True), |
812 'name': "SCC Raw input file" |
750 AttributeType(unicode, block_next = True), |
813 } |
751 AttributeStrLength(12)], |
|
752 'RawData_Start_Date': [AttributeMandatory(True), |
|
753 AttributeType(unicode, block_next = True), |
|
754 AttributeStrLength(8)], |
|
755 'RawData_Start_Time_UT': [AttributeMandatory(True), |
|
756 AttributeType(unicode, block_next = True), |
|
757 AttributeStrLength(6)], |
|
758 'RawData_Stop_Time_UT': [AttributeMandatory(True), |
|
759 AttributeType(unicode, block_next = True), |
|
760 AttributeStrLength(6)], |
|
761 'RawBck_Start_Date': [AttributeMandatory(False), |
|
762 AttributeType(unicode, block_next = True), |
|
763 AttributeStrLength(8)], |
|
764 'RawBck_Start_Time_UT': [AttributeMandatory(False), |
|
765 AttributeType(unicode, block_next = True), |
|
766 AttributeStrLength(6)], |
|
767 'RawBck_Stop_Time_UT': [AttributeMandatory(False), |
|
768 AttributeType(unicode, block_next = True), |
|
769 AttributeStrLength(6)], |
|
770 'Sounding_File_Name': [AttributeMandatory(False), |
|
771 AttributeType(unicode),], |
|
772 'LR_File_Name': [AttributeMandatory(False), |
|
773 AttributeType(unicode),], |
|
774 'Overlap_File_Name': [AttributeMandatory(False), |
|
775 AttributeType(unicode),], |
|
776 'Location': [AttributeMandatory(False), |
|
777 AttributeType(unicode),], |
|
778 'System': [AttributeMandatory(False), |
|
779 AttributeType(unicode),], |
|
780 'Latitude_degrees_north': [AttributeMandatory(False), |
|
781 AttributeType(float),], |
|
782 'Longitude_degrees_east': [AttributeMandatory(False), |
|
783 AttributeType(float),], |
|
784 'Altitude_meter_asl': [AttributeMandatory(False), |
|
785 AttributeType(float),], |
|
786 }, |
|
787 'name': "SCC Raw input file" |
|
788 } |
|
789 |
814 |
790 # Used for the command line arguments |
815 # Used for the command line arguments |
791 spec_shorthands = {'sounding': sounding_specs, |
816 spec_shorthands = {'sounding': sounding_specs, |
792 'lidar_ratio': lidar_ratio_specs, |
817 'lidar_ratio': lidar_ratio_specs, |
793 'overlap': overlap_specs, |
818 'overlap': overlap_specs, |
794 'data': data_specs,} |
819 'data': data_specs,} |
795 |
820 |
796 |
|
797 if __name__ == "__main__": |
821 if __name__ == "__main__": |
798 |
|
799 # For use from a terminal |
822 # For use from a terminal |
800 import argparse |
823 import argparse |
801 |
824 |
802 parser = argparse.ArgumentParser() |
825 parser = argparse.ArgumentParser() |
803 parser.add_argument("file", help = "The path of the file to be checked") |
826 parser.add_argument("file", help="The path of the file to be checked") |
804 parser.add_argument("-s", "--specs", default = 'data', |
827 parser.add_argument("-s", "--specs", default='data', |
805 help = "The specificiations to use", |
828 help="The specificiations to use", |
806 choices = ['data', 'overlap', 'lidar_ratio', 'sounding']) |
829 choices=['data', 'overlap', 'lidar_ratio', 'sounding']) |
807 parser.add_argument("-l", "--level", default = 'warning', |
830 parser.add_argument("-l", "--level", default='warning', |
808 help = "The output level", |
831 help="The output level", |
809 choices = ['error', 'warning', 'notification']) |
832 choices=['error', 'warning', 'notification']) |
810 |
833 |
811 # Check the arguments |
834 # Check the arguments |
812 args = parser.parse_args() |
835 args = parser.parse_args() |
813 |
836 |
814 specs = spec_shorthands[args.specs] |
837 specs = spec_shorthands[args.specs] |
815 |
838 |
816 with FileChecker(args.file, specs) as file_checker: |
839 with FileChecker(args.file, specs) as file_checker: |
817 file_checker.run_checks() |
840 file_checker.run_checks() |
818 file_checker.print_report(args.level) |
841 file_checker.print_report(args.level) |
819 |
|