atmospheric_lidar/scripts/licel2scc_depol.py

Wed, 10 Oct 2018 15:58:32 +0300

author
Iannis <i.binietoglou@impworks.gr>
date
Wed, 10 Oct 2018 15:58:32 +0300
changeset 163
40331f37885f
parent 160
db28629317fa
child 164
e4915d84dd7d
permissions
-rw-r--r--

More things TODO

ulalume3@64 1 """ Command line tool to convert Licel binary files to SCC NetCDF format.
ulalume3@64 2 """
ulalume3@64 3 import argparse
ulalume3@64 4 import glob
ulalume3@64 5 import importlib
ulalume3@64 6 import logging
ulalume3@64 7 import os
ulalume3@64 8 import sys
ulalume3@64 9
ulalume3@64 10 from ..licel_depol import LicelCalibrationMeasurement
ulalume3@67 11 from ..__init__ import __version__
ulalume3@64 12
i@103 13 logger = logging.getLogger(__name__)
i@103 14
ulalume3@64 15
i@101 16 def create_custom_class(custom_netcdf_parameter_path, use_id_as_name=False, temperature=25., pressure=1020.,
i@101 17 licel_timezone='UTC'):
ulalume3@64 18 """ This funtion creates a custom LicelLidarMeasurement subclass,
ulalume3@64 19 based on the input provided by the users.
ulalume3@64 20
ulalume3@64 21 Parameters
ulalume3@64 22 ----------
i@103 23 custom_netcdf_parameter_path : str
ulalume3@64 24 The path to the custom channels parameters.
i@103 25 use_id_as_name : bool
ulalume3@64 26 Defines if channels names are descriptive or transient digitizer IDs.
i@103 27 temperature : float
ulalume3@64 28 The ground temperature in degrees C (default 25.0).
i@103 29 pressure : float
ulalume3@64 30 The ground pressure in hPa (default: 1020.0).
i@101 31 licel_timezone : str
i@101 32 String describing the timezone according to the tz database.
ulalume3@64 33
ulalume3@64 34 Returns
ulalume3@64 35 -------
ulalume3@64 36 CustomLidarMeasurement:
ulalume3@64 37 A custom sub-class of LicelLidarMeasurement
ulalume3@64 38 """
i@160 39 # TODO: Remove the custom netcdf parameter artifact: pass parameters as optional input argument,
i@160 40 # TODO: change setting format to YAML.
ulalume3@64 41 custom_netcdf_parameters = read_settings_file(custom_netcdf_parameter_path)
ulalume3@64 42
ulalume3@64 43 class CustomLidarMeasurement(LicelCalibrationMeasurement):
ulalume3@64 44 extra_netcdf_parameters = custom_netcdf_parameters
ulalume3@64 45
ulalume3@69 46 def __init__(self, plus45_files=None, minus45_files=None):
i@101 47 super(CustomLidarMeasurement, self).__init__(plus45_files, minus45_files, use_id_as_name,
i@101 48 licel_timezone=licel_timezone)
ulalume3@64 49
ulalume3@92 50 def set_PT(self):
ulalume3@64 51 ''' Sets the pressure and temperature at station level. This is used if molecular_calc parameter is
ulalume3@64 52 set to 0 (i.e. use US Standard atmosphere).
ulalume3@64 53
ulalume3@64 54 The results are stored in the info dictionary.
ulalume3@64 55 '''
ulalume3@64 56
ulalume3@64 57 self.info['Temperature'] = temperature
ulalume3@64 58 self.info['Pressure'] = pressure
ulalume3@64 59
ulalume3@64 60 return CustomLidarMeasurement
ulalume3@64 61
ulalume3@64 62
ulalume3@64 63 def read_settings_file(settings_path):
ulalume3@64 64 """ Read the settings file.
ulalume3@64 65
ulalume3@64 66 The file should contain python code."""
ulalume3@64 67 if not os.path.isfile(settings_path):
ulalume3@64 68 logging.error("The provided settings path does not correspond to a file.")
ulalume3@64 69 sys.exit(1)
ulalume3@64 70
ulalume3@64 71 dirname, basename = os.path.split(settings_path)
ulalume3@64 72 sys.path.append(dirname)
ulalume3@64 73
ulalume3@64 74 module_name, _ = os.path.splitext(basename)
ulalume3@64 75 settings = importlib.import_module(module_name)
ulalume3@64 76 return settings
ulalume3@64 77
ulalume3@64 78
ulalume3@64 79 def main():
ulalume3@64 80 # Define the command line argument
ulalume3@68 81 parser = argparse.ArgumentParser(description="A program to convert Licel binary files from depolarization calibration measurements to the SCC NetCDF format.")
ulalume3@64 82 parser.add_argument("parameter_file", help="The path to a parameter file linking licel and SCC channels.")
ulalume3@69 83 parser.add_argument("plus45_string", help="Search string for plus 45 degree files")
ulalume3@69 84 parser.add_argument("minus45_string", help="Search string for minus 45 degree files")
ulalume3@64 85 parser.add_argument("-i", '--id_as_name',
ulalume3@64 86 help="Use transient digitizer ids as channel names, instead of descriptive names",
ulalume3@64 87 action="store_true")
ulalume3@64 88 parser.add_argument("-m", "--measurement_id", help="The new measurement id", default=None)
ulalume3@64 89 parser.add_argument("-n", "--measurement_number",
ulalume3@64 90 help="The measurement number for the date from 00 to 99. Used if no id is provided",
ulalume3@64 91 default="00")
ulalume3@64 92 parser.add_argument("-t", "--temperature", type=float,
ulalume3@64 93 help="The temperature (in C) at lidar level, required if using US Standard atmosphere",
ulalume3@64 94 default="25")
ulalume3@64 95 parser.add_argument("-p", "--pressure", type=float,
ulalume3@64 96 help="The pressure (in hPa) at lidar level, required if using US Standard atmosphere",
ulalume3@64 97 default="1020")
i@101 98 parser.add_argument('--licel_timezone', help="String describing the timezone according to the tz database.",
i@101 99 default="UTC", dest="licel_timezone",
i@101 100 )
ulalume3@64 101 # Verbosity settings from http://stackoverflow.com/a/20663028
ulalume3@64 102 parser.add_argument('-d', '--debug', help="Print dubuging information.", action="store_const",
ulalume3@64 103 dest="loglevel", const=logging.DEBUG, default=logging.INFO,
ulalume3@64 104 )
ulalume3@64 105 parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const",
ulalume3@64 106 dest="loglevel", const=logging.WARNING
ulalume3@64 107 )
victor@106 108 parser.add_argument('-D', '--dark_measurements', help="Location of files containing dark measurements. Use relative path and filename wildcars, see 'files' parameter for example.",
victor@106 109 default="", dest="dark_files"
victor@106 110 )
ulalume3@67 111 parser.add_argument('--version', help="Show current version.", action='store_true')
ulalume3@64 112
i@163 113 # TODO: Add check that either measurement id or measurement number are provided
ulalume3@64 114 args = parser.parse_args()
ulalume3@64 115
ulalume3@64 116 # Get the logger with the appropriate level
ulalume3@64 117 logging.basicConfig(format='%(levelname)s: %(message)s', level=args.loglevel)
ulalume3@64 118 logger = logging.getLogger(__name__)
ulalume3@64 119
ulalume3@64 120 #coloredlogs.install(fmt='%(levelname)s: %(message)s', level=args.loglevel)
ulalume3@64 121
ulalume3@67 122 if args.version:
ulalume3@67 123 print("Version: %s" % __version__)
ulalume3@67 124 sys.exit(0)
ulalume3@67 125
ulalume3@64 126 # Get a list of files to convert
ulalume3@64 127 plus45_files = glob.glob(args.plus45_string)
ulalume3@64 128 minus45_files = glob.glob(args.minus45_string)
ulalume3@64 129
ulalume3@64 130 if len(plus45_files)==0 or len(minus45_files)==0:
ulalume3@64 131 logger.error("No files found when searching for %s and %s." % (plus45_files, minus45_files))
ulalume3@64 132 sys.exit(1)
ulalume3@64 133
ulalume3@64 134 # Read the files
ulalume3@64 135 logger.info("Reading {0} files from {1}".format(len(plus45_files), args.plus45_string))
ulalume3@64 136 logger.info("Reading {0} files from {1}".format(len(minus45_files), args.minus45_string))
ulalume3@64 137
ulalume3@64 138 CustomLidarMeasurement = create_custom_class(args.parameter_file, args.id_as_name, args.temperature,
i@101 139 args.pressure, args.licel_timezone)
ulalume3@64 140
ulalume3@64 141 measurement = CustomLidarMeasurement(plus45_files, minus45_files)
victor@106 142
victor@106 143 # Get a list of files containing dark measurements
victor@106 144 if args.dark_files != "":
victor@106 145 dark_files = glob.glob(args.dark_files)
victor@106 146
victor@106 147 if dark_files:
victor@106 148 logger.debug("Using %s as dark measurements files!" % ', '.join(dark_files))
victor@106 149 measurement.dark_measurement = CustomLidarMeasurement(dark_files, dark_files)
victor@106 150 else:
victor@106 151 logger.warning('No dark measurement files found when searching for %s. Will not use any dark measurements.' % args.dark_files)
ulalume3@64 152
ulalume3@64 153 try:
ulalume3@64 154 measurement = measurement.subset_by_scc_channels()
ulalume3@64 155 except ValueError as err:
ulalume3@64 156 logging.error(err)
ulalume3@64 157 sys.exit(1)
ulalume3@64 158
ulalume3@64 159 # Save the netcdf
ulalume3@64 160 logger.info("Saving netcdf")
ulalume3@64 161 measurement.set_measurement_id(args.measurement_id, args.measurement_number)
ulalume3@92 162 measurement.save_as_SCC_netcdf()
ulalume3@64 163 logger.info("Created file %s" % measurement.scc_filename)

mercurial