Merge from 110:98a19fb7c6ac

Fri, 15 Dec 2017 08:50:40 +0200

author
Iannis <ulalume3@yahoo.com>
date
Fri, 15 Dec 2017 08:50:40 +0200
changeset 111
16b58fb6d5c0
parent 110
b307099457cf (current diff)
parent 109
8e4a9a8c03d7 (diff)
child 112
07bb7a219314

Merge from 110:98a19fb7c6ac

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/diva.py	Fri Dec 15 08:50:40 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[:]
+
--- a/atmospheric_lidar/scripts/licel2scc_depol.py	Fri Dec 15 08:50:16 2017 +0200
+++ b/atmospheric_lidar/scripts/licel2scc_depol.py	Fri Dec 15 08:50:40 2017 +0200
@@ -104,6 +104,9 @@
     parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const",
                         dest="loglevel", const=logging.WARNING
                         )
+    parser.add_argument('-D', '--dark_measurements', help="Location of files containing dark measurements. Use relative path and filename wildcars, see 'files' parameter for example.",
+                        default="", dest="dark_files"
+                        )
     parser.add_argument('--version', help="Show current version.", action='store_true')
 
     args = parser.parse_args()
@@ -134,6 +137,16 @@
                                                  args.pressure, args.licel_timezone)
 
     measurement = CustomLidarMeasurement(plus45_files, minus45_files)
+    
+    # Get a list of files containing dark measurements
+    if args.dark_files != "":
+        dark_files = glob.glob(args.dark_files)
+
+        if dark_files:
+            logger.debug("Using %s as dark measurements files!" % ', '.join(dark_files))
+            measurement.dark_measurement = CustomLidarMeasurement(dark_files, dark_files)
+        else:
+            logger.warning('No dark measurement files found when searching for %s. Will not use any dark measurements.' % args.dark_files)
 
     try:
         measurement = measurement.subset_by_scc_channels()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/systems/rali/rali_diva_parameters.yaml	Fri Dec 15 08:50:40 2017 +0200
@@ -0,0 +1,21 @@
+global_parameters:
+  title: L0 lidar data
+  source: RALI lidar
+  institution: INOE, Bucharest, Romania
+  references: Nemuc, A. et al, Atmos. Meas. Tech. 6, 3243–3255, 2013.
+  Conventions: CF-1.7
+  comment: "Test file"
+  location: Magurele, Bucharest, Romania
+  data_version: 1.0
+  history: "{date} {file} Data file created\n"
+global_variables:
+  laser_pointing_angle: 0
+  latitude: 44.348
+  longitude: 26.029
+  system_altitude: 93.0
+channels:
+  01064.o_an:
+    Laser_Shots: 3000
+    DAQ_Range: 100.0
+
+
--- a/setup.py	Fri Dec 15 08:50:16 2017 +0200
+++ b/setup.py	Fri Dec 15 08:50:40 2017 +0200
@@ -53,6 +53,7 @@
           "matplotlib",
           "sphinx",
           "pytz",
+          "pyyaml",
       ],
       entry_points={
           'console_scripts': ['licel2scc = atmospheric_lidar.scripts.licel2scc:main',

mercurial