def heuristic_atmosphere(RT, instrument, x_RT, x_instrument, meas, geom): '''From a given radiance, estimate atmospheric state with band ratios. Used to initialize gradient descent inversions.''' # Identify the latest instrument wavelength calibration (possibly # state-dependent) and identify channel numbers for the band ratio. wl, fwhm = instrument.calibration(x_instrument) b865 = s.argmin(abs(wl-865)) b945 = s.argmin(abs(wl-945)) b1040 = s.argmin(abs(wl-1040)) if not (any(RT.wl > 850) and any(RT.wl < 1050)): return x_RT x_new = x_RT.copy() # Band ratio retrieval of H2O. Depending on the radiative transfer # model we are using, this state parameter could go by several names. for h2oname in ['H2OSTR', 'h2o']: if h2oname not in RT.statevec: continue # ignore unused names if h2oname not in RT.lut_names: continue # find the index in the lookup table associated with water vapor ind_lut = RT.lut_names.index(h2oname) ind_sv = RT.statevec.index(h2oname) h2os, ratios = [], [] # We iterate through every possible grid point in the lookup table, # calculating the band ratio that we would see if this were the # atmospheric H2O content. It assumes that defaults for all other # atmospheric parameters (such as aerosol, if it is there). for h2o in RT.lut_grids[ind_lut]: # Get Atmospheric terms at high spectral resolution x_RT_2 = x_RT.copy() x_RT_2[ind_sv] = h2o rhoatm_hi, sphalb_hi, transm_hi, transup_hi = RT.get(x_RT_2, geom) rhoatm = instrument.sample(x_instrument, RT.wl, rhoatm_hi) transm = instrument.sample(x_instrument, RT.wl, transm_hi) solar_irr = instrument.sample(x_instrument, RT.wl, RT.solar_irr) # Assume no surface emission. "Correct" the at-sensor radiance # using this presumed amount of water vapor, and measure the # resulting residual (as measured from linear interpolation across # the absorption feature) r = (meas*s.pi/(solar_irr*RT.coszen) - rhoatm) / (transm+1e-8) ratios.append((r[b945]*2.0)/(r[b1040]+r[b865])) h2os.append(h2o) # Finally, interpolate to determine the actual water vapor level that # would optimize the continuum-relative correction p = interp1d(h2os, ratios) bounds = (h2os[0]+0.001, h2os[-1]-0.001) best = min1d(lambda h: abs(1-p(h)), bounds=bounds, method='bounded') x_new[ind_sv] = best.x return x_new
def heuristic_atmosphere(self, rdn, geom): '''From a given radiance, estimate atmospheric state using band ratio heuristics. Used to initialize gradient descent inversions.''' x = self.init_val.copy() # Band ratio retrieval of H2O for h2oname in ['H2OSTR', 'h2o']: if (h2oname in self.lut_names) and \ any(self.wl > 850) and any(self.wl < 1050): ind_lut = self.lut_names.index(h2oname) ind_sv = self.statevec.index(h2oname) b865, b945, b1040 = [ s.argmin(abs(self.wl - t)) for t in (865, 945, 1040) ] h2os, ratios = [], [ ] # will be corrected for transmission, path radiance for h2o in self.lut_grids[ind_lut]: xnew = x.copy() xnew[ind_sv] = h2o rhoatm, sphalb, transm, transup = self.get(xnew, geom) # assume no surface emission r = (rdn * s.pi / (self.solar_irr * self.coszen) - rhoatm) / (transm + 1e-8) ratios.append((r[b945] * 2.0) / (r[b1040] + r[b865])) h2os.append(h2o) p = interp1d(h2os, ratios) bounds = (h2os[0] + 0.001, h2os[-1] - 0.001) best = min1d(lambda h: abs(1 - p(h)), bounds=bounds, method='bounded') x[ind_sv] = best.x Ls_est = s.zeros(rdn.shape) rfl_est = self.invert_algebraic(x, rdn, Ls_est, geom) return x, rfl_est
def heuristic_atmosphere(RT: RadiativeTransfer, instrument, x_RT, x_instrument, meas, geom): """From a given radiance, estimate atmospheric state with band ratios. Used to initialize gradient descent inversions.""" # Identify the latest instrument wavelength calibration (possibly # state-dependent) and identify channel numbers for the band ratio. wl, fwhm = instrument.calibration(x_instrument) b865 = np.argmin(abs(wl - 865)) b945 = np.argmin(abs(wl - 945)) b1040 = np.argmin(abs(wl - 1040)) if not (any(RT.wl > 850) and any(RT.wl < 1050)): return x_RT x_new = x_RT.copy() # Figure out which RT object we are using # TODO: this is currently very specific to vswir-tir 2-mode, eventually generalize my_RT = None for rte in RT.rt_engines: if rte.treat_as_emissive is False: my_RT = rte break if not my_RT: raise ValueError('No suiutable RT object for initialization') # Band ratio retrieval of H2O. Depending on the radiative transfer # model we are using, this state parameter could go by several names. for h2oname in ['H2OSTR', 'h2o']: if h2oname not in RT.statevec_names: continue # ignore unused names if h2oname not in my_RT.lut_names: continue # find the index in the lookup table associated with water vapor ind_lut = my_RT.lut_names.index(h2oname) ind_sv = RT.statevec_names.index(h2oname) h2os, ratios = [], [] # We iterate through every possible grid point in the lookup table, # calculating the band ratio that we would see if this were the # atmospheric H2O content. It assumes that defaults for all other # atmospheric parameters (such as aerosol, if it is there). for h2o in my_RT.lut_grids[ind_lut]: # Get Atmospheric terms at high spectral resolution x_RT_2 = x_RT.copy() x_RT_2[ind_sv] = h2o rhi = RT.get_shared_rtm_quantities(x_RT_2, geom) rhoatm = instrument.sample(x_instrument, RT.wl, rhi['rhoatm']) transm = instrument.sample(x_instrument, RT.wl, rhi['transm']) sphalb = instrument.sample(x_instrument, RT.wl, rhi['sphalb']) solar_irr = instrument.sample(x_instrument, RT.wl, RT.solar_irr) # Assume no surface emission. "Correct" the at-sensor radiance # using this presumed amount of water vapor, and measure the # resulting residual (as measured from linear interpolation across # the absorption feature) rho = meas * np.pi / (solar_irr * RT.coszen) r = 1.0 / (transm / (rho - rhoatm) + sphalb) ratios.append((r[b945] * 2.0) / (r[b1040] + r[b865])) h2os.append(h2o) # Finally, interpolate to determine the actual water vapor level that # would optimize the continuum-relative correction p = interp1d(h2os, ratios) bounds = (h2os[0] + 0.001, h2os[-1] - 0.001) best = min1d(lambda h: abs(1 - p(h)), bounds=bounds, method='bounded') x_new[ind_sv] = best.x return x_new