More changes on Diva channels.

Fri, 02 Nov 2018 16:11:06 +0200

author
Iannis B <ioannis@inoe.ro>
date
Fri, 02 Nov 2018 16:11:06 +0200
changeset 166
ab21bd91bc09
parent 165
392a714d12a2
child 167
0604a628fb1e

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

mercurial