def __init__(self, config): self.statevec = [] self.bounds = s.array([]) self.scale = s.array([]) self.init = s.array([]) self.bvec = [] self.bval = s.array([]) self.emissive = False self.reconfigure(config) if 'reflectance_file' in config: self.rfl, self.wl = load_spectrum(config['reflectance_file']) self.n_wl = len(self.wl) elif 'wavelength_file' in config: self.wl, self.fwhm = load_wavelen(config['wavelength_file']) self.n_wl = len(self.wl)
def __init__(self, fname, write=False, n_rows=None, n_cols=None, n_bands=None, interleave=None, dtype=s.float32, wavelengths=None, fwhm=None, band_names=None, bad_bands=[], zrange='{0.0, 1.0}', ztitles='{Wavelength (nm), Magnitude}', map_info='{}'): self.frames = OrderedDict() self.write = write self.fname = fname self.wl = wavelengths self.band_names = band_names self.fwhm = fwhm self.n_rows = n_rows self.n_cols = n_cols self.n_bands = n_bands if self.fname.endswith('.txt'): # The .txt suffix implies a space-separated ASCII text file of # one or more data columns. This is cheap to load and store, so # we do not defer read/write operations. logging.debug('Inferred ASCII file format for %s' % self.fname) self.format = 'ASCII' if not self.write: self.data, self.wl = load_spectrum(self.fname) self.n_rows, self.n_cols, self.map_info = 1, 1, '{}' if self.wl is not None: self.n_bands = len(self.wl) else: self.n_bands = None self.meta = {} elif self.fname.endswith('.mat'): # The .mat suffix implies a matlab-style file, i.e. a dictionary # of 2D arrays and other matlab-like objects. This is typically # only used for specific output products associated with single # spectrum retrievals; there is no read option. logging.debug('Inferred MATLAB file format for %s' % self.fname) self.format = 'MATLAB' if not self.write: logging.error('Unsupported MATLAB file in input block') raise IOError('MATLAB format in input block not supported') else: # Otherwise we assume it is an ENVI-format file, which is # basically just a binary data cube with a detached human- # readable ASCII header describing dimensions, interleave, and # metadata. We buffer this data in self.frames, reading and # writing individual rows of the cube on-demand. logging.debug('Inferred ENVI file format for %s' % self.fname) self.format = 'ENVI' if not self.write: # If we are an input file, the header must preexist. if not os.path.exists(self.fname + '.hdr'): logging.error('Could not find %s' % (self.fname + '.hdr')) raise IOError('Could not find %s' % (self.fname + '.hdr')) # open file and copy metadata, checking interleave format self.file = envi.open(self.fname + '.hdr', fname) self.meta = self.file.metadata.copy() if self.meta['interleave'] not in ['bil', 'bip']: logging.error('Unsupported interleave format.') raise IOError('Unsupported interleave format.') self.n_rows = int(self.meta['lines']) self.n_cols = int(self.meta['samples']) self.n_bands = int(self.meta['bands']) else: # If we are an output file, we may have to build the header # from scratch. Hopefully the caller has supplied the # necessary metadata details. meta = { 'lines': n_rows, 'samples': n_cols, 'bands': n_bands, 'byte order': 0, 'header offset': 0, 'map info': map_info, 'file_type': 'ENVI Standard', 'sensor type': 'unknown', 'interleave': interleave, 'data type': typemap[dtype], 'wavelength units': 'nm', 'z plot range': zrange, 'z plot titles': ztitles, 'fwhm': fwhm, 'bbl': bad_bands, 'band names': band_names, 'wavelength': self.wl } for k, v in meta.items(): if v is None: logging.error('Must specify %s' % (k)) raise IOError('Must specify %s' % (k)) self.file = envi.create_image(fname + '.hdr', meta, ext='', force=True) self.open_map_with_retries()
def __init__(self, config, forward, inverse, active_rows, active_cols): """Initialization specifies retrieval subwindows for calculating measurement cost distributions""" # Default IO configuration options self.input = {} self.output = {'plot_surface_components': False} self.iv = inverse self.fm = forward self.bbl = '[]' self.radiance_correction = None self.meas_wl = forward.instrument.wl_init self.meas_fwhm = forward.instrument.fwhm_init self.writes = 0 self.n_rows = 1 self.n_cols = 1 self.n_sv = len(self.fm.statevec) self.n_chan = len(self.fm.instrument.wl_init) if 'input' in config: self.input.update(config['input']) if 'output' in config: self.output.update(config['output']) if 'logging' in config: logging.config.dictConfig(config) # A list of all possible input data sources self.possible_inputs = [ "measured_radiance_file", "reference_reflectance_file", "reflectance_file", "obs_file", "glt_file", "loc_file", "surface_prior_mean_file", "surface_prior_variance_file", "rt_prior_mean_file", "rt_prior_variance_file", "instrument_prior_mean_file", "instrument_prior_variance_file", "radiometry_correction_file" ] # A list of all possible outputs. There are several special cases # that we handle differently - the "plot_directory", "summary_file", # "Data dump file", etc. wl_names = [('Channel %i' % i) for i in range(self.n_chan)] sv_names = self.fm.statevec.copy() self.output_info = { "estimated_state_file": (sv_names, '{State Parameter, Value}', '{}'), "estimated_reflectance_file": (wl_names, '{Wavelength (nm), Lambertian Reflectance}', '{0.0,1.0}'), "estimated_emission_file": (wl_names, '{Wavelength (nm), Emitted Radiance (uW nm-1 cm-2 sr-1)}', '{}'), "modeled_radiance_file": (wl_names, '{Wavelength (nm), Modeled Radiance (uW nm-1 cm-2 sr-1)}', '{}'), "apparent_reflectance_file": (wl_names, '{Wavelength (nm), Apparent Surface Reflectance}', '{}'), "path_radiance_file": (wl_names, '{Wavelength (nm), Path Radiance (uW nm-1 cm-2 sr-1)}', '{}'), "simulated_measurement_file": (wl_names, '{Wavelength (nm), Simulated Radiance (uW nm-1 cm-2 sr-1)}', '{}'), "algebraic_inverse_file": (wl_names, '{Wavelength (nm), Apparent Surface Reflectance}', '{}'), "atmospheric_coefficients_file": (wl_names, '{Wavelength (nm), Atmospheric Optical Parameters}', '{}'), "radiometry_correction_file": (wl_names, '{Wavelength (nm), Radiometric Correction Factors}', '{}'), "spectral_calibration_file": (wl_names, '{}', '{}'), "posterior_uncertainty_file": (sv_names, '{State Parameter, Value}', '{}') } self.defined_outputs, self.defined_inputs = {}, {} self.infiles, self.outfiles, self.map_info = {}, {}, '{}' # Load input files and record relevant metadata for q in self.input: if q in self.possible_inputs: self.infiles[q] = SpectrumFile(self.input[q]) if (self.infiles[q].n_rows > self.n_rows) or \ (self.infiles[q].n_cols > self.n_cols): self.n_rows = self.infiles[q].n_rows self.n_cols = self.infiles[q].n_cols for inherit in ['map info', 'bbl']: if inherit in self.infiles[q].meta: setattr(self, inherit.replace(' ', '_'), self.infiles[q].meta[inherit]) for q in self.output: if q in self.output_info: band_names, ztitle, zrange = self.output_info[q] n_bands = len(band_names) self.outfiles[q] = SpectrumFile(self.output[q], write=True, n_rows=self.n_rows, n_cols=self.n_cols, n_bands=n_bands, interleave='bip', dtype=s.float32, wavelengths=self.meas_wl, fwhm=self.meas_fwhm, band_names=band_names, bad_bands=self.bbl, map_info=self.map_info, zrange=zrange, ztitles=ztitle) # Do we apply a radiance correction? if 'radiometry_correction_file' in self.input: filename = self.input['radiometry_correction_file'] self.radiance_correction, wl = load_spectrum(filename) # Last thing is to define the active image area if active_rows is None: active_rows = s.arange(self.n_rows) if active_cols is None: active_cols = s.arange(self.n_cols) self.iter_inds = [] for row in active_rows: for col in active_cols: self.iter_inds.append([row, col]) self.iter_inds = s.array(self.iter_inds)