Fri, 02 Nov 2018 16:11:06 +0200
More changes on Diva channels.
atmospheric_lidar/diva.py | file | annotate | diff | comparison | revisions |
--- a/atmospheric_lidar/diva.py Fri Nov 02 13:23:53 2018 +0200 +++ b/atmospheric_lidar/diva.py Fri Nov 02 16:11:06 2018 +0200 @@ -184,7 +184,7 @@ polarizer_angle.units = 'degree' polarizer_angle.comments = 'Optional' - if not channel.is_analog: + if channel.is_photon_counting: dead_time_model = g.createVariable('dead_time_model', datatype='b') dead_time_model.long_name = 'optimal dead time model of detection system' dead_time_model.flag_values = '0b 1b 2b' @@ -424,7 +424,7 @@ to avoid all the burden of backward compatibility. In the future this could be hosted also as a separte moduel. """ - def __init__(self, file_path, import_now=True): + def __init__(self, file_path, header_only=False): """ This is run when creating a new object. @@ -432,16 +432,15 @@ ---------- file_path : str Paths to the input netCDF file. - import_now : bool - If True, the file is imported when the object is created. + header_only : bool + If True, channel info are not loaded. """ self.file_path = file_path self.file_name = os.path.basename(file_path) - if import_now: - self.import_file(file_path) + self.import_file(file_path, header_only) - def import_file(self): + def import_file(self, header_only): """ Import data from a single DIVA file. """ @@ -477,10 +476,24 @@ self.air_temperature_kelvin = ancillary.variable['air_temperature'][:] self.air_pressure_hpa = ancillary.variable['air_pressure'][:] + self.available_channels = [] for group_name, group in input_file.groups.items(): channel_name = group_name[8:] # Remove 'channel_' prefix - self.channels[channel_name] = DivaChannel(channel_name, group) + self.available_channels.append(channel_name) + + if not header_only: + self.channels[channel_name] = DivaChannel(channel_name, group) + def import_channel(self, channel_name): + """ Import a specific channel. """ + if channel_name not in self.available_channels: + raise ValueError('Channel {0} not available. Should be one of {1}'.format(channel_name, self.available_channels)) + + group_name = 'channel_{0}'.format(channel_name) + + with netcdf.Dataset(self.file_path) as input_file: + group = input_file.groups[group_name] + self.channels[channel_name] = DivaChannel(channel_name, group) class DivaChannel(object): @@ -495,7 +508,133 @@ group : netCDF4.Group object An open netcdf group to initialize. """ - self.group_name = channel_name + self.channel_name = channel_name + + self.long_name = group.long_name + self.detector_manufacturer = group.detector_manufacturer + self.detector_model = group.detector_model + self.daq_manufacturer = group.daq_manufacturer + self.daq_model = group.daq_model + + self.number_of_profiles = len(group.dimensions['profile']) + self.number_of_bins = len(group.dimensions['range']) + self.channel_id = group.variables['channel_id'][:] + self.laser_repetition_rate = group.variables['laser_repetition_rate'][:] + + self.emission_energy_mJ = group.variables['emission_energy'][:] + self.emission_polarization_flag = group.variables['emission_polarization'][:] + self.emission_polarization = self._flag_to_polarization(self.emission_polarization_flag) + self.field_of_view = group.variables['fov'][:] + self.field_of_view_comment = group.variables['fov'].comment + + self.detector_type_flag = group.variables['detector_type'][:] + self.detector_type = self._flag_to_detector_type(self.detector_type_flag) + + self.detection_mode_flag = group.variables['detection_mode'][:] + self.detection_mode = self._flag_to_detector_type(self.detection_mode_flag) + + self.detection_wavelength_nm = group.variables['detection_wavelength'][:] + self.detection_fwhm = group.variables['detection_fwhm'][:] + + self.detection_polarization_flag = group.variables['detection_polarization'] + self.detection_polariation = self._flag_to_detection_polarization(self.detection_polarization_flag) + + self.polarizer_angle_degrees = group.variables['polarizer_angle'][:] + + if self.is_photon_counting: + self.dead_time_model_flag = group.variables['dead_time_model'][:] + self.dead_time_model = self._flag_to_dead_time_model(self.dead_time_model_flag) + + self.dead_time = group.variables['dead_time'][:] + self.dead_time_source = group.variables['dead_time'].comment + self.discriminator = group.variables['discriminator'][:] + + if self.is_analog: + self.adc_bits = group.variables['adc_bits'][:] + self.adc_range = group.variables['adc_range'][:] + + self.bin_length_ns = group.variables['bin_length'][:] + self.detector_voltage = group.variables['detector_voltage'][:] + self.pulses = group.variables['pulses'][:] + self.nd_filter_od = group.variables['nd_filter_od'][:] + self.trigger_delay_ns = group.variables['trigger_delay'][:] + self.time_since_epoch = group.variables['time'][:] + + self.time = [datetime.datetime.utcfromtimestamp(t) for t in self.time_since_epoch] + self.bin_time_ns = group.variables['bin_time'][:] + + self.signal = group.variables['signal'][:] + self.signal_units = group.variables['signal'].units + + signal_stddev_var = group.variables.pop('signal_stddev', None) + + if signal_stddev_var: + self.signal_stddev = signal_stddev_var[:] + else: + self.signal_stddev = None - self. + def _flag_to_polarization(self, flag): + """ Convert polarization flag to str""" + if flag not in [0, 1, 2]: + logger.warning('Polarization flag has unrecognized value: {0}'.format(flag)) + return "" + + values = {0: 'linear', + 1: 'circular', + 2: 'None'} + + return values[flag] + + def _flag_to_detector_type(self, flag): + """ Convert detector type flag to str""" + if flag not in [0, 1]: + logger.warning('Detector type flag has unrecognized value: {0}'.format(flag)) + return "" + + values = {0: 'PMT', + 1: 'APD',} + + return values[flag] + + def _flag_to_detection_mode(self, flag): + """ Convert detector type flag to str""" + if flag not in [0, 1]: + logger.warning('Detection mode flag has unrecognized value: {0}'.format(flag)) + return "" + + values = {0: 'analog', + 1: 'photon counting'} + return values[flag] + + def _flag_to_detection_polarization(self, flag): + """ Convert detector type flag to str""" + if flag not in [0, 1, 2]: + logger.warning('Detection polarization flag has unrecognized value: {0}'.format(flag)) + return "" + + values = {0: 'linear', + 1: 'circular', + 2: 'total',} + + return values[flag] + + def _flag_to_dead_time_model(self, flag): + """ Convert detector type flag to str""" + if flag not in [0, 1, 2]: + logger.warning('Dead time model flag has unrecognized value: {0}'.format(flag)) + return "" + + values = {0: 'paralyzable', + 1: 'non_paralyzable', + 2: 'other', } + + return values[flag] + + @property + def is_analog(self): + return self.detection_mode_flag==0 + + @property + def is_photon_counting(self): + return self.detection_mode_flag==1 \ No newline at end of file