Tue, 07 Jun 2016 18:40:58 +0300
Automaticaly set measurement id and temerature/pressure when saving netcdfs.
Better handling of both depol and classic measurements.
--- a/atmospheric_lidar/generic.py Tue Jun 07 18:39:53 2016 +0300 +++ b/atmospheric_lidar/generic.py Tue Jun 07 18:40:58 2016 +0300 @@ -202,31 +202,56 @@ channel.update() - def set_measurement_id(self, measurement_id): + def set_measurement_id(self, measurement_id=None, measurement_number="00"): """ Sets the measurement id for the SCC file. - :param measurement_id: The string for measurement id + Parameters + ---------- + measurement_id: str + A measurement id with the format YYYYMMDDccNN, where YYYYMMDD the date, + cc the earlinet call sign and NN a number between 00 and 99. + measurement_number: str + If measurement id is not provided the method will try to create one + based on the input dete. The measurement number can specify the value + of NN in the created ID. """ + if measurement_id is None: + date_str = self.info['start_time'].strftime('%Y%m%d') + try: + earlinet_station_id = self.extra_netcdf_parameters.general_parameters['Call sign'] + except: + raise ValueError("No valid SCC netcdf parameters found. Did you define create the proper subclass?") + measurement_id = "{0}{1}{2}".format(date_str, earlinet_station_id, measurement_number) + self.info['Measurement_ID'] = measurement_id - def save_as_netcdf(self, filename = None): """Saves the measurement in the netcdf format as required by the SCC. Input: filename. If no filename is provided <measurement_id>.nc will be used. """ params = self.extra_netcdf_parameters - needed_parameters = ['Measurement_ID', 'Temperature', 'Pressure'] - - for parameter in needed_parameters: + + + # Guess measurement ID if none is provided + if 'Measurement_ID' not in self.info: + self.set_measurement_id() + + # Check if temperature and pressure are defined + for parameter in ['Temperature', 'Pressure']: stored_value = self.info.get(parameter, None) if stored_value is None: - raise ValueError('A value needs to be specified for %s' % parameter) + try: + self.get_PT() + except: + raise ValueError('A value needs to be specified for %s' % parameter) if not filename: filename = "%s.nc" % self.info['Measurement_ID'] - + + self.scc_filename = filename + dimensions = {'points': 1, 'channels': 1, 'time': None, @@ -249,18 +274,8 @@ 'Longitude_degrees_east': None, 'Altitude_meter_asl': None} - channel_variables = \ - {'channel_ID': (('channels', ), 'i'), - 'Background_Low': (('channels', ), 'd'), - 'Background_High': (('channels', ), 'd'), - 'LR_Input': (('channels', ), 'i'), - 'DAQ_Range': (('channels', ), 'd'), - 'Depolarization_Factor': (('channels', ), 'd'), - 'Pol_Calib_Range_Min': (('channels', ), 'd'), - 'Pol_Calib_Range_Max': (('channels', ), 'd'), - } - - + channel_variables = self._get_scc_channel_variables() + channels = self.channels.keys() input_values = dict(self.dimensions, **self.variables) @@ -351,7 +366,18 @@ self.save_netcdf_extra(f) f.close() - + + def _get_scc_channel_variables(self): + channel_variables = \ + {'channel_ID': (('channels',), 'i'), + 'Background_Low': (('channels',), 'd'), + 'Background_High': (('channels',), 'd'), + 'LR_Input': (('channels',), 'i'), + 'DAQ_Range': (('channels',), 'd'), + 'Depolarization_Factor': (('channels',), 'd'), + } + return channel_variables + def add_dark_measurements_to_netcdf(self, f, channels): # Get dark measurements. If it is not given in self.dark_measurement
--- a/atmospheric_lidar/licel_depol.py Tue Jun 07 18:39:53 2016 +0300 +++ b/atmospheric_lidar/licel_depol.py Tue Jun 07 18:40:58 2016 +0300 @@ -125,6 +125,30 @@ new_measurement = self.subset_by_channels(ph_channels) return new_measurement + def _get_scc_channel_variables(self): + """ + Get a list of variables to put in the SCC. + + It can be overridden e.g. in the depolarization product class. + + Returns + ------- + + channel_variables: dict + A dictionary with channel variable specifications. + """ + channel_variables = \ + {'channel_ID': (('channels',), 'i'), + 'Background_Low': (('channels',), 'd'), + 'Background_High': (('channels',), 'd'), + 'LR_Input': (('channels',), 'i'), + 'DAQ_Range': (('channels',), 'd'), + 'Depolarization_Factor': (('channels',), 'd'), + 'Pol_Calib_Range_Min': (('channels',), 'd'), + 'Pol_Calib_Range_Max': (('channels',), 'd'), + } + return channel_variables + class UnequalMeasurementLengthError(RuntimeError): """ Raised when the plus and minus files have different length. """
--- a/atmospheric_lidar/lilas_netcdf_parameters.py Tue Jun 07 18:39:53 2016 +0300 +++ b/atmospheric_lidar/lilas_netcdf_parameters.py Tue Jun 07 18:40:58 2016 +0300 @@ -4,7 +4,8 @@ 'Molecular_Calc': 0, # Use US standard atmosphere 'Latitude_degrees_north': 50.63, 'Longitude_degrees_east': 3.07, - 'Altitude_meter_asl': 0.4} + 'Altitude_meter_asl': 0.4, + 'Call sign': 'mb',} channel_parameters = \ {'00355.p_an': {'channel_ID': 41, @@ -27,8 +28,22 @@ 'Laser_Shots': 1000, 'LR_Input': 1, 'DAQ_Range': 500.0, + 'Depolarization_Factor': 0.88,}, + '00355.s_ph': {'channel_ID': 42, + 'Background_Low': 19000, + 'Background_High': 20000, + 'Laser_Shots': 1000, + 'LR_Input': 1, + 'DAQ_Range': 0, + 'Depolarization_Factor': 0.88}, + '00530.o_an': {'channel_ID': 43, + 'Background_Low': 19000, + 'Background_High': 20000, + 'Laser_Shots': 1000, + 'LR_Input': 1, + 'DAQ_Range': 500.0, 'Depolarization_Factor': 0,}, - '00355.s_ph': {'channel_ID': 42, + '00530.o_ph': {'channel_ID': 44, 'Background_Low': 19000, 'Background_High': 20000, 'Laser_Shots': 1000, @@ -55,14 +70,14 @@ 'Laser_Shots': 1000, 'LR_Input': 1, 'DAQ_Range': 500.0, - 'Depolarization_Factor': 0,}, + 'Depolarization_Factor': 0.77,}, '00532.s_ph': {'channel_ID': 44, 'Background_Low': 19000, 'Background_High': 20000, 'Laser_Shots': 1000, 'LR_Input': 1, 'DAQ_Range': 0, - 'Depolarization_Factor': 0,}, + 'Depolarization_Factor': 0.77,}, '01064.o_an': {'channel_ID': 45, 'Background_Low': 19000, 'Background_High': 20000, @@ -91,11 +106,4 @@ 'LR_Input': 1, 'DAQ_Range': 0, 'Depolarization_Factor': 0,}, - '00607.o_ph': {'channel_ID': 47, - 'Background_Low': 19000, - 'Background_High': 20000, - 'Laser_Shots': 1000, - 'LR_Input': 1, - 'DAQ_Range': 0, - 'Depolarization_Factor': 0,}, }
--- a/readme.rst Tue Jun 07 18:39:53 2016 +0300 +++ b/readme.rst Tue Jun 07 18:40:58 2016 +0300 @@ -7,14 +7,14 @@ Set up ------ -### Parameter file - +Parameter file +~~~~~~~~~~~~~~ Before using the classes you need to setup some channel parameters, that are used when converting the lidar data to Single Calculus Chain format. All the parameters are read from an external file stored in the same folder as the code. You can start by changing the file “cf_netcdf_parameters.py” that describe such parameters for the Clermont Ferrand lidar. -### System class - +System class +~~~~~~~~~~~~ The next thing you need to create a class that describes you system. This is very simple if your lidar data are in the Licel format, as you only need to specify the external file with the extra SCC parameters. You can use as an example the file “cf_raymetrics.py”: :::python