Merge from 81:2b484f310d0d

Mon, 06 Nov 2017 16:02:11 +0200

author
Iannis <i.binietoglou@impworks.gr>
date
Mon, 06 Nov 2017 16:02:11 +0200
changeset 82
01fdb725ca59
parent 81
b6602134d40f (current diff)
parent 80
48d5e9876708 (diff)
child 83
22b773693a3c

Merge from 81:2b484f310d0d

atmospheric_lidar/adam2016_depolarization_parameters.py file | annotate | diff | comparison | revisions
atmospheric_lidar/adam2017_depolarization_parameters.py file | annotate | diff | comparison | revisions
atmospheric_lidar/generic.py file | annotate | diff | comparison | revisions
atmospheric_lidar/scripts/licel2scc_depol.py file | annotate | diff | comparison | revisions
--- a/atmospheric_lidar/__init__.py	Mon Nov 06 16:01:35 2017 +0200
+++ b/atmospheric_lidar/__init__.py	Mon Nov 06 16:02:11 2017 +0200
@@ -1,1 +1,1 @@
-__version__ = '0.2.8'
\ No newline at end of file
+__version__ = '0.2.10'
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2016_depol.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,5 @@
+from licel_depol import LicelCalibrationMeasurement
+import adam2016_depolarization_parameters
+
+class ADAM2017CalibrationMeasurement(LicelCalibrationMeasurement):
+    extra_netcdf_parameters = adam2016_depolarization_parameters
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2016_depolarization_parameters.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,116 @@
+general_parameters =  \
+{'System': '\'ADAM 2012-2017\'',
+ 'Call sign': 'is',
+ 'Laser_Pointing_Angle': 0,
+ 'Molecular_Calc': 0,
+ 'Latitude_degrees_north': 45.8,
+ 'Longitude_degrees_east': 8.6,
+ 'Altitude_meter_asl': 209.0}  # This should be float
+
+# Change to channel_parameters to use all channels. For testing I define only photon counting channels below.
+channel_parameters = \
+{'BC1_p45': {'channel_ID': 647,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1501,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2500,
+         'Pol_Calib_Range_Max': 4000},
+ 'BC2_p45': {'channel_ID': 649,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1501,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2500,
+         'Pol_Calib_Range_Max': 4000},
+ 'BC1_m45': {'channel_ID': 646,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1501,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2500,
+         'Pol_Calib_Range_Max': 4000},
+ 'BC2_m45': {'channel_ID': 648,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1501,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2500,
+         'Pol_Calib_Range_Max': 4000},
+         }
+         
+"""
+{'00532.p_an_p45': {'channel_ID': 383,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_ph_p45': {'channel_ID': 378,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_an_p45': {'channel_ID': 385 ,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 20.0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_ph_p45': {'channel_ID': 380,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_an_m45': {'channel_ID': 384,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_ph_m45': {'channel_ID': 379,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_an_m45': {'channel_ID': 386,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 20.0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_ph_m45': {'channel_ID': 382,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+         }
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2017.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,16 @@
+from licel import LicelLidarMeasurement
+
+import adam2017_netcdf_parameters
+
+class ADAM2017LidarMeasurement(LicelLidarMeasurement):
+    extra_netcdf_parameters = adam2017_netcdf_parameters
+
+    def _get_scc_mandatory_channel_variables(self):
+        channel_variables = \
+            {'Background_Low': (('channels',), 'd'),
+             'Background_High': (('channels',), 'd'),
+             'LR_Input': (('channels',), 'i'),
+             'DAQ_Range': (('channels',), 'd'),
+             'First_Signal_Rangebin': (('channels',), 'i')
+             }
+        return channel_variables
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2017_depol.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,5 @@
+from licel_depol import LicelCalibrationMeasurement
+import adam2017_depolarization_parameters
+
+class ADAM2017CalibrationMeasurement(LicelCalibrationMeasurement):
+    extra_netcdf_parameters = adam2017_depolarization_parameters
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2017_depolarization_parameters.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,116 @@
+general_parameters =  \
+{'System': '\'ADAM May 2017\'',
+ 'Call sign': 'is',
+ 'Laser_Pointing_Angle': 0,
+ 'Molecular_Calc': 0,
+ 'Latitude_degrees_north': 45.8,
+ 'Longitude_degrees_east': 8.6,
+ 'Altitude_meter_asl': 209.0}  # This should be float
+
+# Change to channel_parameters to use all channels. For testing I define only photon counting channels below.
+channel_parameters = \
+{'00532.p_ph_p45': {'channel_ID': 929,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1201,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_ph_p45': {'channel_ID': 931,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1201,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_ph_m45': {'channel_ID': 928,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1201,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_ph_m45': {'channel_ID': 930,
+         'Background_Low': 45000,
+         'Background_High': 60000,
+         'Laser_Shots': 1201,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 2000,
+         'Pol_Calib_Range_Max': 3000},
+         }
+         
+"""
+{'00532.p_an_p45': {'channel_ID': 383,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_ph_p45': {'channel_ID': 378,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_an_p45': {'channel_ID': 385 ,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 20.0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_ph_p45': {'channel_ID': 380,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_an_m45': {'channel_ID': 384,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.p_ph_m45': {'channel_ID': 379,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Depolarization_Factor': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_an_m45': {'channel_ID': 386,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 20.0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+ '00532.s_ph_m45': {'channel_ID': 382,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3000,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'Pol_Calib_Range_Min': 1000,
+         'Pol_Calib_Range_Max': 3000},
+         }
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2017_netcdf_parameters.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,89 @@
+general_parameters =  \
+{'System': '\'ADAM May 2017\'',
+ 'Call sign': 'is',
+ 'Laser_Pointing_Angle': 0,
+ 'Molecular_Calc': 0,
+ 'Latitude_degrees_north': 45.8,
+ 'Longitude_degrees_east': 8.6,
+ 'Altitude_meter_asl': 209.0}  # This should be float
+
+channel_parameters = \
+{'01064.o_an': {'channel_ID': 917,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 500.0,
+         'First_Signal_Rangebin': 9},
+ '00532.p_an': {'channel_ID': 918,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 500.0,
+         'First_Signal_Rangebin': 9},
+'00532.p_ph': {'channel_ID': 919,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+ '00532.s_an': {'channel_ID': 920,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 500.0,
+         'First_Signal_Rangebin': 9},
+ '00532.s_ph': {'channel_ID': 921,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+ '00607.o_an': {'channel_ID': 922,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 500.0,
+         'First_Signal_Rangebin': 9},
+ '00607.o_ph': {'channel_ID': 923,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input':1,
+         'DAQ_Range':500.0,
+         'First_Signal_Rangebin': 0},
+ '00355.o_an': {'channel_ID': 924,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 500.0,
+         'First_Signal_Rangebin': 8},
+ '00355.o_ph': {'channel_ID': 925,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+ '00387.o_an': {'channel_ID': 926,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 500.0,
+         'First_Signal_Rangebin': 9},
+ '00387.o_ph': {'channel_ID': 927,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/adam2017_netcdf_parameters_2.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,89 @@
+general_parameters =  \
+{'System': '\'ADAM May 2017\'',
+ 'Call sign': 'is',
+ 'Laser_Pointing_Angle': 0,
+ 'Molecular_Calc': 0,
+ 'Latitude_degrees_north': 45.8,
+ 'Longitude_degrees_east': 8.6,
+ 'Altitude_meter_asl': 209.0}  # This should be float
+
+channel_parameters = \
+{'01064.o_an': {'channel_ID': 917,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'First_Signal_Rangebin': 9},
+ '00532.p_an': {'channel_ID': 918,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'First_Signal_Rangebin': 9},
+'00532.p_ph': {'channel_ID': 919,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+ '00532.s_an': {'channel_ID': 920,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'First_Signal_Rangebin': 9},
+ '00532.s_ph': {'channel_ID': 921,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+ '00607.o_an': {'channel_ID': 922,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'First_Signal_Rangebin': 9},
+ '00607.o_ph': {'channel_ID': 923,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input':1,
+         'DAQ_Range':100.0,
+         'First_Signal_Rangebin': 0},
+ '00355.o_an': {'channel_ID': 924,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'First_Signal_Rangebin': 8},
+ '00355.o_ph': {'channel_ID': 925,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+ '00387.o_an': {'channel_ID': 926,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 100.0,
+         'First_Signal_Rangebin': 9},
+ '00387.o_ph': {'channel_ID': 927,
+         'Background_Low': 50000,
+         'Background_High': 60000,
+         'Laser_Shots': 3001,
+         'LR_Input': 1,
+         'DAQ_Range': 0,
+         'First_Signal_Rangebin': 0},
+}
+
--- a/atmospheric_lidar/generic.py	Mon Nov 06 16:01:35 2017 +0200
+++ b/atmospheric_lidar/generic.py	Mon Nov 06 16:02:11 2017 +0200
@@ -334,12 +334,20 @@
         temp_v = f.createVariable(channel_var, variable_type, ('channels',))
         for n, channel in enumerate(channels):
             temp_v[n] = params.channel_parameters[channel][channel_var]
-
-        # Write the values of fixed channel parameters
-        for (var, t) in channel_variables.iteritems():
-            temp_v = f.createVariable(var, t[1], t[0])
+        
+        # Write the values of fixed channel parameters:
+        fill_value = -9999
+        for param in self._get_provided_extra_parameters():
+            if param in channel_variables.keys():
+                temp_v = f.createVariable(param, channel_variables[param][1], channel_variables[param][0])
+            else:
+                temp_v = f.createVariable(param, 'd', ('channels',), fill_value = fill_value)
+                
             for (channel, n) in zip(channels, range(len(channels))):
-                temp_v[n] = params.channel_parameters[channel][var]
+                try:
+                    temp_v[n] = params.channel_parameters[channel][param]
+                except KeyError: # The parameter was not provided for this channel so we mask the value.
+                    temp_v[n] = fill_value
 
         # Write the id_timescale values
         temp_id_timescale = f.createVariable('id_timescale', 'i', ('channels',))
@@ -403,6 +411,34 @@
              'DAQ_Range': (('channels',), 'd'),
              }
         return channel_variables
+        
+    def _get_provided_extra_parameters(self):
+        # When looking for non-mandatory channel parameters, ignore the following parameter names:
+        ignore = ['channel_ID', 'channel string ID', 'Depolarization_Factor', 'Laser_Shots']
+        
+        channels = self.channels.keys()
+        params = self.extra_netcdf_parameters.channel_parameters
+        mandatory = self._get_scc_mandatory_channel_variables()
+        
+        # Get all the provided extra parameters (both mandatory and optional):
+        provided_extra_parameters = []
+        for (channel, n) in zip(channels, range(len(channels))):
+            # Check all the mandatory parameters are provided for each of the channels:
+            for var in mandatory.keys():
+                if var not in params[channel].keys():
+                    raise ValueError ("Mandatory parameter '{0}' not provided for channel {1}!".format(
+                        var,
+                        channel
+                    ))
+                    
+            provided_extra_parameters.extend(params[channel].keys())
+            
+        provided_extra_parameters = set(provided_extra_parameters)
+        # Discard certain parameter names:
+        for param in ignore:
+            provided_extra_parameters.discard(param)
+            
+        return provided_extra_parameters
 
     def add_dark_measurements_to_netcdf(self, f, channels):
 
@@ -592,13 +628,14 @@
         prof = np.mean(self.matrix, axis=0)
         return prof
 
-    def plot(self, signal_type='rc', filename=None, zoom=[0, 12000, 0, -1], show_plot=True, cmap=plt.cm.jet, z0=None,
+    def plot(self, figsize=(8, 4), signal_type='rc', zoom=[0, 12000, 0, -1], show_plot=True, cmap=plt.cm.jet, z0=None,
              title=None, vmin=0, vmax=1.3 * 10 ** 7, figsize=(8, 4)):
         # if filename is not None:
         #    matplotlib.use('Agg')
 
         fig = plt.figure(figsize=figsize)
         ax1 = fig.add_subplot(111)
+
         self.draw_plot(ax1, cmap=cmap, signal_type=signal_type, zoom=zoom, z0=z0, vmin=vmin, vmax=vmax)
 
         if title:
@@ -606,13 +643,8 @@
         else:
             ax1.set_title("%s signal - %s" % (signal_type.upper(), self.name))
 
-        if filename is not None:
-            pass
-            # plt.savefig(filename)
-        else:
-            if show_plot:
-                plt.show()
-                # plt.close() ???
+        if show_plot:
+            plt.show()
 
     def draw_plot(self, ax1, cmap=plt.cm.jet, signal_type='rc',
                   zoom=[0, 12000, 0, -1], z0=None,
--- a/atmospheric_lidar/licel_depol.py	Mon Nov 06 16:01:35 2017 +0200
+++ b/atmospheric_lidar/licel_depol.py	Mon Nov 06 16:02:11 2017 +0200
@@ -7,14 +7,14 @@
 
 class LicelCalibrationMeasurement(LicelLidarMeasurement):
 
-    def __init__(self, plus45_files=None, minus45_files=None):
+    def __init__(self, plus45_files=None, minus45_files=None,  use_id_as_name=False):
         # Setup the empty class
-        super(LicelCalibrationMeasurement, self).__init__()
+        super(LicelCalibrationMeasurement, self).__init__(use_id_as_name=use_id_as_name)
 
         self.plus45_files = plus45_files
         self.minus45_files = minus45_files
 
-        if (plus45_files and minus45_files):
+        if plus45_files and minus45_files:
             self.check_equal_length()
 
             self.read_channel_data()
@@ -39,10 +39,10 @@
     def read_channel_data(self):
 
         # Read plus and minus 45 measurements
-        self.plus45_measurement = LicelLidarMeasurement(self.plus45_files)
+        self.plus45_measurement = LicelLidarMeasurement(self.plus45_files, self.use_id_as_name)
         self.plus45_measurement.rename_channel(suffix='_p45')
 
-        self.minus45_measurement = LicelLidarMeasurement(self.minus45_files)
+        self.minus45_measurement = LicelLidarMeasurement(self.minus45_files, self.use_id_as_name)
         self.minus45_measurement.rename_channel(suffix='_m45')
 
         # Combine them in this object
@@ -109,14 +109,6 @@
 
         self.update()
 
-    def subset_by_netcdf_channels(self):
-        """
-        Subset the measurement based on the available netcdf channels in the parameters file.
-        """
-        channels = self.extra_netcdf_parameters.channel_parameters.keys()
-        new_measurement = self.subset_by_channels(channels)
-        return new_measurement
-
     def subset_photoncounting(self):
         """
         Subset photoncounting channels.
@@ -125,7 +117,7 @@
         new_measurement = self.subset_by_channels(ph_channels)
         return new_measurement
 
-    def _get_scc_channel_variables(self):
+    def _get_scc_mandatory_channel_variables(self):
         """
         Get a list of variables to put in the SCC.
 
@@ -138,8 +130,7 @@
            A dictionary with channel variable specifications.
         """
         channel_variables = \
-            {'channel_ID': (('channels',), 'i'),
-             'Background_Low': (('channels',), 'd'),
+            {'Background_Low': (('channels',), 'd'),
              'Background_High': (('channels',), 'd'),
              'LR_Input': (('channels',), 'i'),
              'DAQ_Range': (('channels',), 'd'),
--- a/atmospheric_lidar/rali_depolarization_parameters.py	Mon Nov 06 16:01:35 2017 +0200
+++ b/atmospheric_lidar/rali_depolarization_parameters.py	Mon Nov 06 16:02:11 2017 +0200
@@ -77,80 +77,4 @@
          'DAQ_Range': 0,
          'Pol_Calib_Range_Min': 1000,
          'Pol_Calib_Range_Max': 3000},
-         }
-
-
-channel_parameters_full = \
-{ '00532.p_an_p45': {'channel_ID': 383,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 100.0,
-         'Depolarization_Factor': 0,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.p_ph_p45': {'channel_ID': 378,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 0,
-         'Depolarization_Factor': 0,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.s_an_p45': {'channel_ID': 385 ,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 20.0,
-         'Depolarization_Factor': 0.115,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.s_ph_p45': {'channel_ID': 380,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 0,
-         'Depolarization_Factor': 0.115,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.p_an_m45': {'channel_ID': 384,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 100.0,
-         'Depolarization_Factor': 0,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.p_ph_m45': {'channel_ID': 379,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 0,
-         'Depolarization_Factor': 0,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.s_an_m45': {'channel_ID': 386,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 20.0,
-         'Depolarization_Factor': 0.115,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
- '00532.s_ph_m45': {'channel_ID': 382,
-         'Background_Low': 50000,
-         'Background_High': 60000,
-         'Laser_Shots': 3000,
-         'LR_Input': 1,
-         'DAQ_Range': 0,
-         'Depolarization_Factor': 0.115,
-         'Pol_Calib_Range_Min': 1000,
-         'Pol_Calib_Range_Max': 3000},
-         }
+         }
\ No newline at end of file
--- a/atmospheric_lidar/scripts/licel2scc.py	Mon Nov 06 16:01:35 2017 +0200
+++ b/atmospheric_lidar/scripts/licel2scc.py	Mon Nov 06 16:02:11 2017 +0200
@@ -9,6 +9,7 @@
 
 
 from ..licel import LicelLidarMeasurement
+from ..__init__ import __version__
 
 
 def create_custom_class(custom_netcdf_parameter_path, use_id_as_name=False, temperature=25., pressure=1020.):
@@ -73,9 +74,8 @@
     # Define the command line argument
     parser = argparse.ArgumentParser(description="A program to convert Licel binary files to the SCC NetCDF format.")
     parser.add_argument("parameter_file", help="The path to a parameter file linking licel and SCC channels.")
-    parser.add_argument("directory", nargs='?', help="Directory containing licel files (default '.')", default='.')
-    parser.add_argument("search_string", nargs='?', help="Search string for files in directory (default '*.*')",
-                        default="*.*")
+    parser.add_argument("files", nargs='?', help="Location of licel files. Use relative path and filename wildcards. (default './*.*')",
+                        default="./*.*")
     parser.add_argument("-i", '--id_as_name',
                         help="Use transient digitizer ids as channel names, instead of descriptive names",
                         action="store_true")
@@ -96,6 +96,7 @@
     parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const",
                         dest="loglevel", const=logging.WARNING
                         )
+    parser.add_argument('--version', help="Show current version.", action='store_true')
 
     args = parser.parse_args()
 
@@ -105,13 +106,16 @@
 
     #coloredlogs.install(fmt='%(levelname)s: %(message)s', level=args.loglevel)
 
+    if args.version:
+        print("Version: %s" % __version__)
+        sys.exit(0)
+
     # Get a list of files to convert
-    search_str = os.path.join(args.directory, args.search_string)
-    files = glob.glob(search_str)
+    files = glob.glob(args.files)
 
     if files:
         # Read the files
-        logger.info("Reading {0} files from {1}".format(len(files), args.directory))
+        logger.info("Reading {0} files from {1}".format(len(files), os.path.abspath(os.path.dirname(args.files))))
         CustomLidarMeasurement = create_custom_class(args.parameter_file, args.id_as_name, args.temperature,
                                                      args.pressure)
         measurement = CustomLidarMeasurement(files)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/atmospheric_lidar/scripts/licel2scc_depol.py	Mon Nov 06 16:02:11 2017 +0200
@@ -0,0 +1,140 @@
+""" Command line tool to convert Licel binary files to SCC NetCDF format.
+"""
+import argparse
+import glob
+import importlib
+import logging
+import os
+import sys
+
+
+from ..licel_depol import LicelCalibrationMeasurement
+from ..__init__ import __version__
+
+
+def create_custom_class(custom_netcdf_parameter_path, use_id_as_name=False, temperature=25., pressure=1020.):
+    """ This funtion creates a custom LicelLidarMeasurement subclass,
+    based on the input provided by the users.
+
+    Parameters
+    ----------
+    custom_netcdf_parameter_path: str
+       The path to the custom channels parameters.
+    use_id_as_name: bool
+       Defines if channels names are descriptive or transient digitizer IDs.
+    temperature: float
+       The ground temperature in degrees C (default 25.0).
+    pressure: float
+       The ground pressure in hPa (default: 1020.0).
+
+    Returns
+    -------
+    CustomLidarMeasurement:
+       A custom sub-class of LicelLidarMeasurement
+    """
+
+    custom_netcdf_parameters = read_settings_file(custom_netcdf_parameter_path)
+
+    class CustomLidarMeasurement(LicelCalibrationMeasurement):
+        extra_netcdf_parameters = custom_netcdf_parameters
+
+        def __init__(self, plus45_files=None, minus45_files=None):
+            super(CustomLidarMeasurement, self).__init__(plus45_files, minus45_files, use_id_as_name)
+
+        def get_PT(self):
+            ''' Sets the pressure and temperature at station level. This is used if molecular_calc parameter is
+            set to 0 (i.e. use US Standard atmosphere).
+
+            The results are stored in the info dictionary.
+            '''
+
+            self.info['Temperature'] = temperature
+            self.info['Pressure'] = pressure
+
+    return CustomLidarMeasurement
+
+
+def read_settings_file(settings_path):
+    """ Read the settings file.
+
+    The file should contain python code."""
+    if not os.path.isfile(settings_path):
+        logging.error("The provided settings path does not correspond to a file.")
+        sys.exit(1)
+
+    dirname, basename = os.path.split(settings_path)
+    sys.path.append(dirname)
+
+    module_name, _ = os.path.splitext(basename)
+    settings = importlib.import_module(module_name)
+    return settings
+
+
+def main():
+    # Define the command line argument
+    parser = argparse.ArgumentParser(description="A program to convert Licel binary files from depolarization calibration measurements to the SCC NetCDF format.")
+    parser.add_argument("parameter_file", help="The path to a parameter file linking licel and SCC channels.")
+    parser.add_argument("plus45_string", help="Search string for plus 45 degree files")
+    parser.add_argument("minus45_string", help="Search string for minus 45 degree files")
+    parser.add_argument("-i", '--id_as_name',
+                        help="Use transient digitizer ids as channel names, instead of descriptive names",
+                        action="store_true")
+    parser.add_argument("-m", "--measurement_id", help="The new measurement id", default=None)
+    parser.add_argument("-n", "--measurement_number",
+                        help="The measurement number for the date from 00 to 99. Used if no id is provided",
+                        default="00")
+    parser.add_argument("-t", "--temperature", type=float,
+                        help="The temperature (in C) at lidar level, required if using US Standard atmosphere",
+                        default="25")
+    parser.add_argument("-p", "--pressure", type=float,
+                        help="The pressure (in hPa) at lidar level, required if using US Standard atmosphere",
+                        default="1020")
+    # Verbosity settings from http://stackoverflow.com/a/20663028
+    parser.add_argument('-d', '--debug', help="Print dubuging information.", action="store_const",
+                        dest="loglevel", const=logging.DEBUG, default=logging.INFO,
+                        )
+    parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const",
+                        dest="loglevel", const=logging.WARNING
+                        )
+    parser.add_argument('--version', help="Show current version.", action='store_true')
+
+    args = parser.parse_args()
+
+    # Get the logger with the appropriate level
+    logging.basicConfig(format='%(levelname)s: %(message)s', level=args.loglevel)
+    logger = logging.getLogger(__name__)
+
+    #coloredlogs.install(fmt='%(levelname)s: %(message)s', level=args.loglevel)
+
+    if args.version:
+        print("Version: %s" % __version__)
+        sys.exit(0)
+
+    # Get a list of files to convert
+    plus45_files = glob.glob(args.plus45_string)
+    minus45_files = glob.glob(args.minus45_string)
+
+    if len(plus45_files)==0 or len(minus45_files)==0:
+        logger.error("No files found when searching for %s and %s." % (plus45_files, minus45_files))
+        sys.exit(1)
+
+    # Read the files
+    logger.info("Reading {0} files from {1}".format(len(plus45_files), args.plus45_string))
+    logger.info("Reading {0} files from {1}".format(len(minus45_files), args.minus45_string))
+
+    CustomLidarMeasurement = create_custom_class(args.parameter_file, args.id_as_name, args.temperature,
+                                                     args.pressure)
+
+    measurement = CustomLidarMeasurement(plus45_files, minus45_files)
+
+    try:
+        measurement = measurement.subset_by_scc_channels()
+    except ValueError as err:
+        logging.error(err)
+        sys.exit(1)
+
+    # Save the netcdf
+    logger.info("Saving netcdf")
+    measurement.set_measurement_id(args.measurement_id, args.measurement_number)
+    measurement.save_as_netcdf()
+    logger.info("Created file %s" % measurement.scc_filename)
--- a/readme.rst	Mon Nov 06 16:01:35 2017 +0200
+++ b/readme.rst	Mon Nov 06 16:02:11 2017 +0200
@@ -7,6 +7,12 @@
 The package provides a single command line tool, called licel2scc that can convert Licel binary files to the
 EARLINET's Single Calculus Chain NetCDF format.
 
+Installation
+============
+
+The easiest way to install this module is from the python package index using ``pip``::
+
+   pip install atmospheric-lidar
 
 Using it as a Licel to SCC converter
 ====================================
@@ -20,19 +26,15 @@
 
 Command line interface
 ----------------------
-The usage of the  ``licel2scc`` program is described bellow::
+The usage of the  ``licel2scc`` program is described below::
 
-    usage: licel2scc [-h] [-i] [-m MEASUREMENT_ID] [-n MEASUREMENT_NUMBER]
-                     [-t TEMPERATURE] [-p PRESSURE] [-d] [-s]
-                     parameter_file [directory] [search_string]
-
-    A program to convert LICEL binary files to the SCC NetCDF format.
+    A program to convert Licel binary files to the SCC NetCDF format.
 
     positional arguments:
       parameter_file        The path to a parameter file linking licel and SCC
                             channels.
-      directory             Directory containing licel files (default '.')
-      search_string         Search string for files in directory (default '*.*')
+      files                 Location of licel files. Use relative path and
+                            filename wildcards. (default './*.*')
 
     optional arguments:
       -h, --help            show this help message and exit
@@ -51,7 +53,39 @@
                             using US Standard atmosphere
       -d, --debug           Print dubuging information.
       -s, --silent          Show only warning and error messages.
+      --version             Show current version.
 
+Similarly, the ``licel2scc-depol`` program can be used to convert
+Licel files from Delta45 depolarization calibration measurements::
+
+    A program to convert Licel binary files from depolarization calibration
+    measurements to the SCC NetCDF format.
+
+    positional arguments:
+      parameter_file        The path to a parameter file linking licel and SCC
+                            channels.
+      plus45_string         Search string for plus 45 degree files (default '*.*')
+      minus45_string        Search string for minus 45 degree files (default
+                            '*.*')
+
+    optional arguments:
+      -h, --help            show this help message and exit
+      -i, --id_as_name      Use transient digitizer ids as channel names, instead
+                            of descriptive names
+      -m MEASUREMENT_ID, --measurement_id MEASUREMENT_ID
+                            The new measurement id
+      -n MEASUREMENT_NUMBER, --measurement_number MEASUREMENT_NUMBER
+                            The measurement number for the date from 00 to 99.
+                            Used if no id is provided
+      -t TEMPERATURE, --temperature TEMPERATURE
+                            The temperature (in C) at lidar level, required if
+                            using US Standard atmosphere
+      -p PRESSURE, --pressure PRESSURE
+                            The pressure (in hPa) at lidar level, required if
+                            using US Standard atmosphere
+      -d, --debug           Print dubuging information.
+      -s, --silent          Show only warning and error messages.
+      --version             Show current version.
 
 Usage in python code
 --------------------
--- a/setup.py	Mon Nov 06 16:01:35 2017 +0200
+++ b/setup.py	Mon Nov 06 16:02:11 2017 +0200
@@ -54,6 +54,7 @@
           "sphinx",
       ],
       entry_points={
-          'console_scripts': ['licel2scc = atmospheric_lidar.scripts.licel2scc:main'],
+          'console_scripts': ['licel2scc = atmospheric_lidar.scripts.licel2scc:main',
+                              'licel2scc-depol = atmospheric_lidar.scripts.licel2scc_depol:main'],
       },
       )

mercurial