Fri, 15 Dec 2017 12:58:20 +0200
Some thoughts on DIVA file format parameters.
atmospheric_lidar/diva.py | file | annotate | diff | comparison | revisions | |
atmospheric_lidar/systems/rali/rali_diva_parameters.yaml | file | annotate | diff | comparison | revisions |
--- a/atmospheric_lidar/diva.py Fri Dec 15 08:50:40 2017 +0200 +++ b/atmospheric_lidar/diva.py Fri Dec 15 12:58:20 2017 +0200 @@ -20,6 +20,7 @@ parameters = pyyaml.load(f) global_parameters = parameters['global_parameters'] # Shortcut + channels = parameters['channels'] iso_date = datetime.datetime.utcnow().isoformat() python_file_name = os.path.basename(__file__) @@ -39,6 +40,10 @@ f.history = global_parameters['history'].format(date=iso_date, file=python_file_name) f.featureType = "timeSeriesProfile" + # Top level dimensions + f.createDimension('name_strlen', size=40) + f.createDimension('nv', size=2) + # Top level variables latitude = f.createVariable('latitude', datatype='f4') latitude.standard_name = 'latitude' @@ -55,117 +60,160 @@ laser_angle.long_name = 'zenith angle of emitted laser' laser_angle.units = 'degree' - laser_angle = f.createVariable('laser_zenith_angle', datatype='f4') - laser_angle.long_name = 'zenith angle of emitted laser' - laser_angle.units = 'degrees' + 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' altitude = f.createVariable('altitude', datatype='f4') altitude.standard_name = 'altitude' altitude.long_name = 'system altitude' altitude.units = 'm' + for channel_name, channel_parameters in channels.iteritems(): - # Create a separate group for each channel - f = f.createGroup("channel_532nmP") # This should be changed to a meaningful channel name - f.data_type = self.data_type + # Create a separate group for each channel + group_name = "channel_{0}".format(channel_name) # Give channels groups a standard name + g = f.createGroup(group_name) + g.long_name = channel_parameters['long_name'] + g.detector_manufacturer = channel_parameters['long_name'] # Optional + g.detector_model = channel_parameters['detector_model'] + g.daq_manufacturer = channel_parameters['daq_manufacturer'] + g.daq_model = channel_parameters['daq_model'] - f.createDimension('profile', len(self.time)) - f.createDimension('range', len(self.range)) + # Dimensions + g.createDimension('profile', size=None) # Infinite dimension + g.createDimension('range', len(self.range)) - id = f.createVariable('channel_id', 'i4') - id.cf_role = "trajectory_id" + # Variables + name = g.createVariable('channel_id', dimensions=('name_strlen',)) + name.cf_role = 'timeseries_id' + name.long_name = 'channel identification' - latitude = f.createVariable('latitude', datatype='f8', dimensions=('profile',), zlib=True) - latitude.long_name = 'aircraft GPS latitude' - latitude.units = 'degrees_north' - latitude.standard_name = 'latitude' + laser_rep_rate = g.createVariable('laser_repetition_rate') + laser_rep_rate.long_name = 'nominal laser repetition rate' + laser_rep_rate.units = 'Hz' - longitude = f.createVariable('longitude', datatype='f8', dimensions=('profile',), zlib=True) - longitude.long_name = 'aircraft GPS longitude' - longitude.units = 'degrees_east' - longitude.standard_name = 'longitude' + emission_energy = g.createVariable('emission_energy', datatype='f8', dimensions=('profile',)) + emission_energy.long_name = 'emission energy per pulse' + emission_energy.units = 'mJ' + emission_energy.standard_name = 'radiation_wavelength' + emission_energy.comment = "could be scalar, if value is nominal." - altitude = f.createVariable('altitude', datatype='f4', dimensions=('profile',), zlib=True) - altitude.long_name = 'aircraft GPS altitude' - altitude.units = 'm' - altitude.standard_name = 'altitude' + emission_pol = g.createVariable('emission_polarization', datatype='b') + emission_pol.long_name = 'nominal emission poalrization' + emission_pol.flag_values = '0b 1b 2b' + emission_pol.flag_meanings = 'linear circular none' - time = f.createVariable('time', datatype='f8', dimensions=('profile',), - zlib=True) - time.long_name = 'starting time of record' - time.units = "seconds since 1970-01-01 00:00:00" - time.standard_name = "time" + fov = g.createVariable('fov', datatype='f4') + fov.long_name = 'channel field of view full angle' + fov.units = 'mrad' + fov.comment = 'simulated' + + detector_type = g.createVariable('detector_type', datatype='b') + detector_type.long_name = 'detector type' + detector_type.flag_values = '0b 1b' + detector_type.flag_meanings = 'PMT APD' - bin_range = f.createVariable('range', datatype='f4', dimensions=('range',), - zlib=True) # Use name 'bin_range' to avoid conflict with built-in range - bin_range.long_name = 'range from instrument' - bin_range.units = "m" - bin_range.positive = "down" - bin_range.axis = 'Z' # This is strictly not correct, as it does not correspond to geophysical variable. Still it can be usefull for quick plotting. + detection_mode = g.createVariable('detection_mode', datatype='b') + detection_mode.long_name = 'detection mode' + detection_mode.flag_values = '0b 1b' + detection_mode.flag_meanings = 'analog photon_counting' + + detection_cw = g.createVariable('detection_wavelength', datatype='f8') + detection_cw.long_name = 'center wavelength of detection filters' + detection_cw.units = 'nm' + detection_cw.standard_name = 'sensor_band_central_radiation_wavelength' - pitch = f.createVariable('pitch', datatype='f4', dimensions=('profile',), zlib=True) - pitch.long_name = 'aircraft pitch' - pitch.units = 'degree' - pitch.standard_name = 'platform_pitch_angle' - pitch.coordinates = "time longitude latitude" + detection_fwhm = g.createVariable('detection_fwhm', datatype='f8') + detection_fwhm.long_name = 'FWHM of detection filters' + detection_fwhm.units = 'nm' - roll = f.createVariable('roll', datatype='f4', dimensions=('profile',), zlib=True) - roll.long_name = 'aircraft roll' - roll.units = 'degree' - roll.standard_name = 'platform_roll_angle' - roll.coordinates = "time longitude latitude" + detection_pol = g.createVariable('detection_polarization', datatype='b') + detection_pol.long_name = 'nominal detection poalrization' + detection_pol.flag_values = '0b 1b 2b' + detection_pol.flag_meanings = 'linear circular none' + + polarizer_angle = g.createVariable('polarizer_angle', datatype='f4', dimensions=('profile', ), zlib=True) + polarizer_angle.long_name = 'polarizer angle in respect to laser plane of polarization' + polarizer_angle.units = 'degree' + polarizer_angle.comments = 'Optional' - heading = f.createVariable('heading', datatype='f4', dimensions=('profile',), zlib=True) - heading.long_name = 'aircraft heading' - heading.units = 'degree' - heading.standard_name = 'platform_course' - heading.coordinates = "time longitude latitude" + 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' + dead_time_model.flag_meanings = 'paralyzable non_paralyzable other' - hv = f.createVariable('hv', datatype='f4', dimensions=('profile',), zlib=True) - hv.long_name = 'detector high voltage' - hv.units = 'V' - hv.coordinates = "time longitude latitude" + dead_time = g.createVariable('dead_time', datatype='f8') + dead_time.long_name = 'dead time value' + dead_time.units = 'ns' + dead_time.comment = "Manufacturer. Source of the value." + + bin_length = g.createVariable('bin_length', datatype='f4') + bin_length.long_name = "time duration of each bin" + bin_length.units = 'ns' + + detector_voltage = g.createVariable('detector_voltage', datatype='f4', dimensions=('profile',), zlib=True) + detector_voltage.long_name = 'detector voltage' + detector_voltage.units = 'V' + detector_voltage.coordinates = "time" - averaging_time = f.createVariable('averaging_time', datatype='f4', dimensions=('profile',), zlib=True) - averaging_time.long_name = 'averaging time' - averaging_time.units = 's' - averaging_time.coordinates = "time longitude latitude" + discriminator = g.createVariable('discriminator', datatype='f8', dimensions=('profiles',)) + discriminator.long_name = 'discriminator level' + discriminator.units = '' + + adc_range = g.createVariable('adc_range', datatype='f4', dimensions=('profile',), + zlib=True) + adc_range.long_name = 'analog-to-digital converter range' + adc_range.units = 'mV' + adc_range.coordinates = "time" - emission_wl = f.createVariable('emission_wavelength', datatype='f8', dimensions=('profile',), - zlib=True) - emission_wl.long_name = 'emission wavelength in vacuum' - emission_wl.units = 'nm' - emission_wl.standard_name = 'radiation_wavelength' - emission_wl.coordinates = "time longitude latitude" + adc_bits = g.createVariable('adc_bits', datatype='i4', dimensions=('profile',), + zlib=True) + adc_bits.long_name = 'analog-to-digital converter bits' + adc_bits.coordinates = "time" + + pulses = g.createVariable('pulses', datatype='i4', dimensions=('profile',), + zlib=True) + pulses.long_name = 'accumulated laser pulses per record' + pulses.coordinates = "time" - pulses = f.createVariable('pulses', datatype='i4', dimensions=('profile',), - zlib=True) - pulses.long_name = 'laser pulses per record' - pulses.coordinates = "time longitude latitude" + nd_filter = g.createVariable('nd_filter_od', datatype='f8', dimensions=('profile',)) + nd_filter.long_name = "neutral density filter optical depth " + nd_filter.coordinates = "time" - signal = f.createVariable('signal', datatype='i4', dimensions=('profile', 'range'), - zlib=True) - signal.long_name = 'signal' - signal.units = "counts" - signal.missing_value = -1 - signal.coordinates = "time longitude latitude range" + emission_delay = g.createVariable('emission_delay', datatype='f4') + emission_delay.long_name = "pulse emission difference from channel trigger" + emission_delay.units = 'ns' + emission_delay.comments = 'Positive values for pre-trigger systems. Negative for trigger delay.' - # Assign channel attributes - f.channel_name = 'L_532nmP' + time = g.createVariable('time', datatype='f8', dimensions=('profile',), + zlib=True) + time.long_name = 'profile start time ' + time.units = "seconds since 1970-01-01 00:00:00" + time.standard_name = "time" + time.bounds = "time_bnds" + g.createVariable('time_bnds', datatype='f8', dimensions=('profile', 'nv'), zlib=True) - # Assign variables - id[:] = 1 - latitude[:] = self.latitude[:] - longitude[:] = self.longitude[:] - altitude[:] = self.gps_altitude[:] - pitch[:] = self.pitch[:] - roll[:] = self.roll[:] - heading[:] = self.heading_angle[:] - hv[:] = self.high_voltage[:] - averaging_time[:] = self.averaging_time[:] - emission_wl[:] = self.emission_wavelength_vacuum[:] - pulses[:] = self.pulses[:] - time[:] = self.time[:] - bin_range[:] = self.range[:] - signal[:] = self.signal[:] + bin_time = g.createVariable('bin_time', datatype='f4', dimensions=('range',), + zlib=True) # Use name 'bin_range' to avoid conflict with built-in range + bin_time.long_name = 'bin start time since trigger' + bin_time.units = "ns" + signal = g.createVariable('signal', datatype='i4', dimensions=('profile', 'range'), + zlib=True) + signal.long_name = 'signal' + signal.units = channel_parameters['signal_units'] + signal.coordinates = "time" + signal.ancillary_variables = "signal_stddev" + + # If measured + signal_stddev = g.createVariable('signal', datatype='i4', dimensions=('profile', 'range'), + zlib=True) + signal_stddev.long_name = 'signal standard deviation' + signal_stddev.units = channel_parameters['signal_units'] + signal_stddev.coordinates = "time" + + # Assign variables + # TBD \ No newline at end of file
--- a/atmospheric_lidar/systems/rali/rali_diva_parameters.yaml Fri Dec 15 08:50:40 2017 +0200 +++ b/atmospheric_lidar/systems/rali/rali_diva_parameters.yaml Fri Dec 15 12:58:20 2017 +0200 @@ -4,10 +4,10 @@ institution: INOE, Bucharest, Romania references: Nemuc, A. et al, Atmos. Meas. Tech. 6, 3243–3255, 2013. Conventions: CF-1.7 - comment: "Test file" + comment: Test file location: Magurele, Bucharest, Romania data_version: 1.0 - history: "{date} {file} Data file created\n" + history: "{date} {file} Data file created.\n" global_variables: laser_pointing_angle: 0 latitude: 44.348 @@ -15,7 +15,26 @@ system_altitude: 93.0 channels: 01064.o_an: - Laser_Shots: 3000 - DAQ_Range: 100.0 - - + long_name: elastic signal + detector_type: APD + detection_mode: analog # analog or photon-counting + detector_manufacturer: Hamamatsu # Optional + detector_model: ABC # Optional + daq_manufacturer: Licel # Optional + daq_model: - # Optional + bin_length: 50 # ns + pulse_delay: 5000 # ns + laser_repetition_rate: 10 # Hz + signal_units: mV # counts or mV + emission_wavelength: 1064.01 # nm + emission_polarization: linear # linear, circular, or none + filter_cw: 1064.01 # nm + filter_fwhm: 1. # nm + fov: 2.4 # mrad full angle + detection_polarization: linear # linear, circular, or none + polarizer_angle: 0. # polarization angle in case of linear polarization + dead_time_model: paralyzable # paralyzable, non-paralyzable, or other + dead_time: 3.8 # ns + 00532.p_ph: + discriminator: 10 # discriminator level +