def calc_emissivity_4SAIL(lai, vza, alpha, emis_veg=0.98, emis_soil=0.95, tau=0.0): ''' Estimates surface directional emissivity using 4SAIL Radiative Transfer Model Parameters ---------- lai : array_like Leaf Area Index vza : array_like View Zenith Angle alpha : array_like Average leaf angle in Campbell ellipsoidal leaf inclination distribution function emis_veg : float Leaf emissivity emis_soil : bool Bare soil emissivity tau : float Leaf thermal transmittance, default=0 Returns ------- emissivity : array_like surface directional emissivity ''' # Get array dimensions and check for consistency in the dimensions lai = np.asarray(lai) vza = _check_default_parameter_size(vza, lai) alpha = _check_default_parameter_size(alpha, lai) dims = lai.shape # Vectorize the inputs lai = lai.reshape(-1) vza = vza.reshape(-1) alpha = alpha.reshape(-1) # Solar parameters (illumination angles and hotpost) in FourSAIL are not relevant: hotspot, sza, psi = np.zeros(lai.shape), np.zeros(lai.shape), np.zeros( lai.shape) lidf = sail.CalcLIDF_Campbell_vec(alpha, n_elements=18) [_, _, _, _, _, _, _, _, _, _, _, _, _, _, rdot, _, _, _, _, _, _] = sail.FourSAIL_vec(lai, hotspot, lidf, sza, vza, psi, np.ones(lai.shape)[np.newaxis, :] - emis_veg, np.zeros(lai.shape)[np.newaxis, :], np.ones(lai.shape)[np.newaxis, :] - emis_soil) # Kirchoff law emissivity = 1.0 - rdot # Convert output vector to original array emissivity = emissivity.reshape(dims) return emissivity
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, _, _, _] = FourSAIL.FourSAIL_vec(input_param['LAI'], input_param['hotspot'], lidf, np.ones(N_samples_canopy) * 37., np.zeros(N_samples_canopy), np.zeros(N_samples_canopy), r.T, t.T, rsoil) rho_canopy = rdot * 0.2 + rsot * (1.0 - 0.2) #Convolve spectra by full width half maximum sigma = fwhm / (2.0 * np.sqrt(2.0 * np.log(2.0))) rho_canopy = gaussian_filter1d(rho_canopy, sigma, axis=0) rho_canopy_nadir = rho_canopy.T # Run oblique observations [_, _, _, _, _, _, _, _, _, _, _, _, _, _, rdot, _, _, rsot, _, _, _] = FourSAIL.FourSAIL_vec(input_param['LAI'], input_param['hotspot'], lidf, np.ones(N_samples_canopy) * 37., np.ones(N_samples_canopy) * 40., np.zeros(N_samples_canopy), r.T, t.T, rsoil)
lidf = FourSAIL.CalcLIDF_Campbell_vec(samples[:, 8]) # 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) [_, _, _, _, _, _, _, _, _, _, _, _, _, _, rdot, _, _, rsot, _, _, _] = FourSAIL.FourSAIL_vec(samples[:, 7], np.ones(N_samples_canopy) * 0.01, lidf, np.ones(N_samples_canopy) * 37., np.zeros(N_samples_canopy), np.zeros(N_samples_canopy), r.T, t.T, rsoil) rho_canopy = rdot * 0.2 + rsot * (1.0 - 0.2) if fwhm: #Convolve spectra by full width half maximum sigma = fwhm / (2.0 * np.sqrt(2.0 * np.log(2.0))) rho_canopy = gaussian_filter1d(rho_canopy, sigma, axis=0) rho_canopy = rho_canopy.T del r, t, lidf, _, rdot, rsot, rsoil print('Running Sensitivity Analysis')
def calc_fapar_4sail(skyl, LAI, lidf, hotspot, sza, rho_leaf, tau_leaf, rsoil): '''Estimates the fraction of Absorbed and intercepted PAR using the 4SAIL Radiative Transfer Model. Parameters ---------- skyl : float Ratio of diffuse to total PAR radiation LAI : float Leaf (Plant) Area Index lidf : list Leaf Inclination Distribution Function, 5 degrees step hotspot : float hotspot parameters, use 0 to ignore the hotspot effect (turbid medium) sza : float Sun Zenith Angle (degrees) rho_leaf : list Narrowband leaf bihemispherical reflectance, it might be simulated with PROSPECT (400-700 @1nm) tau_leaf : list Narrowband leaf bihemispherical transmittance, it might be simulated with PROSPECT (400-700 @1nm) rsoil : list Narrowband soil bihemispherical reflectance (400-700 @1nm) Returns ------- fAPAR : float Fraction of Absorbed Photosynthetically Active Radiation fIPAR : float Fraction of Intercepted Photosynthetically Active Radiation''' # Diffuse and direct irradiance Es = 1.0 - skyl Ed = skyl #Initialize values S_0 = np.zeros(rho_leaf.shape) S_1 = np.zeros(rho_leaf.shape) # Start the hemispherical integration vzas_psis = ((vza, psi) for vza in np.arange(0, 90 - STEP_VZA / 2., STEP_VZA) for psi in np.arange(0, 360, STEP_PSI)) step_vza_radians, step_psi_radians = np.radians(STEP_VZA), np.radians( STEP_PSI) for vza, psi in vzas_psis: vza += STEP_VZA / 2. # Calculate the reflectance factor and project into the solid angle cosvza = np.cos(np.radians(vza)) sinvza = np.sin(np.radians(vza)) [ tss, _, _, rdd, tdd, _, tsd, _, _, _, _, _, _, _, rdot, _, _, rsot, _, _, _ ] = FourSAIL.FourSAIL_vec(LAI, hotspot, lidf, sza, np.ones(LAI.shape) * vza, np.ones(LAI.shape) * psi, rho_leaf, tau_leaf, rsoil) # Downwelling solar beam radiation at ground level (beam transmissnion) Es_1 = tss * Es # Upwelling diffuse shortwave radiation at ground level Ed_up_1 = (rsoil * (Es_1 + tsd * Es + tdd * Ed)) / (1. - rsoil * rdd) # Downwelling diffuse shortwave radiation at ground level Ed_down_1 = tsd * Es + tdd * Ed + rdd * Ed_up_1 # Upwelling shortwave (beam and diffuse) radiation towards the observer (at angle psi/vza) Eo_0 = rdot * Ed + rsot * Es # Spectral flux at the top of the canopy # & add the top of the canopy flux to the integral and continue through the hemisphere S_0 += Eo_0 * cosvza * sinvza * step_vza_radians * step_psi_radians # Spectral flus at the bottom of the canopy # & add the bottom of the canopy flux to the integral and continue through the hemisphere S_1 += ( Es_1 + tdd * Ed) * cosvza * sinvza * step_vza_radians * step_psi_radians / np.pi # Absorbed flux at ground lnevel Sn_soil = (1. - rsoil) * (Es_1 + Ed_down_1 ) # narrowband net soil shortwave radiation # Calculate the vegetation (sw/lw) net radiation (divergence) as residual of top of the canopy and net soil radiation Rn_sw_veg_nb = 1.0 - S_0 - Sn_soil # narrowband net canopy sw radiation fAPAR = np.sum( Rn_sw_veg_nb, axis=0) / Rn_sw_veg_nb.shape[0] # broadband net canopy sw radiation fIPAR = np.sum(1.0 - S_1, axis=0) / S_1.shape[0] return fAPAR, fIPAR
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