ulalume3@64: """ Command line tool to convert Licel binary files to SCC NetCDF format. ulalume3@64: """ ulalume3@64: import argparse ulalume3@64: import glob ulalume3@64: import importlib ulalume3@64: import logging ulalume3@64: import os ulalume3@64: import sys ulalume3@64: ulalume3@64: ulalume3@64: from ..licel_depol import LicelCalibrationMeasurement ulalume3@64: ulalume3@64: ulalume3@64: def create_custom_class(custom_netcdf_parameter_path, use_id_as_name=False, temperature=25., pressure=1020.): ulalume3@64: """ This funtion creates a custom LicelLidarMeasurement subclass, ulalume3@64: based on the input provided by the users. ulalume3@64: ulalume3@64: Parameters ulalume3@64: ---------- ulalume3@64: custom_netcdf_parameter_path: str ulalume3@64: The path to the custom channels parameters. ulalume3@64: use_id_as_name: bool ulalume3@64: Defines if channels names are descriptive or transient digitizer IDs. ulalume3@64: temperature: float ulalume3@64: The ground temperature in degrees C (default 25.0). ulalume3@64: pressure: float ulalume3@64: The ground pressure in hPa (default: 1020.0). ulalume3@64: ulalume3@64: Returns ulalume3@64: ------- ulalume3@64: CustomLidarMeasurement: ulalume3@64: A custom sub-class of LicelLidarMeasurement ulalume3@64: """ ulalume3@64: ulalume3@64: custom_netcdf_parameters = read_settings_file(custom_netcdf_parameter_path) ulalume3@64: ulalume3@64: class CustomLidarMeasurement(LicelCalibrationMeasurement): ulalume3@64: extra_netcdf_parameters = custom_netcdf_parameters ulalume3@64: ulalume3@64: def __init__(self, filelist=None): ulalume3@64: super(CustomLidarMeasurement, self).__init__(filelist, use_id_as_name) ulalume3@64: ulalume3@64: def get_PT(self): ulalume3@64: ''' Sets the pressure and temperature at station level. This is used if molecular_calc parameter is ulalume3@64: set to 0 (i.e. use US Standard atmosphere). ulalume3@64: ulalume3@64: The results are stored in the info dictionary. ulalume3@64: ''' ulalume3@64: ulalume3@64: self.info['Temperature'] = temperature ulalume3@64: self.info['Pressure'] = pressure ulalume3@64: ulalume3@64: return CustomLidarMeasurement ulalume3@64: ulalume3@64: ulalume3@64: def read_settings_file(settings_path): ulalume3@64: """ Read the settings file. ulalume3@64: ulalume3@64: The file should contain python code.""" ulalume3@64: if not os.path.isfile(settings_path): ulalume3@64: logging.error("The provided settings path does not correspond to a file.") ulalume3@64: sys.exit(1) ulalume3@64: ulalume3@64: dirname, basename = os.path.split(settings_path) ulalume3@64: sys.path.append(dirname) ulalume3@64: ulalume3@64: module_name, _ = os.path.splitext(basename) ulalume3@64: settings = importlib.import_module(module_name) ulalume3@64: return settings ulalume3@64: ulalume3@64: ulalume3@64: def main(): ulalume3@64: # Define the command line argument ulalume3@64: parser = argparse.ArgumentParser(description="A program to convert Licel binary files to the SCC NetCDF format.") ulalume3@64: parser.add_argument("parameter_file", help="The path to a parameter file linking licel and SCC channels.") ulalume3@64: parser.add_argument("plus45_string", nargs='?', help="Search string for plus 45 degree files (default '*.*')", default="*.*") ulalume3@64: parser.add_argument("minus45_string", nargs='?', help="Search string for minus 45 degree files (default '*.*')", default="*.*") ulalume3@64: parser.add_argument("-i", '--id_as_name', ulalume3@64: help="Use transient digitizer ids as channel names, instead of descriptive names", ulalume3@64: action="store_true") ulalume3@64: parser.add_argument("-m", "--measurement_id", help="The new measurement id", default=None) ulalume3@64: parser.add_argument("-n", "--measurement_number", ulalume3@64: help="The measurement number for the date from 00 to 99. Used if no id is provided", ulalume3@64: default="00") ulalume3@64: parser.add_argument("-t", "--temperature", type=float, ulalume3@64: help="The temperature (in C) at lidar level, required if using US Standard atmosphere", ulalume3@64: default="25") ulalume3@64: parser.add_argument("-p", "--pressure", type=float, ulalume3@64: help="The pressure (in hPa) at lidar level, required if using US Standard atmosphere", ulalume3@64: default="1020") ulalume3@64: # Verbosity settings from http://stackoverflow.com/a/20663028 ulalume3@64: parser.add_argument('-d', '--debug', help="Print dubuging information.", action="store_const", ulalume3@64: dest="loglevel", const=logging.DEBUG, default=logging.INFO, ulalume3@64: ) ulalume3@64: parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const", ulalume3@64: dest="loglevel", const=logging.WARNING ulalume3@64: ) ulalume3@64: ulalume3@64: args = parser.parse_args() ulalume3@64: ulalume3@64: # Get the logger with the appropriate level ulalume3@64: logging.basicConfig(format='%(levelname)s: %(message)s', level=args.loglevel) ulalume3@64: logger = logging.getLogger(__name__) ulalume3@64: ulalume3@64: #coloredlogs.install(fmt='%(levelname)s: %(message)s', level=args.loglevel) ulalume3@64: ulalume3@64: # Get a list of files to convert ulalume3@64: plus45_files = glob.glob(args.plus45_string) ulalume3@64: minus45_files = glob.glob(args.minus45_string) ulalume3@64: ulalume3@64: if len(plus45_files)==0 or len(minus45_files)==0: ulalume3@64: logger.error("No files found when searching for %s and %s." % (plus45_files, minus45_files)) ulalume3@64: sys.exit(1) ulalume3@64: ulalume3@64: # Read the files ulalume3@64: logger.info("Reading {0} files from {1}".format(len(plus45_files), args.plus45_string)) ulalume3@64: logger.info("Reading {0} files from {1}".format(len(minus45_files), args.minus45_string)) ulalume3@64: ulalume3@64: CustomLidarMeasurement = create_custom_class(args.parameter_file, args.id_as_name, args.temperature, ulalume3@64: args.pressure) ulalume3@64: ulalume3@64: measurement = CustomLidarMeasurement(plus45_files, minus45_files) ulalume3@64: ulalume3@64: try: ulalume3@64: measurement = measurement.subset_by_scc_channels() ulalume3@64: except ValueError as err: ulalume3@64: logging.error(err) ulalume3@64: sys.exit(1) ulalume3@64: ulalume3@64: # Save the netcdf ulalume3@64: logger.info("Saving netcdf") ulalume3@64: measurement.set_measurement_id(args.measurement_id, args.measurement_number) ulalume3@64: measurement.save_as_netcdf() ulalume3@64: logger.info("Created file %s" % measurement.scc_filename)