72 module_name, _ = os.path.splitext(basename) |
75 module_name, _ = os.path.splitext(basename) |
73 settings = importlib.import_module(module_name) |
76 settings = importlib.import_module(module_name) |
74 return settings |
77 return settings |
75 |
78 |
76 |
79 |
77 def get_cloud_free_files(CustomLidarMeasurement, files, args): |
80 def read_cloudmask_settings_file(settings_file_path): |
|
81 """ Read the configuration file. |
|
82 |
|
83 The file should be in YAML syntax.""" |
|
84 |
|
85 if not os.path.isfile(settings_file_path): |
|
86 logging.error("Wrong path for cloudmask settings file (%s)" % settings_file_path) |
|
87 sys.exit(1) |
|
88 |
|
89 with open(settings_file_path) as yaml_file: |
|
90 try: |
|
91 settings = yaml.load(yaml_file) |
|
92 logging.debug("Read cloudmask settings file(%s)" % settings_file_path) |
|
93 except: |
|
94 logging.error("Could not parse YAML file (%s)" % settings_file_path) |
|
95 sys.exit(1) |
|
96 |
|
97 return settings |
|
98 |
|
99 |
|
100 def get_cloud_free_files(CustomLidarMeasurement, files, settings): |
78 logger.warning("Starting cloud mask procedure. This is an experimental feature.") |
101 logger.warning("Starting cloud mask procedure. This is an experimental feature.") |
79 |
102 |
80 try: |
103 try: |
81 from cloudmask import cloudmask # Import here until we setup a proper installation procedure |
104 from cloudmask import cloudmask # Import here until we setup a proper installation procedure |
82 except ImportError: |
105 except ImportError: |
83 logger.error("Cloud mask module could not be loaded. Please install manually.") |
106 logger.error("Cloud mask module could not be loaded. Please install manually.") |
84 sys.exit(1) |
107 sys.exit(1) |
85 |
108 |
86 measurement = CustomLidarMeasurement(files) |
109 measurement = CustomLidarMeasurement(files) |
87 channel = measurement.channels[args.cloudmask_channel] |
110 channel = measurement.channels[settings['channel']] |
88 cloud_mask = cloudmask.CloudMaskRaw(channel) |
111 cloud_mask = cloudmask.CloudMaskRaw(channel) |
89 idxs = cloud_mask.cloud_free_periods(args.cloudfree_period, args.cloud_search_height) |
112 |
|
113 idxs = cloud_mask.cloud_free_periods(settings['cloudfree_period_min'], |
|
114 settings['file_duration_max'], |
|
115 settings['max_cloud_height']) |
|
116 |
|
117 logger.debug('Cloud free indices: {0}'.format(idxs)) |
90 |
118 |
91 if len(idxs) == 0: # If no cloud-free period found |
119 if len(idxs) == 0: # If no cloud-free period found |
92 logger.info('No cloud free period found. Nothing converted.') |
120 logger.info('No cloud free period found. Nothing converted.') |
93 sys.exit(1) |
121 sys.exit(1) |
94 |
122 |
95 logger.info("{0} cloud free period(s) found.".format(len(idxs))) |
123 logger.info("{0} cloud free period(s) found.".format(len(idxs))) |
|
124 |
|
125 if settings['plot']: |
|
126 output_filename = "cloudfree_{0}_{1}_{2}.png".format(channel.wavelength, |
|
127 channel.start_time.strftime('%Y%m%d_%H%M%S'), |
|
128 channel.stop_time.strftime('%Y%m%d_%H%M%S')) |
|
129 output_path = os.path.join(settings['plot_directory'], output_filename) |
|
130 fig, _ = cloud_mask.plot_cloudfree(idxs) |
|
131 |
|
132 plt.savefig(output_path) |
|
133 |
96 file_list = [] |
134 file_list = [] |
97 for idx_min, idx_max in idxs: |
135 for idx_min, idx_max in idxs: |
98 current_files = measurement.files[idx_min:idx_max] |
136 current_files = measurement.files[idx_min:idx_max] |
99 file_list.append(current_files) |
137 file_list.append(current_files) |
100 |
138 |
166 default="", dest="dark_files" |
204 default="", dest="dark_files" |
167 ) |
205 ) |
168 parser.add_argument('--licel_timezone', help="String describing the timezone according to the tz database.", |
206 parser.add_argument('--licel_timezone', help="String describing the timezone according to the tz database.", |
169 default="UTC", dest="licel_timezone", |
207 default="UTC", dest="licel_timezone", |
170 ) |
208 ) |
171 parser.add_argument('--cloudmask', help="Experimental feature to automatically cloud mask measurements", |
209 parser.add_argument('--cloudmask_settings', help="Experimental feature to automatically cloud mask measurements", |
172 default=False, action='store_true', |
210 default="") |
173 ) |
211 |
174 parser.add_argument('--cloudmask_channel', help="Name of channel to apply the cloud mask.") |
|
175 parser.add_argument('--cloudfree_period', type=float, help="Duration (in min) of cloud-free periods", |
|
176 default="30", |
|
177 ) |
|
178 parser.add_argument('--cloud_search_height', type=float, help="Maximum altitude (in m) to check for clouds.", |
|
179 default="12000", |
|
180 ) |
|
181 # Verbosity settings from http://stackoverflow.com/a/20663028 |
212 # Verbosity settings from http://stackoverflow.com/a/20663028 |
182 parser.add_argument('-d', '--debug', help="Print dubuging information.", action="store_const", |
213 parser.add_argument('-d', '--debug', help="Print dubuging information.", action="store_const", |
183 dest="loglevel", const=logging.DEBUG, default=logging.INFO, |
214 dest="loglevel", const=logging.DEBUG, default=logging.INFO, |
184 ) |
215 ) |
185 parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const", |
216 parser.add_argument('-s', '--silent', help="Show only warning and error messages.", action="store_const", |
211 # If everything OK, proceed |
242 # If everything OK, proceed |
212 logger.info("Found {0} files matching {1}".format(len(files), os.path.abspath(args.files))) |
243 logger.info("Found {0} files matching {1}".format(len(files), os.path.abspath(args.files))) |
213 CustomLidarMeasurement = create_custom_class(args.parameter_file, args.id_as_name, args.temperature, |
244 CustomLidarMeasurement = create_custom_class(args.parameter_file, args.id_as_name, args.temperature, |
214 args.pressure, args.licel_timezone) |
245 args.pressure, args.licel_timezone) |
215 |
246 |
216 if args.cloudmask: |
247 if args.cloudmask_settings: |
217 file_lists = get_cloud_free_files(CustomLidarMeasurement, files, args) |
248 cloudmask_settings = read_cloudmask_settings_file(args.cloudmask_settings) |
|
249 |
|
250 file_lists = get_cloud_free_files(CustomLidarMeasurement, files, cloudmask_settings) |
218 |
251 |
219 for n, files in enumerate(file_lists): |
252 for n, files in enumerate(file_lists): |
220 measurement_id, measurement_no = get_corrected_measurement_id(args, n) |
253 measurement_id, measurement_no = get_corrected_measurement_id(args, n) |
221 convert_to_scc(CustomLidarMeasurement, files, args.dark_files, measurement_id, measurement_no) |
254 convert_to_scc(CustomLidarMeasurement, files, args.dark_files, measurement_id, measurement_no) |
222 else: |
255 else: |