def prospect5AndD(wl, isProspect5, N, Car, BP, Cm, Cab, Anth, Cw): if isProspect5: ws, rs, ts = ProspectD.Prospect5(N, Cab, Car, BP, Cw, Cm) else: ws, rs, ts = ProspectD.ProspectD(N, Cab, Car, BP, Cw, Cm, Anth) arr = wl.split(",") reflectances = [] transmittances = [] r, t = 0, 0 for wavelengthStr in arr: wavelength = float(wavelengthStr) # interpolation if wavelength <= 400: r, t = rs[0], ts[0] elif wavelength >= 2500: r, t = rs[2500], ts[2500] else: wavelength_int = math.floor(wavelength) extra = wavelength - wavelength_int left_r = rs[wavelength_int - 400] right_r = rs[wavelength_int - 400 + 1] k = (right_r - left_r) r = k * extra + left_r left_t = ts[wavelength_int - 400] right_t = ts[wavelength_int - 400 + 1] k = right_t - left_t t = k * extra + left_t reflectances.append("%.4f" % r) transmittances.append("%.4f" % t) return ','.join(reflectances), ','.join(transmittances)
def FCost_PROSPECTS_wl(x0, ObjParam, FixedValues, rho_leaf, wls, scale): ''' Cost Function for inverting PROSPECT5 the Root MeanSquare Error of observed vs. modeled reflectances and scaled [0,1] parameters. Parameters ---------- x0 : list Scaled (0-1) a priori PROSPECT5 values to be retrieved during the inversion. ObjParam : list PROSAIL parameters to be retrieved during the inversion, sorted in the same order as in the param list. ObjParam'=['N_leaf','Cab','Car','Cbrown', 'Cw','Cm', 'LAI', 'leaf_angle','hotspot']. FixedValues' : dict Values of the parameters that are fixed during the inversion. The dictionary must complement the list from ObjParam. rho_leaf : 1D-array observed leaf reflectance. The size of this list be n_wlss. wls : list wavebands used in the inversion. The size is n_wls. scale : list minimum and scale tuple (min,scale) for each objective parameter. Returns ------- mse : float Mean Square Error of observed vs. modelled surface reflectance This is the function to be minimized.''' param_list = ProspectDJacobian.paramsProspectD # Get the a priori parameters and fixed parameters for the inversion input_parameters = dict() i = 0 j = 0 for param in param_list: if param in ObjParam: #Transform the random variables (0-1) into biophysical variables input_parameters[param] = x0[i] * float(scale[i][1]) + float( scale[i][0]) i = i + 1 else: input_parameters[param] = FixedValues[j] j = j + 1 # Start processing n_wl = len(wls) error = np.zeros(n_wl) for i, wl in enumerate(wls): [l, r, t] = ProspectD.ProspectD_wl( wl, input_parameters['N_leaf'], input_parameters['Cab'], input_parameters['Car'], input_parameters['Cbrown'], input_parameters['Cw'], input_parameters['Cm'], input_parameters['Ant']) error[i] = (r - rho_leaf[i])**2 mse = 0.5 * np.mean(error) return mse
def simulate_prospectD_LUT(input_param, wls_sim, srf=None, outfile=None, ObjParam=('N_leaf', 'Cab', 'Car', 'Cbrown', 'Cm', 'Cw', 'Ant')): [wls, r, t] = ProspectD.ProspectD_vec(input_param['N_leaf'], input_param['Cab'], input_param['Car'], input_param['Cbrown'], input_param['Cw'], input_param['Cm'], input_param['Ant']) #Convolve the simulated spectra to a gaussian filter per band rho_leaf = [] tau_leaf = [] if srf: if type(srf) == float or type(srf) == int: wls = np.asarray(wls_sim) #Convolve spectra by full width half maximum sigma = FWHM2Sigma(srf) r = gaussian_filter1d(r, sigma) t = gaussian_filter1d(t, sigma) for wl in wls_sim: rho_leaf.append(float(r[wls == wl])) tau_leaf.append(float(t[wls == wl])) elif type(srf) == list or type(srf) == tuple: for weight in srf: rho_leaf.append(float(np.sum(weight * r) / np.sum(weight))) tau_leaf.append(float(np.sum(weight * t) / np.sum(weight))) else: rho_leaf = np.copy(r) tau_leaf = np.copy(t) rho_leaf = np.asarray(rho_leaf) tau_leaf = np.asarray(tau_leaf) if outfile: fid = open(outfile + '_rho', 'wb') pickle.dump(rho_leaf, fid, -1) fid.close() fid = open(outfile + '_param', 'wb') pickle.dump(input_param, fid, -1) fid.close() return rho_leaf, input_param
def run(N, chloro, caroten, brown, EWT, LMA, Ant, LAI, hot_spot, solar_zenith, solar_azimuth, view_zenith, view_azimuth, LIDF, skyl=0.2, soilType=DEFAULT_SOIL): ''' Runs Prospect5 4SAIL model to estimate canopy directional reflectance factor. Parameters ---------- N : float Leaf structural parameter. chloro : float chlorophyll a+b content (mug cm-2). caroten : float carotenoids content (mug cm-2). brown : float brown pigments concentration (unitless). EWT : float equivalent water thickness (g cm-2 or cm). LMA : float dry matter content (g cm-2). LAI : float Leaf Area Index. hot_spot : float Hotspot parameter. solar_zenith : float Sun Zenith Angle (degrees). solar_azimuth : float Sun Azimuth Angle (degrees). view_zenith : float View(sensor) Zenith Angle (degrees). view_azimuth : float View(sensor) Zenith Angle (degrees). LIDF : float or tuple(float,float) Leaf Inclination Distribution Function parameter. * if float, mean leaf angle for the Cambpell Spherical LIDF. * if tuple, (a,b) parameters of the Verhoef's bimodal LIDF |LIDF[0]| + |LIDF[1]|<=1. skyl : float, optional Fraction of diffuse shortwave radiation, default=0.2. soilType : str, optional filename of the soil type, defautl use inceptisol soil type, see SoilSpectralLibrary folder. Returns ------- wl : array_like wavelenghts. rho_canopy : array_like canopy reflectance factors. References ---------- .. [Feret08] Feret et al. (2008), PROSPECT-4 and 5: Advances in the Leaf Optical Properties Model Separating Photosynthetic Pigments, Remote Sensing of Environment. .. [Verhoef2007] Verhoef, W.; Jia, Li; Qing Xiao; Su, Z., (2007) Unified Optical-Thermal Four-Stream Radiative Transfer Theory for Homogeneous Vegetation Canopies, IEEE Transactions on Geoscience and Remote Sensing, vol.45, no.6, pp.1808-1822, http://dx.doi.org/10.1109/TGRS.2007.895844. ''' # Read the soil reflectance rsoil = np.genfromtxt(os.path.join(SOIL_FOLDER, soilType)) #wl_soil=rsoil[:,0] rsoil = np.array(rsoil[:, 1]) # Calculate the lidf if type(LIDF) == tuple or type(LIDF) == list: if len(LIDF) != 2: print( "ERROR, Verhoef's bimodal LIDF distribution must have two elements (LIDFa, LIDFb)" ) return None, None elif LIDF[0] + LIDF[1] > 1: print( "ERROR, |LIDFa| + |LIDFb| > 1 in Verhoef's bimodal LIDF distribution" ) else: lidf = FourSAIL.CalcLIDF_Verhoef(LIDF[0], LIDF[1]) else: lidf = FourSAIL.CalcLIDF_Campbell(LIDF) # PROSPECT5 for leaf bihemispherical reflectance and transmittance wl, rho_leaf, tau_leaf = ProspectD.ProspectD(N, chloro, caroten, brown, EWT, LMA, Ant) # Get the relative sun-view azimth angle psi = abs(solar_azimuth - view_azimuth) # 4SAIL for canopy reflectance and transmittance factors [ tss, too, tsstoo, rdd, tdd, rsd, tsd, rdo, tdo, rso, rsos, rsod, rddt, rsdt, rdot, rsodt, rsost, rsot, gammasdf, gammasdb, gammaso ] = FourSAIL.FourSAIL(LAI, hot_spot, lidf, solar_zenith, view_zenith, psi, rho_leaf, tau_leaf, rsoil) rho_canopy = rdot * skyl + rsot * (1 - skyl) return wl, rho_canopy
print('Generating %s simulations for SAIL' % N_samples_canopy) samples = saltelli.sample(problem_canopy, N, calc_second_order=False) input_param = {} for i, param in enumerate(FourSAIL.paramsPro4SAIL): input_param[param] = samples[:, i] samples_new = np.zeros((N_samples_canopy, len(ObjParams))) j = 0 for i, param in enumerate(FourSAIL.paramsPro4SAIL): if param in ObjParams: samples_new[:, j] = input_param[param] j += 1 print('Running ProspectD+4SAIL') l, r, t = ProspectD.ProspectD_vec(input_param['N_leaf'], input_param['Cab'], input_param['Car'], input_param['Cbrown'], input_param['Cw'], input_param['Cm'], input_param['Ant']) lidf = FourSAIL.CalcLIDF_Campbell_vec(input_param['leaf_angle']) # Read the soil reflectance rsoil = np.genfromtxt( pth.join(soil_folder, 'ipgp.jussieu.soil.prosail.dry.coarse.1.spectrum.txt')) #wl_soil=rsoil[:,0] rsoil = np.array(rsoil[:, 1]) rsoil = np.repeat(rsoil[:, np.newaxis], N_samples_canopy, axis=1) # Run nadir observations [_, _, _, _, _, _, _, _, _, _, _, _, _, _, rdot, _, _, rsot, _, _,
parser.add_argument("--Anth", help="Anth.", type=float) parser.add_argument("--Cw", help="Cw.", type=float) args = parser.parse_args() wl = args.wl # nm isProspect5 = args.isProspect5 N = args.N Car = args.Car BP = args.BP Cm = args.Cm Cab = args.Cab Anth = args.Anth Cw = args.Cw if isProspect5: ws, rs, ts = ProspectD.Prospect5(N, Cab, Car, BP, Cw, Cm) else: ws, rs, ts = ProspectD.ProspectD(N, Cab, Car, BP, Cw, Cm, Anth) arr = wl.split(",") reflectances = [] transmittances = [] r, t = 0, 0 for wavelengthStr in arr: wavelength = float(wavelengthStr) # interpolation if wavelength <= 400: r, t = rs[0], ts[0] elif wavelength >= 2500: r, t = rs[2500], ts[2500] else:
9, 'names': ['N_leaf', 'Cab', 'Car', 'Cbrown', 'Cw', 'Cm', 'Ant', 'LAI', 'leaf_angle'], 'bounds': [(1.0, 3.0), (0.0, 100.0), (0.0, 40.0), (0.0, 1.0), (0.000063, 0.040000), (0.001900, 0.016500), (0.00, 40.), (0.10, 6.), (30.0, 80.0)] } print('Generating %s simulations for ProspectD' % (N * (problem_leaf['num_vars'] + 2))) samples = saltelli.sample(problem_leaf, N, calc_second_order=calc_second_order) print('Running ProspectD') wls, rho, tau = ProspectD.ProspectD_vec(samples[:, 0], samples[:, 1], samples[:, 2], samples[:, 3], samples[:, 4], samples[:, 5], samples[:, 6]) N_samples_canopy = N * (problem_canopy['num_vars'] + 2) print('Generating %s simulations for SAIL' % N_samples_canopy) samples = saltelli.sample(problem_canopy, N, calc_second_order=calc_second_order) print('Running ProspectD+4SAIL') l, r, t = ProspectD.ProspectD_vec(samples[:, 0], samples[:, 1], samples[:, 2], samples[:, 3], samples[:, 4], samples[:, 5], samples[:, 6]) lidf = FourSAIL.CalcLIDF_Campbell_vec(samples[:, 8])
def FCost_ProSail_wl(x0, ObjParam, FixedValues, n_obs, rho_canopy, vza, sza, psi, skyl, rsoil, wls, scale): ''' Cost Function for inverting PROSPEC5 + 4SAIL based on the Mean Square Error of observed vs. modeled reflectances and scaled [0,1] parameters Parameters ---------- x0 : list Scaled (0-1) a priori PROSAIL values to be retrieved during the inversion. ObjParam : list PROSAIL parameters to be retrieved during the inversion, sorted in the same order as in the param list. ObjParam'=['N_leaf','Cab','Car','Cbrown', 'Cw','Cm', 'LAI', 'leaf_angle','hotspot']. FixedValues' : dict Values of the parameters that are fixed during the inversion. The dictionary must complement the list from ObjParam. N_obs : int the total number of observations used for the inversion. N_Obs=1. rho_canopy : 2D-array observed surface reflectances. The size of this list be N_obs x n_wls. vza : list View Zenith Angle for each one of the observations. The size must be equal to N_obs. sza : list Sun Zenith Angle for each one of the observations. The size must be equal to N_obs. psi : list Relative View-Sun Angle for each one of the observations. The size must be equal to N_obs. skyl : 2D-array ratio of diffuse radiation for each one of the observations. The size must be equal to N_obs x wls. rsoil : 1D-array background (soil) reflectance. The size must be equal to n_wls. wls : list wavebands used in the inversion. The size must be equal to n_wls. scale : list minimum and scale tuple (min,scale) for each objective parameter. Returns ------- mse : float Mean Square Error of observed vs. modelled surface reflectance This is the function to be minimized.''' param_list = FourSAILJacobian.paramsPro4SAIL # Get the a priori parameters and fixed parameters for the inversion input_parameters = dict() i = 0 j = 0 for param in param_list: if param in ObjParam: #Transform the random variables (0-1) into biophysical variables input_parameters[param] = x0[i] * float(scale[i][1]) + float( scale[i][0]) i = i + 1 else: input_parameters[param] = FixedValues[j] j = j + 1 # Start processing n_wl = len(wls) error = np.zeros(n_obs * n_wl) #Calculate LIDF lidf = FourSAIL.CalcLIDF_Campbell(float(input_parameters['leaf_angle'])) i = 0 for obs in range(n_obs): j = 0 for wl in wls: [l, r, t] = ProspectD.ProspectD_wl( wl, input_parameters['N_leaf'], input_parameters['Cab'], input_parameters['Car'], input_parameters['Cbrown'], input_parameters['Cw'], input_parameters['Cm'], input_parameters['Ant']) [ _, _, _, _, _, _, _, _, _, _, _, _, _, _, rdot, _, _, rsot, _, _, _ ] = FourSAIL.FourSAIL_wl(input_parameters['LAI'], input_parameters['hotspot'], lidf, float(sza[obs]), float(vza[obs]), float(psi[obs]), r, t, float(rsoil[j])) r2 = rdot * float(skyl[obs, j]) + rsot * (1 - float(skyl[obs, j])) error[i] = (r2 - rho_canopy[obs, j])**2 i += 1 j += 1 mse = 0.5 * np.mean(error) return mse
def simulate_prosail_lut(input_param, wls_sim, rsoil_vec, skyl=0.1, sza=37, vza=0, psi=0, srf=None, outfile=None, calc_FAPAR=False, reduce_4sail=False): print('Starting Simulations') # Calculate the lidf lidf = FourSAIL.CalcLIDF_Campbell_vec(input_param['leaf_angle']) #for i,wl in enumerate(wls_wim): [wls, r, t] = ProspectD.ProspectD_vec(input_param['N_leaf'], input_param['Cab'], input_param['Car'], input_param['Cbrown'], input_param['Cw'], input_param['Cm'], input_param['Ant']) r = r.T t = t.T if type(skyl) == float: skyl = skyl * np.ones(r.shape) if calc_FAPAR: par_index = wls <= 700 rho_leaf_fapar = np.mean(r[par_index], axis=0).reshape(1, -1) tau_leaf_fapar = np.mean(t[par_index], axis=0).reshape(1, -1) skyl_rho_fapar = np.mean(skyl[par_index], axis=0).reshape(1, -1) rsoil_vec_fapar = np.mean(rsoil_vec[par_index], axis=0).reshape(1, -1) par_index = wls_sim <= 700 #Convolve the simulated spectra to a gaussian filter per band rho_leaf = [] tau_leaf = [] skyl_rho = [] rsoil = [] if srf and reduce_4sail: if type(srf) == float or type(srf) == int: wls_sim = np.asarray(wls_sim) #Convolve spectra by full width half maximum sigma = fwhm2sigma(srf) r = gaussian_filter1d(r, sigma, axis=1) t = gaussian_filter1d(t, sigma, axis=1) s = gaussian_filter1d(skyl, sigma, axis=1) soil = gaussian_filter1d(rsoil_vec, sigma, axis=1) for wl in wls_sim: rho_leaf.append(r[wls == wl].reshape(-1)) tau_leaf.append(t[wls == wl].reshape(-1)) skyl_rho.append(s[wls == wl].reshape(-1)) rsoil.append(soil[wls == wl].reshape(-1)) elif type(srf) == list or type(srf) == tuple: skyl = np.tile(skyl, (r.shape[1], 1)).T for weight in srf: weight = np.tile(weight, (r.shape[1], 1)).T rho_leaf.append( np.sum(weight * r, axis=0) / np.sum(weight, axis=0)) tau_leaf.append( np.sum(weight * t, axis=0) / np.sum(weight, axis=0)) skyl_rho.append( np.sum(weight * skyl, axis=0) / np.sum(weight, axis=0)) rsoil.append( np.sum(weight * rsoil_vec, axis=0) / np.sum(weight, axis=0)) skyl_rho = np.asarray(skyl_rho) elif reduce_4sail: wls_sim = np.asarray(wls_sim) for wl in wls_sim: rho_leaf.append(r[wls == wl].reshape(-1)) tau_leaf.append(t[wls == wl].reshape(-1)) skyl_rho.append(skyl[wls == wl].reshape(-1)) rsoil.append(rsoil_vec[wls == wl].reshape(-1)) else: rho_leaf = r.T tau_leaf = t.T skyl_rho = np.asarray(skyl.T) rsoil = np.asarray(rsoil_vec) rho_leaf = np.asarray(rho_leaf) tau_leaf = np.asarray(tau_leaf) skyl_rho = np.asarray(skyl_rho) rsoil = np.asarray(rsoil) [_, _, _, _, _, _, _, _, _, _, _, _, _, _, rdot, _, _, rsot, _, _, _] = FourSAIL.FourSAIL_vec(input_param['LAI'], input_param['hotspot'], lidf, np.ones(input_param['LAI'].shape) * sza, np.ones(input_param['LAI'].shape) * vza, np.ones(input_param['LAI'].shape) * psi, rho_leaf, tau_leaf, rsoil) r2 = rdot * skyl_rho + rsot * (1 - skyl_rho) del rdot, rsot if calc_FAPAR: fAPAR_array, fIPAR_array = calc_fapar_4sail( skyl_rho_fapar, input_param['LAI'], lidf, input_param['hotspot'], np.ones(input_param['LAI'].shape) * sza, rho_leaf_fapar, tau_leaf_fapar, rsoil_vec_fapar) fAPAR_array[np.isfinite(fAPAR_array)] = np.clip( fAPAR_array[np.isfinite(fAPAR_array)], 0, 1) fIPAR_array[np.isfinite(fIPAR_array)] = np.clip( fIPAR_array[np.isfinite(fIPAR_array)], 0, 1) input_param['fAPAR'] = fAPAR_array input_param['fIPAR'] = fIPAR_array del fAPAR_array, fIPAR_array rho_canopy = [] if srf and not reduce_4sail: if type(srf) == float or type(srf) == int: #Convolve spectra by full width half maximum sigma = fwhm2sigma(srf) r2 = gaussian_filter1d(r2, sigma, axis=1) for wl in wls_sim: rho_canopy.append(r2[wls == wl].reshape(-1)) elif type(srf) == list or type(srf) == tuple: for weight in srf: weight = np.tile(weight, (1, r2.shape[2])).T rho_canopy.append( np.sum(weight * r2, axis=0) / np.sum(weight, axis=0)) elif reduce_4sail: rho_canopy = np.asarray(r2) else: for wl in wls_sim: rho_canopy.append(r2[wls == wl].reshape(-1)) rho_canopy = np.asarray(rho_canopy) if outfile: fid = open(outfile + '_rho', 'wb') pickle.dump(rho_canopy, fid, -1) fid.close() fid = open(outfile + '_param', 'wb') pickle.dump(input_param, fid, -1) fid.close() return rho_canopy.T, input_param