Fri, 02 Nov 2018 13:23:53 +0200
Initial classed to read diva L0 data format.
atmospheric_lidar/diva.py | file | annotate | diff | comparison | revisions | |
atmospheric_lidar/licel.py | file | annotate | diff | comparison | revisions |
--- a/atmospheric_lidar/diva.py Fri Oct 19 14:13:33 2018 +0300 +++ b/atmospheric_lidar/diva.py Fri Nov 02 13:23:53 2018 +0200 @@ -17,7 +17,7 @@ logger = logging.getLogger(__name__) -class DivaMixin: +class DivaConverterMixin: def save_as_diva_netcdf(self, output_path, parameter_file): """ Save the current data in the 'draft' DIVA format. """ @@ -29,8 +29,7 @@ global_variables = parameters['global_variables'] # Shortcut channels = parameters['channels'] - - iso_date = datetime.datetime.utcnow().isoformat() + iso_date = datetime.datetime.utcnow().strftime('%Y-%d-%mT%H:%M:%SZ') python_file_name = os.path.basename(__file__) with netcdf.Dataset(output_path, 'w', format="NETCDF4") as f: @@ -65,16 +64,16 @@ longitude.long_name = 'system longitude' longitude.units = 'degrees_east' - laser_angle = f.createVariable('laser_zenith_angle', datatype='f4') - laser_angle.standard_name = 'sensor_zenith_angle' - laser_angle.long_name = 'zenith angle of emitted laser' - laser_angle.units = 'degree' + lidar_zenith_angle = f.createVariable('lidar_zenith_angle', datatype='f4') + lidar_zenith_angle.standard_name = 'sensor_zenith_angle' + lidar_zenith_angle.long_name = 'zenith angle of emitted laser' + lidar_zenith_angle.units = 'degree' - laser_azimuth = f.createVariable('laser_azimuth_angle', datatype='f4') - laser_azimuth.standard_name = 'sensor_azimuth_angle' - laser_azimuth.long_name = 'azimuth angle of emitted laser' - laser_azimuth.units = 'degree' - laser_azimuth.comment = 'Based on North. Optional' + lidar_azimuth = f.createVariable('lidar_azimuth_angle', datatype='f4') + lidar_azimuth.standard_name = 'sensor_azimuth_angle' + lidar_azimuth.long_name = 'azimuth angle of emitted laser' + lidar_azimuth.units = 'degree' + lidar_azimuth.comment = 'Based on North. Optional' altitude = f.createVariable('altitude', datatype='f4') altitude.standard_name = 'altitude' @@ -84,7 +83,7 @@ # Assign top-level variables latitude[:] = global_variables['latitude'] longitude[:] = global_variables['longitude'] - laser_angle[:] = global_variables['laser_pointing_angle'] + lidar_zenith_angle[:] = global_variables['laser_pointing_angle'] altitude[:] = global_variables['system_altitude'] # Optional ancillary group @@ -418,46 +417,85 @@ return choices[pol_string] -class DivaLidarMeasurement(BaseLidarMeasurement): +class DivaLidarMeasurement(object): + """ A class to read raw lidar files in DIVA format. - def __init__(self, file_list): + Unlike other classes in this module, it does not inherit from BasicLidarMeasurement. This is done + 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): """ This is run when creating a new object. Parameters ---------- - file_list : list or str - A list of the full paths to the input file(s). + file_path : str + Paths to the input netCDF file. + import_now : bool + If True, the file is imported when the object is created. """ - if isinstance(file_list, str): - file_list = [file_list, ] - super(DivaLidarMeasurement, self).__init__(file_list=file_list) + self.file_path = file_path + self.file_name = os.path.basename(file_path) + + if import_now: + self.import_file(file_path) + + def import_file(self): + """ Import data from a single DIVA file. + """ + + logger.debug('Importing file {0}'.format(self.file_name)) + + self.channels = {} - def _import_file(self, filename): - """ Import data from a single DIVA file. """ + with netcdf.Dataset(self.file_path) as input_file: + self.title = input_file.title + self.source = input_file.source + self.institution = input_file.institution + self.references = input_file.references + self.location = input_file.location + self.data_version = input_file.data_version + self.PI = input_file.PI + self.PI_email = input_file.PI_email + self.conversion_date_str = input_file.conversion_date + self.conversion_date = datetime.datetime.strptime(input_file.conversion_date, '%Y-%d-%mT%H:%M:%SZ') + self.comment = input_file.comment + self.conventions = input_file.Conventions + self.history = input_file.history - logger.debug('Importing file {0}'.format(filename)) - current_file = self.file_class(filename, use_id_as_name=self.use_id_as_name, licel_timezone=self.licel_timezone) - self.durations[current_file.filename] = current_file.duration() + self.latitude = input_file.variables['latitude'][:] + self.longitude = input_file.variables['longitude'][:] + + self.lidar_zenith_angle = input_file.variables['lidar_zenith_angle'][:] + self.lidar_azimuth_angle = input_file.variables['lidar_azimuth_angle'][:] + self.lidar_altitude = input_file.variables['altitude'][:] + + ancillary = input_file.groups.pop('ancillary') + self.meteo_time = ancillary.variables['time'][:] + self.air_temperature_kelvin = ancillary.variable['air_temperature'][:] + self.air_pressure_hpa = ancillary.variable['air_pressure'][:] - self._create_or_append_channel(current_file) - file_laser_shots = [] - self.laser_shots.append(file_laser_shots) + 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) + class DivaChannel(object): - def __init__(self, file_name, channel_group): + def __init__(self, channel_name, group): """ This is run when first creating the object. Parameters ---------- - file_name : str - The filename of the diva dataset. - channel_group : str - The name of the netCDF4 group that holds the channel data. + channel_name : str + Name of the group + group : netCDF4.Group object + An open netcdf group to initialize. """ - self.file_name = file_name - self.channel_group = channel_group + self.group_name = channel_name + self. +
--- a/atmospheric_lidar/licel.py Fri Oct 19 14:13:33 2018 +0300 +++ b/atmospheric_lidar/licel.py Fri Nov 02 13:23:53 2018 +0200 @@ -7,7 +7,7 @@ import pytz from .generic import BaseLidarMeasurement, LidarChannel -from .diva import DivaMixin +from .diva import DivaConverterMixin logger = logging.getLogger(__name__) @@ -608,5 +608,6 @@ channel.analog_photon_string, channel.resolution, channel.points)) -class LicelDivaLidarMeasurement(DivaMixin, LicelLidarMeasurement): + +class LicelDivaLidarMeasurement(DivaConverterMixin, LicelLidarMeasurement): pass \ No newline at end of file