atmospheric_lidar/diva.py

changeset 108
b5a0a2d2ce81
child 112
07bb7a219314
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/diva.py	Thu Dec 14 22:47:33 2017 +0200
@@ -0,0 +1,171 @@
+""" This is a class for experimenting with the new DIVA / EARLINET NetCDF file format.
+
+In the long run, this should be places as a method in BaseLidarMeasurement class. For now it is kept
+separately not to interfere with normal development.
+"""
+import netCDF4 as netcdf
+import pyyaml
+import datetime
+import os
+
+from .generic import BaseLidarMeasurement
+
+
+class DivaOutput(BaseLidarMeasurement):
+
+    def save_as_diva(self, output_path, parameter_file):
+        """ Save the current data in the 'draft' DIVA format. """
+
+        with open(parameter_file, 'r') as f:
+            parameters = pyyaml.load(f)
+
+        global_parameters = parameters['global_parameters']  # Shortcut
+
+        iso_date = datetime.datetime.utcnow().isoformat()
+        python_file_name = os.path.basename(__file__)
+
+        with netcdf.Dataset(output_path, 'w', format="NETCDF4") as f:
+
+            # Global attributes
+            f.title = global_parameters['title']
+            f.source = global_parameters['source']
+            f.institution = global_parameters['institution']
+            f.references = global_parameters['references']
+            f.location = global_parameters['location']
+            f.data_version = global_parameters['data_version']
+            f.conversion_date = iso_date
+            f.comment = global_parameters['comment']
+            f.Conventions = global_parameters['Conventions']
+            f.history = global_parameters['history'].format(date=iso_date, file=python_file_name)
+            f.featureType = "timeSeriesProfile"
+
+            # Top level variables
+            latitude = f.createVariable('latitude', datatype='f4')
+            latitude.standard_name = 'latitude'
+            latitude.long_name = 'system latitude'
+            latitude.units = 'degrees_north'
+
+            longitude = f.createVariable('longitude', datatype='f4')
+            longitude.standard_name = 'longitude'
+            longitude.long_name = 'system longitude'
+            longitude.units = 'degrees_east'
+
+            laser_angle = f.createVariable('laser_zenith_angle', datatype='f4')
+            laser_angle.standard_name = 'sensor_zenith_angle'
+            laser_angle.long_name = 'zenith angle of emitted laser'
+            laser_angle.units = 'degree'
+
+            laser_angle = f.createVariable('laser_zenith_angle', datatype='f4')
+            laser_angle.long_name = 'zenith angle of emitted laser'
+            laser_angle.units = 'degrees'
+
+            altitude = f.createVariable('altitude', datatype='f4')
+            altitude.standard_name = 'altitude'
+            altitude.long_name = 'system altitude'
+            altitude.units = 'm'
+
+
+            # Create a separate group for each channel
+            f = f.createGroup("channel_532nmP")  # This should be changed to a meaningful channel name
+            f.data_type = self.data_type
+
+            f.createDimension('profile', len(self.time))
+            f.createDimension('range', len(self.range))
+
+            id = f.createVariable('channel_id', 'i4')
+            id.cf_role = "trajectory_id"
+
+            latitude = f.createVariable('latitude', datatype='f8', dimensions=('profile',), zlib=True)
+            latitude.long_name = 'aircraft GPS latitude'
+            latitude.units = 'degrees_north'
+            latitude.standard_name = 'latitude'
+
+            longitude = f.createVariable('longitude', datatype='f8', dimensions=('profile',), zlib=True)
+            longitude.long_name = 'aircraft GPS longitude'
+            longitude.units = 'degrees_east'
+            longitude.standard_name = 'longitude'
+
+            altitude = f.createVariable('altitude', datatype='f4', dimensions=('profile',), zlib=True)
+            altitude.long_name = 'aircraft GPS altitude'
+            altitude.units = 'm'
+            altitude.standard_name = 'altitude'
+
+            time = f.createVariable('time', datatype='f8', dimensions=('profile',),
+                                    zlib=True)
+            time.long_name = 'starting time of record'
+            time.units = "seconds since 1970-01-01 00:00:00"
+            time.standard_name = "time"
+
+            bin_range = f.createVariable('range', datatype='f4', dimensions=('range',),
+                                         zlib=True)  # Use name 'bin_range' to avoid conflict with built-in range
+            bin_range.long_name = 'range from instrument'
+            bin_range.units = "m"
+            bin_range.positive = "down"
+            bin_range.axis = 'Z'  # This is strictly not correct, as it does not correspond to geophysical variable. Still it can be usefull for quick plotting.
+
+            pitch = f.createVariable('pitch', datatype='f4', dimensions=('profile',), zlib=True)
+            pitch.long_name = 'aircraft pitch'
+            pitch.units = 'degree'
+            pitch.standard_name = 'platform_pitch_angle'
+            pitch.coordinates = "time longitude latitude"
+
+            roll = f.createVariable('roll', datatype='f4', dimensions=('profile',), zlib=True)
+            roll.long_name = 'aircraft roll'
+            roll.units = 'degree'
+            roll.standard_name = 'platform_roll_angle'
+            roll.coordinates = "time longitude latitude"
+
+            heading = f.createVariable('heading', datatype='f4', dimensions=('profile',), zlib=True)
+            heading.long_name = 'aircraft heading'
+            heading.units = 'degree'
+            heading.standard_name = 'platform_course'
+            heading.coordinates = "time longitude latitude"
+
+            hv = f.createVariable('hv', datatype='f4', dimensions=('profile',), zlib=True)
+            hv.long_name = 'detector high voltage'
+            hv.units = 'V'
+            hv.coordinates = "time longitude latitude"
+
+            averaging_time = f.createVariable('averaging_time', datatype='f4', dimensions=('profile',), zlib=True)
+            averaging_time.long_name = 'averaging time'
+            averaging_time.units = 's'
+            averaging_time.coordinates = "time longitude latitude"
+
+            emission_wl = f.createVariable('emission_wavelength', datatype='f8', dimensions=('profile',),
+                                           zlib=True)
+            emission_wl.long_name = 'emission wavelength in vacuum'
+            emission_wl.units = 'nm'
+            emission_wl.standard_name = 'radiation_wavelength'
+            emission_wl.coordinates = "time longitude latitude"
+
+            pulses = f.createVariable('pulses', datatype='i4', dimensions=('profile',),
+                                      zlib=True)
+            pulses.long_name = 'laser pulses per record'
+            pulses.coordinates = "time longitude latitude"
+
+            signal = f.createVariable('signal', datatype='i4', dimensions=('profile', 'range'),
+                                      zlib=True)
+            signal.long_name = 'signal'
+            signal.units = "counts"
+            signal.missing_value = -1
+            signal.coordinates = "time longitude latitude range"
+
+            # Assign channel attributes
+            f.channel_name = 'L_532nmP'
+
+            # Assign variables
+            id[:] = 1
+            latitude[:] = self.latitude[:]
+            longitude[:] = self.longitude[:]
+            altitude[:] = self.gps_altitude[:]
+            pitch[:] = self.pitch[:]
+            roll[:] = self.roll[:]
+            heading[:] = self.heading_angle[:]
+            hv[:] = self.high_voltage[:]
+            averaging_time[:] = self.averaging_time[:]
+            emission_wl[:] = self.emission_wavelength_vacuum[:]
+            pulses[:] = self.pulses[:]
+            time[:] = self.time[:]
+            bin_range[:] = self.range[:]
+            signal[:] = self.signal[:]
+

mercurial