Fri, 14 Feb 2020 12:38:45 +0200
Support of naming channels by order. In principle should not be required.
--- a/atmospheric_lidar/licel.py Tue Dec 10 13:24:02 2019 +0200 +++ b/atmospheric_lidar/licel.py Fri Feb 14 12:38:45 2020 +0200 @@ -17,7 +17,7 @@ class LicelChannelData: """ A class representing a single channel found in a single Licel file.""" - def __init__(self, raw_info, raw_data, duration, use_id_as_name=False): + def __init__(self, raw_info, raw_data, duration, use_id_as_name=False, channel_name=None): """ This is run when creating a new object. @@ -32,11 +32,14 @@ use_id_as_name : bool If True, the transient digitizer name (e.g. BT0) is used as a channel name. If False, a more descriptive name is used (e.g. '01064.o_an'). + channel_name : str or None + If provided, it will override the automatic generated channel name. It can be used if names are not unique. """ self.raw_info = raw_info self.raw_data = raw_data self.duration = duration self.use_id_as_name = use_id_as_name + self.channel_name_input = channel_name self._assign_properties() def _assign_properties(self): @@ -90,6 +93,9 @@ channel_name : str The channel name """ + if self.channel_name_input is not None: + return self.channel_name_input + if self.use_id_as_name: channel_name = self.id else: @@ -168,7 +174,7 @@ # If True, it corrects the old Raymetrics convention of zenith angle definition (zenith = -90 degrees) fix_zenith_angle = False - def __init__(self, file_path, use_id_as_name=False, licel_timezone="UTC", import_now=True): + def __init__(self, file_path, use_id_as_name=False, get_name_by_order=False, licel_timezone="UTC", import_now=True): """ This is run when creating a new object. @@ -179,6 +185,9 @@ use_id_as_name : bool If True, the transient digitizer name (e.g. BT0) is used as a channel name. If False, a more descriptive name is used (e.g. '01064.o_an'). + get_name_by_order : bool + If True, the channel name is given by the order of the channel in the file. In this case the + `use_id_as_name` variable is ignored. licel_timezone : str The timezone of dates found in the Licel files. Should match the available timezones in the TZ database. @@ -191,6 +200,7 @@ self.file_name = os.path.basename(file_path) self.use_id_as_name = use_id_as_name + self.get_name_by_order = get_name_by_order self.start_time = None self.stop_time = None self.licel_timezone = licel_timezone @@ -214,7 +224,7 @@ f.readline() # Import the data - for current_channel_info in self.channel_info: + for channel_no, current_channel_info in enumerate(self.channel_info): raw_data = np.fromfile(f, 'i4', int(current_channel_info['number_of_datapoints'])) a = np.fromfile(f, 'b', 1) b = np.fromfile(f, 'b', 1) @@ -223,8 +233,13 @@ logger.warning("No end of line found after record. File could be corrupt: %s" % self.file_path) logger.warning('a: {0}, b: {1}.'.format(a, b)) + if self.get_name_by_order: + channel_name = channel_no + else: + channel_name = None + channel = self.channel_data_class(current_channel_info, raw_data, self.duration(), - use_id_as_name=self.use_id_as_name) + use_id_as_name=self.use_id_as_name, channel_name=channel_name) # Assign the channel either as normal channel or photodiode if channel.is_photodiode: @@ -488,12 +503,13 @@ channel_class = LicelChannel photodiode_class = PhotodiodeChannel - def __init__(self, file_list=None, use_id_as_name=False, licel_timezone='UTC'): + def __init__(self, file_list=None, use_id_as_name=False, get_name_by_order=False, licel_timezone='UTC'): self.raw_info = {} # Keep the raw info from the files self.durations = {} # Keep the duration of the files self.laser_shots = [] self.use_id_as_name = use_id_as_name + self.get_name_by_order = get_name_by_order self.licel_timezone = licel_timezone self.photodiodes = {} @@ -506,6 +522,7 @@ else: logger.debug('Importing file {0}'.format(filename)) current_file = self.file_class(filename, use_id_as_name=self.use_id_as_name, + get_name_by_order=self.get_name_by_order, licel_timezone=self.licel_timezone) self.raw_info[current_file.file_path] = current_file.raw_info self.durations[current_file.file_path] = current_file.duration()
--- a/atmospheric_lidar/licelv2.py Tue Dec 10 13:24:02 2019 +0200 +++ b/atmospheric_lidar/licelv2.py Fri Feb 14 12:38:45 2020 +0200 @@ -132,7 +132,7 @@ # If True, it corrects the old Raymetrics convention of zenith angle definition (zenith = -90 degrees) fix_zenith_angle = False - def __init__(self, file_path, licel_timezone="UTC", import_now=True): + def __init__(self, file_path, licel_timezone="UTC", get_name_by_order=False, import_now=True): """ This is run when creating a new object. @@ -150,6 +150,7 @@ """ super(LicelFileV2, self).__init__(file_path=file_path, use_id_as_name=False, # Obsolete + get_name_by_order=get_name_by_order, licel_timezone=licel_timezone, import_now=import_now) @@ -316,12 +317,13 @@ powermeter_class = PhotodiodeChannel standard_deviation_class = LicelV2Channel - def __init__(self, file_list=None, licel_timezone='UTC'): + def __init__(self, file_list=None, get_name_by_order=False, licel_timezone='UTC'): self.standard_deviations = {} self.powermeters = {} super(LicelLidarMeasurementV2, self).__init__(file_list=file_list, + get_name_by_order=get_name_by_order, use_id_as_name=False, licel_timezone=licel_timezone)
--- a/atmospheric_lidar/raymetrics.py Tue Dec 10 13:24:02 2019 +0200 +++ b/atmospheric_lidar/raymetrics.py Fri Feb 14 12:38:45 2020 +0200 @@ -66,6 +66,7 @@ licel_file_channel_format = 'active analog_photon laser_used number_of_datapoints 1 HV bin_width wavelength d1 d2 d3 d4 ADCbits number_of_shots discriminator ID' fix_zenith_angle = True + skip_scan_overview_line = False # Skip the 3d line containing azimuth_start, stop etc. Used to overcome a bug in some output files. def _read_rest_of_header(self, f): """ Read the third and fourth row of of the header lines. @@ -97,13 +98,23 @@ self.azimuth_angle_raw = float(self.raw_info['azimuth_angle']) self.temperature = float(self.raw_info['temperature']) self.pressure = float(self.raw_info['pressure']) - self.azimuth_start_raw = float(self.raw_info['azimuth_start']) - self.azimuth_stop_raw = float(self.raw_info['azimuth_stop']) - self.azimuth_step = float(self.raw_info['azimuth_step']) - self.zenith_start_raw = float(self.raw_info['zenith_start']) - self.zenith_stop_raw = float(self.raw_info['zenith_stop']) - self.zenith_step = float(self.raw_info['zenith_step']) - self.azimuth_offset = float(self.raw_info['azimuth_offset']) + + if not self.skip_scan_overview_line: + self.azimuth_start_raw = float(self.raw_info['azimuth_start']) + self.azimuth_stop_raw = float(self.raw_info['azimuth_stop']) + self.azimuth_step = float(self.raw_info['azimuth_step']) + self.zenith_start_raw = float(self.raw_info['zenith_start']) + self.zenith_stop_raw = float(self.raw_info['zenith_stop']) + self.zenith_step = float(self.raw_info['zenith_step']) + self.azimuth_offset = float(self.raw_info['azimuth_offset']) + else: + self.azimuth_start_raw = np.nan + self.azimuth_stop_raw = np.nan + self.azimuth_step = np.nan + self.zenith_start_raw = np.nan + self.zenith_stop_raw = np.nan + self.zenith_step = np.nan + self.azimuth_offset = 0 self.azimuth_angle = (self.azimuth_angle_raw + self.azimuth_offset) % 360 self.azimuth_start = (self.azimuth_start_raw + self.azimuth_offset) % 360 @@ -690,6 +701,10 @@ return lat_out, lon_out, Z +class ScanningFileMissingLine(ScanningFile): + skip_scan_overview_line = True + + class ScanningLidarMeasurement(LicelLidarMeasurement): """ A class representing a scanning measurement set.