def create(self, channel_index=None, **kwargs): # Azimuth is modified because the convention used by the OCO L1B file is to # take both solar and observation angles as viewed from an observer # standing in the FOV. In this convention, the convention for glint # would be a relative azimuth difference of 180 degrees, as the # spacecraft and sun would be on opposite sides of the sky. However, the # radiative transfer convention is that the azimuth angles must be the # same for glint (it is "follow the photons" convention). However, we'd # like the solar azimuth to not be changed, so as to continue to agree # with zenith, so this change of the observation azimuth has the effect # of putting everything in a "reverse follow-the-photons" convention, # where we look from the satellite to the FOV, then from the FOV to the # sun. Note that because of an old historical reason, however, both # zenith angles remain > 0 and < 90, even in the RT convention. l1b = self.l1b() orig_units = l1b.sounding_azimuth(0).units rel_azm_vals = [] deg_units = rf.Unit("deg") for chan_idx in range(l1b.number_spectrometer): val = (180 + l1b.sounding_azimuth(chan_idx).convert(deg_units).value) - \ l1b.solar_azimuth(chan_idx).convert(deg_units).value if val > 360: val -= 360 elif val < 0: val += 360 rel_azm_vals.append(val) return rf.ArrayWithUnit_double_1(rel_azm_vals, orig_units)
def _as_array_with_unit(self, accessor): num_channels = self.l1b().number_spectrometer vals = [] units = None for chan_idx in range(num_channels): chan_val = accessor(chan_idx) vals.append(chan_val.value) new_units = chan_val.units if units != None and new_units.name != units.name: raise param.ParamError( "All units for L1B values must be the same to compact as an array" ) else: units = new_units val_arr = np.array(vals) if len(val_arr.shape) == 1: return rf.ArrayWithUnit_double_1(vals, units) if len(val_arr.shape) == 2: return rf.ArrayWithUnit_double_2(vals, units) else: raise param.ParamError( "Unhandled return value size from L1b class")
def test_array_with_unit_param(): # Check that arrays are correctly handled config_def = { 'creator': ParamReturnCreator(param.ArrayWithUnit), 'val': rf.ArrayWithUnit_double_1(np.arange(1, 6), "m"), } config_inst = process_config(config_def)
def spacing(self): "Returns the array with unit value for spacing specified regardless if it was specified as an array or scalar value with unit" spacing_val = self.high_res_spacing() num_channels = self.num_channels() if isinstance(spacing_val, rf.DoubleWithUnit): # Create an ArrayWithDouble matching the number of channels used spacing_used = rf.ArrayWithUnit_double_1(np.full(num_channels, spacing_val.value), spacing_val.units) else: self.check_num_channels(spacing_val.value.shape[0]) spacing_used = spacing_val return spacing_used
def create(self, **kwargs): value = self.value(**kwargs) units = self.units() num_dims = len(value.shape) if num_dims == 3: return rf.ArrayWithUnit_double_3(value, units) elif num_dims == 2: return rf.ArrayWithUnit_double_2(value, units) elif num_dims == 1: return rf.ArrayWithUnit_double_1(value, units) else: raise param.ParamError( "Unsupported number of dimensions %s for array" % (num_dims))
def create(self, **kwargs): import warnings warnings.warn("Instead of using this creator use framweork.ArrayWithUnit factory class", DeprecationWarning) value = self.value(**kwargs) units = self.units() num_dims = len(value.shape) if num_dims == 3: return rf.ArrayWithUnit_double_3(value, units) elif num_dims == 2: return rf.ArrayWithUnit_double_2(value, units) elif num_dims == 1: return rf.ArrayWithUnit_double_1(value, units) else: raise param.ParamError("Unsupported number of dimensions %s for array" % (num_dims))
def create(self, **kwargs): coeffs = self.value() flags = self.retrieval_flag() sounding_number = self.sounding_number() order = self.order() band_names = self.desc_band_name() hdf_group = self.hdf_group() scale_uncertainty = self.scale_uncertainty() scale_to_stddev = self.scale_to_stddev() l1b = self.l1b() if scale_uncertainty and scale_to_stddev is None: raise param.ParamError( "scale_to_stddev must be supplied when scale_uncertainty is True" ) if scale_uncertainty and l1b is None: raise param.ParamError( "l1b must be supplied when scale_uncertainty is True") eof_hdf = rf.HdfFile(self.eof_file()) eofs = [] for chan_idx in range(self.num_channels()): if (scale_uncertainty): chan_rad = l1b.radiance(chan_idx) uncert = rf.ArrayWithUnit_double_1(chan_rad.uncertainty, chan_rad.units) eof_obj = rf.EmpiricalOrthogonalFunction( coeffs[chan_idx], bool(flags[chan_idx]), eof_hdf, uncert, chan_idx, sounding_number, order, band_names[chan_idx], hdf_group, scale_to_stddev) else: eof_obj = rf.EmpiricalOrthogonalFunction( coeffs[chan_idx], bool(flags[chan_idx]), eof_hdf, chan_idx, sounding_number, order, band_names[chan_idx], hdf_group) eofs.append(eof_obj) return eofs
def create(self, **kwargs): l1b = self.l1b() num_channels = l1b.number_spectrometer solar_dist_vals = np.empty(num_channels) solar_dist_units = None for chan_idx in range(num_channels): chan_doppler_shift = \ rf.SolarDopplerShiftPolynomial(l1b.time(chan_idx), l1b.latitude(chan_idx), l1b.solar_zenith(chan_idx), l1b.solar_azimuth(chan_idx), l1b.altitude(chan_idx), self.constants(), self.do_doppler_shift()) chan_solar_dist = chan_doppler_shift.solar_distance solar_dist_vals[chan_idx] = chan_solar_dist.value solar_dist_units = chan_solar_dist.units return rf.ArrayWithUnit_double_1(solar_dist_vals, solar_dist_units)