def parse_metadata(metafile, pan=False): import os, sys, fnmatch, dateutil.parser from xml.dom import minidom from acolite import distance_se from numpy import pi, tan, arctan2, mod dtor = pi / 180. if not os.path.isfile(metafile): print('Metadata file {} not found.'.format(metafile)) sys.exit() try: xmldoc = minidom.parse(metafile) except: print('Error opening metadata file.') sys.exit() metadata = {} metadata['SATELLITE'] = 'Pléiades' ## get image information metadata_tags = [ 'NROWS', 'NCOLS', 'NBANDS', 'RESAMPLING_SPACING', 'MISSION', 'MISSION_INDEX', 'INSTRUMENT', 'INSTRUMENT_INDEX', 'IMAGING_DATE', 'IMAGING_TIME', 'BAND_MODE', 'RED_CHANNEL', 'GREEN_CHANNEL', 'BLUE_CHANNEL', 'ALPHA_CHANNEL', 'EXTENT_TYPE' ] for tag in metadata_tags: node = xmldoc.getElementsByTagName(tag) if len(node) > 0: metadata[tag] = node[0].firstChild.nodeValue metadata['SENSOR'] = '{}{}'.format(metadata['MISSION'], metadata['MISSION_INDEX']) if 'SPOT' in metadata['SENSOR']: metadata['SATELLITE'] = 'SPOT' ## get acquisition time #time_s = xmldoc.getElementsByTagName('Time_Range')[0].getElementsByTagName("START")[0].firstChild.nodeValue #time_e = xmldoc.getElementsByTagName('Time_Range')[0].getElementsByTagName("END")[0].firstChild.nodeValue #metadata["TIME_START"] = dateutil.parser.parse(time_s) #metadata["TIME_END"] = dateutil.parser.parse(time_e) #metadata["DOY"] = metadata["TIME_END"].strftime('%j') metadata["TIME"] = dateutil.parser.parse(''.join( [metadata["IMAGING_DATE"], 'T', metadata["IMAGING_TIME"]])) metadata["DOY"] = metadata["TIME"].strftime('%j') metadata["SE_DISTANCE"] = distance_se(metadata['DOY']) ### node = xmldoc.getElementsByTagName("RADIOMETRIC_PROCESSING") metadata['RADIOMETRIC_PROCESSING'] = node[0].firstChild.nodeValue if len( node) > 0 else 'RADIANCE' ## get 'special' values for t in xmldoc.getElementsByTagName('Special_Value'): name = (t.getElementsByTagName("SPECIAL_VALUE_TEXT") [0].firstChild.nodeValue) value = (t.getElementsByTagName("SPECIAL_VALUE_COUNT") [0].firstChild.nodeValue) metadata[name] = value ## get view and sun geometry geometric_tags = [ 'LOCATION_TYPE', 'TIME', 'SUN_AZIMUTH', 'SUN_ELEVATION', 'AZIMUTH_ANGLE', 'VIEWING_ANGLE_ACROSS_TRACK', 'VIEWING_ANGLE_ALONG_TRACK', 'VIEWING_ANGLE', 'INCIDENCE_ANGLE_ALONG_TRACK', 'INCIDENCE_ANGLE_ACROSS_TRACK', 'INCIDENCE_ANGLE' ] geometric_values = [] for t in xmldoc.getElementsByTagName('Located_Geometric_Values'): geom = {} for tag in geometric_tags: node = t.getElementsByTagName(tag) if len(node) > 0: if tag in ['LOCATION_TYPE', 'TIME']: geom[tag] = node[0].firstChild.nodeValue else: geom[tag] = float(node[0].firstChild.nodeValue) ## compute viewing azimuth orientation_angle = geom['AZIMUTH_ANGLE'] #incidence_across = geom['INCIDENCE_ANGLE_ACROSS_TRACK'] #incidence_along = geom['INCIDENCE_ANGLE_ALONG_TRACK'] #geom['VIEWING_AZIMUTH'] = mod(orientation_angle - arctan2(tan(incidence_across*dtor), tan(incidence_along*dtor))/dtor,360) #ang_across = geom['VIEWING_ANGLE_ACROSS_TRACK'] #ang_along = geom['VIEWING_ANGLE_ALONG_TRACK'] ang_across = geom['INCIDENCE_ANGLE_ACROSS_TRACK'] ang_along = geom['INCIDENCE_ANGLE_ALONG_TRACK'] geom['VIEWING_AZIMUTH'] = mod( orientation_angle - arctan2(tan(ang_across * dtor), tan(ang_along * dtor)) / dtor, 360) #geom['VIEWING_AZIMUTH'] = geom['AZIMUTH_ANGLE'] geometric_values.append(geom) metadata['GEOMETRY'] = geometric_values ## get band info such as F0 and calibration band_info = {} bands = ['B0', 'B1', 'B2', 'B3'] default_F0 = [1915., 1830., 1594., 1060.] if pan is True: bands = ['P'] default_F0 = [1548.] for band in bands: band_data = {} for t in xmldoc.getElementsByTagName('BAND_ID'): if (t.firstChild.nodeValue) == band: parent = t.parentNode.nodeName if parent == 'Band_Solar_Irradiance': unit = t.parentNode.getElementsByTagName( 'MEASURE_UNIT')[0].firstChild.nodeValue F0 = float( t.parentNode.getElementsByTagName('VALUE') [0].firstChild.nodeValue) if F0 == 999.: idx = [i for i, j in enumerate(bands) if j == band] F0 = default_F0[idx[0]] band_data['F0'] = F0 if parent == 'Band_Radiance': unit = t.parentNode.getElementsByTagName( 'MEASURE_UNIT')[0].firstChild.nodeValue band_data['radiance_gain'] = float( t.parentNode.getElementsByTagName('GAIN') [0].firstChild.nodeValue) band_data['radiance_bias'] = float( t.parentNode.getElementsByTagName('BIAS') [0].firstChild.nodeValue) if parent == 'Band_Reflectance': band_data['reflectance_gain'] = float( t.parentNode.getElementsByTagName('GAIN') [0].firstChild.nodeValue) band_data['reflectance_bias'] = float( t.parentNode.getElementsByTagName('BIAS') [0].firstChild.nodeValue) if parent == 'Band_Digital_Number': band_data['radiance_to_dn_gain'] = float( t.parentNode.getElementsByTagName('GAIN') [0].firstChild.nodeValue) band_data['radiance_to_dn_bias'] = float( t.parentNode.getElementsByTagName('BIAS') [0].firstChild.nodeValue) if parent == 'Band_Spectral_Range': unit = t.parentNode.getElementsByTagName( 'MEASURE_UNIT')[0].firstChild.nodeValue wave_start = float( t.parentNode.getElementsByTagName('MIN') [0].firstChild.nodeValue) wave_end = float( t.parentNode.getElementsByTagName('MAX') [0].firstChild.nodeValue) if wave_start > 100.: wave_start /= 1000. if wave_end > 100.: wave_end /= 1000. band_data['wave_start'] = wave_start band_data['wave_end'] = wave_end band_data['wave'] = (band_data['wave_end'] + band_data['wave_start']) / 2. #if band_data['wave_start'] > 100.: band_data['wave_start']=band_data['wave_start']/1000. #if band_data['wave_end'] > 100.: band_data['wave_start']=band_data['wave_start']/1000. #if band_data['wave'] > 100.: band_data['wave_start']=band_data['wave_start']/1000. band_data['wave_name'] = str( round(int(band_data['wave'] * 1000.), 2)) if pan is False: if band == metadata['RED_CHANNEL']: band_data['band_index'] = 0 if band == metadata['GREEN_CHANNEL']: band_data['band_index'] = 1 if band == metadata['BLUE_CHANNEL']: band_data['band_index'] = 2 if band == metadata['ALPHA_CHANNEL']: band_data['band_index'] = 3 band_info[band] = band_data metadata['BAND_INFO'] = band_info ## read vertices of spatial extent vertex_tags = ['LON', 'LAT', 'X', 'Y', 'COL', 'ROW'] vertex_values = [] for t in xmldoc.getElementsByTagName('Vertex'): vertex = {} for tag in vertex_tags: node = t.getElementsByTagName(tag) if len(node) > 0: vertex[tag] = float(node[0].firstChild.nodeValue) vertex_values.append(vertex) vertices = {} for t in xmldoc.getElementsByTagName('Center'): vertex = {} for tag in vertex_tags: node = t.getElementsByTagName(tag) if len(node) > 0: vertex[tag] = float(node[0].firstChild.nodeValue) vertices['C'] = vertex ncols = float(metadata['NCOLS']) nrows = float(metadata['NROWS']) for i, v in enumerate(vertex_values): col = float(v['COL']) row = float(v['ROW']) if (col == 1) & (row == 1): vertices['UL'] = v continue if (col == ncols) & (row == 1): vertices['UR'] = v continue if (col == ncols) & (row == nrows): vertices['LR'] = v continue if (col == 1) & (row == nrows): vertices['LL'] = v continue vertices['V{}'.format(i)] = v metadata['VERTICES'] = vertices ## get tile information try: metadata['ntiles'] = int( xmldoc.getElementsByTagName("NTILES")[0].firstChild.nodeValue) metadata['ntiles_R'] = int( xmldoc.getElementsByTagName("NTILES_COUNT") [0]._attrs['ntiles_R'].nodeValue) metadata['ntiles_C'] = int( xmldoc.getElementsByTagName("NTILES_COUNT") [0]._attrs['ntiles_C'].nodeValue) metadata['tiles_nrows'] = int( xmldoc.getElementsByTagName("NTILES_SIZE") [0]._attrs['nrows'].nodeValue) metadata['tiles_ncols'] = int( xmldoc.getElementsByTagName("NTILES_SIZE") [0]._attrs['ncols'].nodeValue) except: metadata['ntiles'] = 1 metadata['ntiles_R'] = 1 metadata['ntiles_C'] = 1 metadata['tiles_nrows'] = int(metadata['NROWS']) metadata['tiles_ncols'] = int(metadata['NROWS']) ## set some defaults metadata['THS'] = 90. - metadata['GEOMETRY'][1]['SUN_ELEVATION'] metadata['THV'] = metadata['GEOMETRY'][1]['VIEWING_ANGLE'] azi = abs(metadata['GEOMETRY'][1]['SUN_AZIMUTH'] - metadata['GEOMETRY'][1]['VIEWING_AZIMUTH']) if azi > 180: azi -= 180 metadata['AZI'] = azi metadata['SENSOR'] = metadata['INSTRUMENT'] + metadata['MISSION_INDEX'] bands = sorted({band for band in metadata['BAND_INFO']}) wavelengths = sorted({ metadata['BAND_INFO'][band]['wave'] for band in metadata['BAND_INFO'] }) band_wavelengths = sorted({ metadata['BAND_INFO'][band]['wave_name'] for band in metadata['BAND_INFO'] }) #band_indices = [metadata['BAND_INFO'][band]['band_index'] for band in bands] band_indices = [] for bi, band in enumerate(bands): if 'band_index' in metadata['BAND_INFO'][band].keys(): band_indices.append(metadata['BAND_INFO'][band]['band_index']) else: band_indices.append(bi) metadata['BANDS'] = bands metadata['WAVELENGTHS'] = wavelengths metadata['BAND_WAVELENGTHS'] = band_wavelengths metadata['BAND_INDICES'] = band_indices band_names = [] for band in bands: if band == 'B0': band_names.append('Blue') if band == 'B1': band_names.append('Green') if band == 'B2': band_names.append('Red') if band == 'B3': band_names.append('NIR') metadata['BAND_NAMES'] = band_names metadata['BANDS_ALL'] = ['Blue', 'Green', 'Red', 'NIR'] metadata['BANDS_REDNIR'] = ['Red', 'NIR'] metadata['BANDS_VIS'] = ['Blue', 'Green', 'Red'] metadata['BANDS_NIR'] = ['NIR'] metadata['BANDS_BESTFIT'] = ['Red', 'NIR'] return metadata
def fixed_model(metadata, tau550, rsr_file=None, lutdir=None, lut='PONDER-LUT-201607-MOD2-1013mb', pressure=None): import acolite as pp import os ## get scene geometry and default bands from metadata try: if 'SE_DISTANCE' in metadata.keys(): se_distance = metadata['SE_DISTANCE'] else: se_distance = pp.distance_se(metadata['DOY']) ths = metadata['THS'] thv = metadata['THV'] azi = metadata['AZI'] if 'SATELLITE_SENSOR' in metadata.keys(): sensor = metadata['SATELLITE_SENSOR'] else: sensor = metadata['SENSOR'] #rednir_bands = metadata['BANDS_REDNIR'] #vis_bands = metadata['BANDS_VIS'] #nir_bands = metadata['BANDS_NIR'] #bestfit_bands_defaults = metadata['BANDS_BESTFIT'] bands_sorted = metadata['BANDS_ALL'] except: print( 'Could not get appropriate metadata for model selection for satellite {}' .format(metadata['SATELLITE'])) print(metadata.keys()) return (1) # ## get scene geometry # if metadata['SATELLITE']=='Pléiades': # se_distance = pp.distance_se(metadata['DOY']) # ths = 90. - metadata['GEOMETRY'][1]['SUN_ELEVATION'] # thv = metadata['GEOMETRY'][1]['VIEWING_ANGLE'] # azi = abs(metadata['GEOMETRY'][1]['SUN_AZIMUTH'] - metadata['GEOMETRY'][1]['AZIMUTH_ANGLE']) # if azi > 180: azi -= 180 # sensor = metadata['INSTRUMENT']+metadata['MISSION_INDEX'] # rednir_bands = ['Red','NIR'] # vis_bands = ['Blue','Green','Red'] # if metadata['SATELLITE']=='WorldView2': # se_distance = pp.distance_se(metadata['DOY']) # ths = metadata['THS'] # thv = metadata['THV'] # azi = metadata['AZI'] # sensor = 'WorldView2' # rednir_bands = ['RED','NIR1','NIR2'] # vis_bands = ['COASTAL','BLUE','GREEN','YELLOW','RED'] ## set LUT dir and rsr_file #pypath='/storage/Python/' ## to improve! #pp_path = os.path.dirname(pp.__file__) #if lutdir is None: # lutdir=pp_path+'/data/LUT/' #if rsr_file is None: # rsr_file = pp_path+'/data/RSR/'+sensor+'.txt' ## set LUT dir and rsr_file from acolite import config pp_path = config['pp_data_dir'] if lutdir is None: lutdir = pp_path + '/LUT/' if rsr_file is None: rsr_file = pp_path + '/RSR/' + sensor + '.txt' rsr, rsr_bands = pp.rsr_read(file=rsr_file) ## get sensor LUT #lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut(sensor, rsr_file, lutdir=lutdir, lutid=lut, override=0) #(ratm, rorayl, dtotr, utotr, dtott, utott, astot) = pp.aerlut.lut_get_ac_parameters_fixed_tau_sensor(lut_sensor,meta_sensor,azi,thv,ths,tau550) ## get sensor LUT lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut(sensor, rsr_file, lutdir=lutdir, lutid=lut, override=0) ## read luts at other pressures if needed if pressure is not None: lut_data_dict = {} lut_data_dict[lut] = {'lut': lut_sensor, 'meta': meta_sensor} lut_split = lut.split('-') lut0 = '-'.join(lut_split[0:-1] + ['0500mb']) lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut(sensor, rsr_file, lutdir=lutdir, lutid=lut0, override=0) lut_data_dict[lut0] = {'lut': lut_sensor, 'meta': meta_sensor} lut1 = '-'.join(lut_split[0:-1] + ['1100mb']) lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut(sensor, rsr_file, lutdir=lutdir, lutid=lut1, override=0) lut_data_dict[lut1] = {'lut': lut_sensor, 'meta': meta_sensor} lut_sensor, meta_sensor = pp.aerlut.aerlut_pressure( lut, lutdir, pressure, sensor, rsr_file, lut_data_dict=lut_data_dict) (ratm, rorayl, dtotr, utotr, dtott, utott, astot) = pp.aerlut.lut_get_ac_parameters_fixed_tau_sensor( lut_sensor, meta_sensor, azi, thv, ths, tau550) return (ratm, rorayl, dtotr, utotr, dtott, utott, astot, tau550), lut_sensor, meta_sensor
def select_model(metadata, rdark, rsr_file=None, lutdir=None, bestfit='bands', bestfit_bands=None, force_band=None, pressure=None, model_selection='min_tau', rdark_list_selection='intercept', lowess_frac=0.5, lut_data_dict=None, luts=[ 'PONDER-LUT-201704-MOD1-1013mb', 'PONDER-LUT-201704-MOD2-1013mb', 'PONDER-LUT-201704-MOD3-1013mb' ]): import acolite as pp import os from numpy import float64, ndarray, arange, nanmin, where, nan, isnan, min from numpy.ma import MaskedArray, is_masked from statsmodels.nonparametric.smoothers_lowess import lowess ## get scene geometry and default bands from metadata try: if 'SE_DISTANCE' in metadata.keys(): se_distance = metadata['SE_DISTANCE'] else: se_distance = pp.distance_se(metadata['DOY']) ths = metadata['THS'] thv = metadata['THV'] azi = metadata['AZI'] if 'LUT_SENSOR' in metadata.keys(): sensor = metadata['LUT_SENSOR'] elif 'SATELLITE_SENSOR' in metadata.keys(): sensor = metadata['SATELLITE_SENSOR'] else: sensor = metadata['SENSOR'] bestfit_bands_defaults = metadata['BANDS_BESTFIT'] bands_sorted = metadata['BANDS_ALL'] except: print( 'Could not get appropriate metadata for model selection for satellite {}' .format(metadata['SATELLITE'])) print(metadata.keys()) return (1) bestfit_bands_all = rdark.keys() if bestfit_bands is None: bestfit_bands = bestfit_bands_defaults if bestfit_bands == 'default': bestfit_bands = bestfit_bands_defaults if bestfit_bands == 'all': bestfit_bands = bestfit_bands_all ## set LUT dir and rsr_file pp_path = pp.config['pp_data_dir'] if lutdir is None: lutdir = pp_path + '/LUT/' if rsr_file is None: rsr_file = pp_path + '/RSR/' + sensor + '.txt' rsr, rsr_bands = pp.shared.rsr_read(file=rsr_file) ## make lut data dictionary that can be reused in next runs if lut_data_dict is None: lut_data_dict = {} for li, lut in enumerate(luts): ## get sensor LUT lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut(sensor, rsr_file, lutdir=lutdir, lutid=lut, override=0) lut_data_dict[lut] = {'lut': lut_sensor, 'meta': meta_sensor} ## read luts at other pressures if needed if pressure is not None: lut_split = lut.split('-') lut0 = '-'.join(lut_split[0:-1] + ['0500mb']) lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut( sensor, rsr_file, lutdir=lutdir, lutid=lut0, override=0) lut_data_dict[lut0] = {'lut': lut_sensor, 'meta': meta_sensor} lut1 = '-'.join(lut_split[0:-1] + ['1100mb']) lut_sensor, meta_sensor = pp.aerlut.get_sensor_lut( sensor, rsr_file, lutdir=lutdir, lutid=lut1, override=0) lut_data_dict[lut1] = {'lut': lut_sensor, 'meta': meta_sensor} ## empty dicts rdark_smooth = {} rdark_selected = {} ## default is not to use the 'list' type model/rdark selection ## will only be used if the rdark is a list and the rdark_list_selection=="list" rdark_list = False ## find out what kind of rdark is given and which selection to use for band in rdark.keys(): ## given rdark is a single spectrum if (type(rdark[band]) == float64): rdark_selected[band] = rdark[band] ## given rdark is a list of spectra elif (type(rdark[band]) == ndarray) or (type(rdark[band]) == MaskedArray): #pixel_range = range(0, len(rdark[band])) pixel_range = [float(i) for i in range(0, len(rdark[band]))] #print(pixel_range) rdark_list = True ## select rdark by lowess smoothing the given spectra if rdark_list_selection == 'smooth': rdark_smooth[band] = lowess(rdark[band], pixel_range, frac=lowess_frac)[:, 1] rdark_selected[band] = rdark_smooth[band][0] rdark_list = False ## select rdark by OLS intercept elif rdark_list_selection == 'intercept': for band in rdark.keys(): reg = pp.shared.regression.lsqfity( pixel_range, rdark[band]) # m, b, r, sm, sb rdark_selected[band] = reg[1] rdark_list = False ## select rdark from all given pixels according to min rmsd elif rdark_list_selection == 'list': rdark_selected[band] = rdark[band] rdark_list = True ## select rdark from all given pixels according to min rmsd, but first smooth the given rdark elif rdark_list_selection == 'list_smooth': rdark_selected[band] = lowess(rdark[band], pixel_range, frac=lowess_frac)[:, 1] rdark_list = True ## fallback selection is darkest pixel in each band else: rdark_list_selection = 'darkest' rdark_selected[band] = nanmin(rdark[band]) ## given dark is something else else: print('rdark type not recognised') rdark_selected = (rdark) if rdark_list: from numpy import min, max rdark_len = [len(rdark[b]) for b in rdark] max_len = max(rdark_len) min_len = min(rdark_len) rdark = {b: rdark[b][0:min_len] for b in rdark} ## find best fitting model sel_rmsd = 1. sel_tau = 5. taufits = [] daot_minimum = 5 ## run through luts for li, lut in enumerate(luts): ## get current sensor LUT if pressure is not None: ## interpolate LUTs to given pressure lut_sensor, meta_sensor = pp.aerlut.aerlut_pressure( lut, lutdir, pressure, sensor, rsr_file, lut_data_dict=lut_data_dict) else: ## just the default LUTs lut_sensor, meta_sensor = (lut_data_dict[lut]["lut"], lut_data_dict[lut]["meta"]) ## get tau for selected dark spectrum tau_550, tau_rmsd, tau_band = pp.aerlut.lut_get_taufit_sensor( lut_sensor, meta_sensor, azi, thv, ths, rdark_selected, bestfit_bands=bestfit_bands, force_band=force_band) ## if rdark list method do not select tau and model here, just append to 'taufits' list for later processing if (rdark_list): taufits.append((tau_550, tau_rmsd, tau_band)) ## if single spectra selected before, select tau and model here else: ## get tau and ac parameters for this model tmp = pp.aerlut.lut_get_ac_parameters_sensor(lut_sensor, meta_sensor, azi, thv, ths, rdark_selected, force_band=force_band) ## band index for this model (i.e. band giving lowest tau) idx = tmp[8] ## selected tau for this model tau550_cur = tmp[7][idx] ## probably obsolete if bestfit == 'bands': rmsd_y = [rdark_selected[band] for band in bestfit_bands] rmsd_x = [tmp[0][band] for band in bestfit_bands] rmsd = pp.rmsd(rmsd_x, rmsd_y) else: rmsd = tmp[9][idx] ## find best spectral fit if model_selection == 'min_rmsd': if is_masked(rmsd): rmsd = 1.0 if (rmsd <= sel_rmsd) | (li == 0): sel_rmsd = rmsd sel_idx = idx sel_ac_par = tmp sel_model_lut, sel_model_lut_meta = (lut_sensor, meta_sensor) pixel_idx = -1 ## find lowest tau fit if model_selection == 'min_tau': if (tau550_cur <= sel_tau) | (li == 0): sel_tau = tau550_cur sel_rmsd = rmsd sel_idx = idx sel_ac_par = tmp sel_model_lut, sel_model_lut_meta = (lut_sensor, meta_sensor) pixel_idx = -1 ## find lowest tau and second band with most similar tau if model_selection == 'min_dtau': allt = [tmp[7][b] for i, b in enumerate(tmp[7].keys())] min_tau = min([t for t in allt if t > 0.001]) allt_diff_sorted = [t - min_tau for t in allt if t > min_tau] allt_diff_sorted.sort() if allt_diff_sorted[0] < daot_minimum: daot_minimum = allt_diff_sorted[0] daot_second_band = [b for i,b in enumerate(tmp[7].keys()) \ if allt[i] == allt_diff_sorted[0] + min_tau][0] sel_tau = tau550_cur sel_rmsd = rmsd sel_idx = (idx, daot_second_band) sel_ac_par = tmp sel_model_lut, sel_model_lut_meta = (lut_sensor, meta_sensor) pixel_idx = -1 ## find lowest tau and minimum rmsd with any other band if model_selection == 'min_drmsd': rmsdi = {} rmsdi_band = '' rmsdi_min = 5 for i, b in enumerate(tmp[7].keys()): if b == idx: continue rmsd_yi = [rdark_selected[b], rdark_selected[idx]] rmsd_xi = [tmp[0][b], tmp[0][idx]] rmsdi[b] = pp.rmsd(rmsd_xi, rmsd_yi) if is_masked(rmsdi[b]): rmsdi[b] = 5 if (rmsdi[b] < rmsdi_min) & (b != idx): rmsdi_band = b rmsdi_min = rmsdi[b] # this happens if no band fits better (e.g. for rhopath==rhorayleigh) if rmsdi_band == '': rmsdi_band = b sel_rmsd = -1 sel_idx = (idx, idx) sel_ac_par = tmp sel_model_lut, sel_model_lut_meta = (lut_sensor, meta_sensor) pixel_idx = -1 elif (rmsdi[rmsdi_band] <= sel_rmsd) | (li == 0): sel_rmsd = rmsdi[rmsdi_band] sel_idx = (idx, rmsdi_band) sel_ac_par = tmp sel_model_lut, sel_model_lut_meta = (lut_sensor, meta_sensor) pixel_idx = -1 ## get rdark/tau+model according to min rmsd/tau in the given pixel lists ## when rdark_list_selection did not select a single spectrum if (rdark_list): ## choose best lut for each pixel tau_550_sel = [] tau_rmsd_sel = [] tau_band_sel = [] tau_model_sel = [] ## get for each pixel the minimum rmsd [1] according to the models ## default select on min tau list_min_idx = 0 if model_selection == "min_tau": list_min_idx = 0 elif model_selection == "min_rmsd": list_min_idx = 1 for i in pixel_range: val_c = [ taufits[j][list_min_idx][i] for j in range(0, len(taufits)) ] ## selected tau/rmsd per model for this pixel idx = [i for i, t in enumerate(val_c) if (t == nanmin(val_c))] if len(idx) == 0: tau_550_sel.append(nan) tau_rmsd_sel.append(nan) tau_band_sel.append(nan) tau_model_sel.append(nan) else: idx = idx[0] tau_550_sel.append(taufits[idx][0][i]) tau_rmsd_sel.append(taufits[idx][1][i]) tau_band_sel.append(taufits[idx][2][i]) tau_model_sel.append(idx + 1) ## select pixel with min rmsd pixel_idx = where(tau_rmsd_sel == nanmin(tau_rmsd_sel))[0][0] ## select lut and band lut_sel = luts[tau_model_sel[pixel_idx] - 1] sel_idx = tau_band_sel[pixel_idx] sel_rmsd = tau_rmsd_sel[pixel_idx] ## construct the selected dark pixel for band in rdark_selected.keys(): rdark_selected[band] = rdark_selected[band][pixel_idx] ## get selected LUT if pressure is not None: sel_model_lut, sel_model_lut_meta = pp.aerlut.aerlut_pressure( lut_sel, lutdir, pressure, sensor, rsr_file, lut_data_dict=lut_data_dict) else: sel_model_lut, sel_model_lut_meta = ( lut_data_dict[lut_sel]["lut"], lut_data_dict[lut_sel]["meta"]) ## get ac parameters for the selected rdark - probably better to use the TAU to retrieve parameters ? sel_ac_par = pp.aerlut.lut_get_ac_parameters_sensor( sel_model_lut, sel_model_lut_meta, azi, thv, ths, rdark_selected, force_band=force_band) ## get ac parameters from previously selected model (ratm_s, rorayl_s, dtotr_s, utotr_s, dtott_s, utott_s, astot_s) = sel_ac_par[0:7] tau550_all_bands = sel_ac_par[7] if type(sel_idx) == str: tau550 = tau550_all_bands[sel_idx] else: tau550 = tau550_all_bands[sel_idx[0]] dark_idx = sel_idx ## if tau is the minimum in the model ratm may be nans ## in that case replace by Rayleigh reflectance from numpy import isnan for band in ratm_s.keys(): if isnan(ratm_s[band]): ratm_s[band] = rorayl_s[band] return (ratm_s,rorayl_s,dtotr_s,utotr_s,dtott_s,utott_s,astot_s, tau550),\ (bands_sorted, tau550_all_bands, dark_idx, sel_rmsd, rdark_selected, pixel_idx), (sel_model_lut, sel_model_lut_meta)