Supporting Types

WISER uses a number of types internally to wrap various kinds of information. These types often hold NumPy ndarray objects or other such details for the actual data, and also provide metadata about the information being managed. These types are important for most kinds of plugins, and are documented here.

Raster Data Sets

Imaging spectroscopy cubes are represented with the RasterDataSet class. This class provides access to both the data and metadata of a spectral image cube.

class wiser.raster.RasterDataSet(impl: RasterDataImpl, data_cache: DataCache | None = None)[source]

A 2D raster data-set for imaging spectroscopy, possibly with many bands of data for each pixel.

This class is not deep copyable. If you try to deep copy it, you will get an reference to the same object.

get_id() int | None[source]

Returns a numeric ID for referring to the data set within the application. A value of None indicates that the data-set has not yet been assigned an ID.

set_id(id: int) None[source]

Sets a unique numeric ID for referring to the data set within WISER.

get_description() str | None[source]

Returns a string description of the dataset that might be specified in the raster file’s metadata. A missing description is indicated by the None value.

set_description(description: str | None) None[source]

Sets the string description of the dataset.

get_format()[source]

Returns a string describing the type of raster data file that backs this dataset. The file-type string will be specific to the kind of loader used to load the dataset.

get_filepaths()[source]

Returns the paths and filenames of all files associated with this raster dataset. This will be an empty list (not None) if the data is in-memory only, e.g. because it wasn’t yet saved.

get_width()[source]

Returns the number of pixels per row in the raster data.

get_height()[source]

Returns the number of rows of data in the raster data.

num_bands()[source]

Returns the number of spectral bands in the raster data.

get_shape() Tuple[int, int, int][source]

Returns the shape of the raster data set. This is always in the order (num_bands, height, width).

get_elem_type() dtype[source]

Returns the element-type of the raster data set.

get_band_memory_size() int[source]

Returns the approximate size of a band of this dataset. It’s approximate because this doesn’t account for compression

get_memory_size() int[source]

Returns the approximate size of this dataset. It’s approximate because this doesn’t account for compression

get_band_unit() Unit | None[source]

Returns the units used for all bands’ wavelengths, or None if bands do not specify units.

band_list() List[Dict[str, Any]][source]

Returns a description of all bands in the data set. The description is formulated as a list of dictionaries, where each dictionary provides details about the band. The list of dictionaries is in the same order as the bands in the raster dataset, so that the dictionary at index i in the list describes band i.

Dictionaries may (but are not required to) contain these keys:

  • ‘index’ - the integer index of the band (always present)

  • ‘description’ - the string description of the band

  • ‘wavelength’ - a value-with-units for the spectral wavelength of the band. astropy.units is used to represent the values-with-units.

  • ‘wavelength_str’ - the string version of the band’s wavelength

  • ‘wavelength_units’ - the string version of the band’s wavelength-units value

Note that since both lists and dictionaries are mutable, care must be taken not to mutate the return-value of this method, as it will affect the data-set’s internal state.

set_band_list(band_list: List[Dict[str, Any]])[source]

This should ONLY be used for datasets that have NumPyRasterDataImpl as their impl type. This can be VERY destructive to metadata for other impl dataset types. Use with caution!

Args:
band_list (List[Dict[str, Any]]):

band_list should contain at least one of these keys: * ‘index’ - the integer index of the band (always present) * ‘description’ - the string description of the band * ‘wavelength’ - a value-with-units for the spectral wavelength of

the band. astropy.units is used to represent the values-with-units.

  • ‘wavelength_str’ - the string version of the band’s wavelength

  • ‘wavelength_units’ - the string version of the band’s wavelength-units value

set_band_descriptions(band_descriptions: List[str])[source]

This sets just the band description for all the bands in the dataset based on what is in band_descriptions list.

set_band_unit(unit: Unit)[source]

This should ONLY be used for datasets that have NumPyRasterDataImpl as their impl type. This can be destructive to metadata for other impl dataset types. Use with caution!

has_wavelengths()[source]

Returns True if all bands specify a wavelength (or some other unit that can be converted to wavelength); otherwise, returns False.

get_wavelengths() List[Quantity] | None[source]

Returns the wavelengths of the dataset if it has wavelengths.

default_display_bands() Tuple[int] | Tuple[int, int, int] | None[source]

Returns a tuple of integer indexes, specifying the default bands for display. If the list has 3 values, these are displayed using the red, green and blue channels of an image. If the list has 1 value, the band is displayed as grayscale.

If the raster data specifies no default bands, the return value is None.

get_data_ignore_value() int | float | None[source]

Returns the number that indicates a value to be ignored in the dataset. If this value is unknown or unspecified in the data, None is returned.

get_bad_bands() List[int] | None[source]

Returns a “bad band list” as a list of 0 or 1 integer values, with the same number of elements as the total number of bands in the dataset. A value of 0 means the band is “bad,” and a value of 1 means the band is “good.”

The returned list is a copy of the internal list; mutation on the returned list will not affect the raster data set.

get_image_data(filter_data_ignore_value=True)[source]

Returns a numpy 3D array of the entire image cube.

The numpy array is configured such that the pixel (x, y) values of band b are at element array[b][y][x].

If the data-set has a “data ignore value” and filter_data_ignore_value is also set to True, the array will be filtered such that any element with the “data ignore value” will be filtered to NaN. Note that this filtering will impact performance.

get_image_data_subset(x: int, y: int, band: int, dx: int, dy: int, dband: int, filter_data_ignore_value=True)[source]

Returns a 3D numpy array of values specified starting at x, y, and band and going until x+dx, y+dy, band+dband. The d variables are exclusive.

Data returned is in format arr[b][y][x]

get_band_data(band_index: int, filter_data_ignore_value=True) ndarray | MaskedArray[source]

Returns a numpy 2D array of the specified band’s data. The first band is at index 0.

The numpy array is configured such that the pixel (x, y) values are at element array[y][x].

If the data-set has a “data ignore value” and filter_data_ignore_value is also set to True, the array will be filtered such that any element with the “data ignore value” will be filtered to NaN. Note that this filtering will impact performance.

get_band_data_normalized(band_index: int, band_min=None, band_max=None, filter_data_ignore_value=True) ndarray | MaskedArray[source]

Returns a numpy 2D array of the specified band’s data. The first band is at index 0.

The numpy array is configured such that the pixel (x, y) values are at element array[y][x].

If the data-set has a “data ignore value” and filter_data_ignore_value is also set to True, the array will be filtered such that any element with the “data ignore value” will be filtered to NaN. Note that this filtering will impact performance.

sample_band_data(band_index: int, sample_factor: int, filter_data_ignore_value=True) ndarray | MaskedArray[source]

Returns a numpy 2D array of the specified band’s data. The first band is at index 0.

The numpy array is configured such that the pixel (x, y) values are at element array[y][x].

If the data-set has a “data ignore value” and filter_data_ignore_value is also set to True, the array will be filtered such that any element with the “data ignore value” will be filtered to NaN. Note that this filtering will impact performance.

get_multiple_band_data(band_list: List[int], filter_data_ignore_value=True)[source]

Returns a numpy 3D array of the specified images band data for all pixels in those bands. The numpy array is configured such that the pixel (x, y) for band b values are at element array[b][y][x]. If the data-set has a “data ignore value” and filter_data_ignore_value is also set to True, the array will be filtered such that any element with the “data ignore value” will be filtered to NaN. Note that this filtering will impact performance.

get_band_stats(band_index: int, band: ndarray | MaskedArray | None = None)[source]

Returns statistics of the specified band’s data, wrapped in a BandStats object.

get_all_bands_at(x: int, y: int, filter_bad_values=True)[source]

Returns a numpy 1D array of the values of all bands at the specified (x, y) coordinate in the raster data.

If filter_bad_values is set to True, bands that are marked as “bad” in the metadata will be set to NaN, and bands with the “data ignore value” will also be set to NaN.

get_all_bands_at_rect(x: int, y: int, dx: int, dy: int, filter_bad_values=True)[source]

Returns a numpy 2D array of the values of all bands at the specified rectangle in the raster data. If filter_bad_values is set to True, bands that are marked as “bad” in the metadata will be set to NaN, and bands with the “data ignore value” will also be set to NaN.

get_geo_transform() Tuple[source]

Returns the geographic transform for this dataset as a 6-tuple of floats. The geographic transform is used to map pixel coordinates to linear geographic coordinates, and is always an affine transformation. To map linear geographic coordinates into angular geographic coordinates, see the get_spatial_ref() method.

This value is always present; if the underlying data file doesn’t specify a geographic transform then an identity transformation is returned.

See https://gdal.org/tutorials/geotransforms_tut.html for more details on how to interpret this value.

get_spatial_ref() SpatialReference | None[source]

Returns the GDAL spatial reference system used for this dataset, or None if the dataset doesn’t have a spatial reference system.

cache_band_stats(index, arr: ndarray)[source]

Stores the band stats in this dataset’s cache for band stats

is_pixel_in_image_bounds(pixel: Tuple[int, int]) bool[source]

Checks to see if the pixel is in the bounds of the image.

The 0th index of pixel corresponds to the width (x-coordinate) and the 1st index corresponds to the height (y-coordinate). The coordinate (0, 0) is the top left most valid pixel.

Args:
  • pixel: The pixel that we want to know is inbounds or not

Returns:

True if the pixel is within the bounds of the image, False otherwise.

is_spatial_coord_in_spatial_bounds(spatial_coord: Tuple[float, float]) bool[source]

Checks to see if the spatial coordinate is in the spatial bounds of the image.

The 0th index of spatial_coord corresponds to the x coordinate in spatial terms, and the 1st index corresponds to the y coordinate. The spatial extent of the image is determined using self._geo_transform (as returned by GDAL’s GetGeoTransform) along with the image dimensions from self.get_width() (x direction) and self.get_height() (y direction).

Args:
  • spatial_coord: The spatial coordinate that we want to know is inbounds or not

Returns:

True if the spatial coordinate is within the spatial bounds of the image, False otherwise.

Tests to see if the passed in dataset is compatible to link with the current dataset

Args:
dataset (RasterDataSet):

The dataset that we want to determine our dataset’s link state with

Returns:

GeographicLinkState: 0 is no link, 1 is pixel link, 2 is spatial link

copy_spatial_metadata(source: SpatialMetadata) None[source]

Copy the spatial metadata from the SpatialMetadata object.

The spatial metadata includes the geographical transform, and the spatial reference system, if the raster has one. Any mutable values are deep-copied so that changes to the source’s information do not affect this object.

show_edit_dataset_dialog(app)[source]

Creates an edit dataset dialog menu. Should have a label at the top that says none of the changes persist on disk. THey only persist for this session.

Should have a section under this with a label

update_band_info(wavelengths: List[Quantity])[source]

Updates the band information for this dataset. Updates the units and the _band_info field. These changes do not persist across sessions.

static deserialize_into_class(dataset_serialize_value: str | ndarray, dataset_metadata: Dict) RasterDataSet[source]

We need to properly open up the dataset, if it is a subdataset, then we need to properly open that subdataset.

Args:
dataset_serialize_value (Union[str, np.ndarray]):

A string that represents the file path to the dataset, or a numpy array that represents the data in the dataset.

dataset_metadata (Dict):

A dictionary that represents the metadata needed to recreate this object.

Returns:

RasterDataSet: Takes the passed in parameters and reconstructs a dataset ojbect.

copy_serialized_metadata_from(dataset_metadata: Dict) None[source]

Copies the metadata from the dataset_metadata dictionary into this object. This is useful when reconstructing RasterDataSet objects meta data in another process. This is needed because the user can change the in memory copy of the RasterDataSet object and so if we reconstruct this object just from the impl dataset, we would not get this changed metadata.

get_serialized_form() SerializedForm[source]

Gives a tuple that represents all of the data needed to recreate this object. The first element is this class, so we can get the deserialize_into_class function The second element is a string that represents the file path to the dataset, or a numpy array that represents the data in the dataset. The third element is a dictionary that represents the metadata needed to recreate this object.

Making a Data Set from a NumPy Array

A data-set may be constructed from a NumPy array using the WISER data loader. See the section Loading Raster Data into WISER for more details.

Raster Data Bands

A single band of a raster data set may be represented by the RasterDataBand class. This class is a simple wrapper of a wiser.raster.RasterDataSet object, that also includes the index of the referenced band.

class wiser.raster.RasterDataBand(dataset: RasterDataSet, band_index: int)[source]

A helper class to represent a single band of a raster data set. This is a simple wrapper around class:RasterDataSet that also tracks a single band.

get_band_index() int[source]

Return the 0-based index of the band in the backing data set.

get_data(filter_data_ignore_value: bool = True) ndarray[source]

Returns a numpy 2D array of this band’s data.

The numpy array is configured such that the pixel (x, y) values are at element array[y][x].

If the data-set has a “data ignore value” and filter_data_ignore_value is also set to True, the array will be filtered such that any element with the “data ignore value” will be filtered to NaN. Note that this filtering will impact performance.

get_stats() BandStats[source]

Returns statistics of this band’s data, wrapped in a class:BandStats object.

static deserialize_into_class(band_index: int, band_metadata: Dict) RasterDataBand[source]

This should recreate the object from the serialized form that is obtained from the get_serialized_form method.

get_serialized_form() SerializedForm[source]

Gives a tuple that represents all of the data needed to recreate this object. The first element is this class, so we can get the deserialize_into_class function The second element is a string that represents the file path to the dataset, or a numpy array that represents the data in the dataset. The third element is a dictionary that represents the metadata needed to recreate this object.

Spectra

WISER has a rather complex class hierarchy to represent spectra, as they may come from pixels in a spectral image cube, they may be from a spectral library, they may be calculated from the area in a Region of Interest or the area around a pixel in an image, and so forth. The base-type of all these different kinds of spectra is the Spectrum class:

class wiser.raster.Spectrum[source]

The base class for representing spectra of interest to the user of the application.

get_source_name() str[source]

Returns the name of the spectrum’s source.

num_bands() int[source]

Returns the number of spectral bands in the spectrum.

get_bad_bands() ndarray[source]

Returns a boolean numpy array indicating which bands are bad (1 for bands to keep, 0 for bands to removed). If no bad bands are defined, returns None.

get_shape() Tuple[int][source]

Returns the shape of the spectrum. This is always simply (num_bands).

get_elem_type() dtype[source]

Returns the element-type of the spectrum.

has_wavelengths() bool[source]

Returns True if this spectrum has wavelength units for all bands, False otherwise.

get_wavelengths() List[Quantity][source]

Returns a list of wavelength values corresponding to each band. The individual values are astropy values-with-units.

get_wavelength_units() Unit | None[source]

Returns the astropy unit corresponding to the wavelength.

get_spectrum() ndarray[source]

Return the spectrum data as a 1D NumPy array.

get_serialized_form() SerializedForm[source]

This should return all of the information needed to recreate this object. The first element is this class, so we can get the deserialize_into_class function The second element is a string that represents the file path to the dataset, or a numpy array that represents the data in the dataset. The third element is a dictionary that represents the metadata needed to recreate this object.

static deserialize_into_class(spectrum_arr: str | ndarray, metadata: Dict) NumPyArraySpectrum[source]

This should recreate the object from the serialized form that is obtained from the get_serialized_form method.

Making a Spectrum from a NumPy Array

A spectrum may be constructed from a NumPy array using the NumPyArraySpectrum subclass:

class wiser.raster.NumPyArraySpectrum(arr: ndarray, name: str | None = None, source_name: str | None = None, wavelengths: List[Quantity] | None = None, editable=True, discardable=True)[source]

This class represents a spectrum that wraps a simple 1D NumPy array. This is generally used for computed spectra.

get_name() str | None[source]

Returns the current name of the spectrum, or None if no name has been assigned.

set_name(name: str | None)[source]

Sets the name of the spectrum. None may be specified if the spectrum is to be unnamed.

get_source_name() str | None[source]

Returns the name of the spectrum’s source, or None if no source name has been specified.

get_elem_type() dtype[source]

Returns the element-type of the spectrum.

num_bands() int[source]

Returns the number of spectral bands in the spectrum.

set_bad_bands(bad_bands: ndarray)[source]

Sets the bad bands array for this spectrum. 1 is keep, 0 is ignore.

get_bad_bands()[source]

Returns a boolean numpy array indicating which bands are bad (1 for bands to keep, 0 for bands to removed). If no bad bands are defined, returns None.

has_wavelengths() bool[source]

Returns True if this spectrum has wavelength units for all bands, False otherwise.

get_wavelengths() List[Quantity][source]

Returns a list of wavelength values corresponding to each band. The individual values are astropy values-with-units.

set_wavelengths(wavelengths: List[Quantity] | None)[source]

Sets the wavelength values that correspond to each band. The argument is a list of astropy values-with-units. Alternately, this method may be used to clear the wavelength information, by passing in None as the argument.

get_wavelength_units() Unit | None[source]

Returns the astropy unit corresponding to the wavelength.

get_spectrum() ndarray[source]

Return the spectrum data as a 1D NumPy array.

Region Of Interest

A region of interest that is draw on the screen is represented by the Region Of Interest class.

class wiser.raster.RegionOfInterest(name: str | None = None, color: str = 'yellow')[source]

Represents a Region of Interest (abbreviated “ROI”) in the data being analyzed. The Region of Interest may specify multiple selections of various types, indicating the actual area comprising the ROI. Various other attributes may be specified as well, such as the color that the ROI is drawn in.

get_id() int | None[source]
set_id(id: int) None[source]
get_name()[source]
set_name(name)[source]
get_color() str[source]

Returns the color of the ROI as a string.

set_color(color: str) None[source]
get_description() str | None[source]
set_description(description: str | None) None[source]
get_selections() List[Selection][source]
add_selection(selection: Selection) None[source]
del_selection(sel_index: int) None[source]
get_metadata()[source]
get_all_pixels() Set[Tuple[int, int]][source]

Return a Python set containing the coordinates of all pixels that are a part of this Region of Interest. Each pixel coordinate will only appear once, even if the pixel appears within multiple selections in the ROI.

get_bounding_box() QRect[source]
pprint()[source]

DynamicInputDialog

A utility for plugin developers to use to easily collect user input through a GUI.

class wiser.gui.ui_library.DynamicInputDialog(dialog_title: str | None = None, description: str | None = None, parent=None)[source]

This class lets plugin creators make a dialog with inputs that they can set!

You make use of this class by using the function create_input_dialog

create_input_dialog(inputs: List[Tuple[str, str, DynamicInputType, List[Any] | None]]) Dict[str, Any] | None[source]

Create and execute a dynamic input dialog.

Args:
inputs:

A list of tuples defining the requested inputs: [

(“<display name>”, “<return_key>”, DynamicInputType, [<combo_items> or None]), …

]

  • For DynamicInputType.COMBO_BOX:

    Provide a 4th element: a list of items for the combo box. No other DynamicInputTypes need this.

Returns:
Optional[Dict]:
  • On Accepted: { “<return_key>”: value, … }

  • On Rejected: None

DynamicInputType

class wiser.gui.ui_library.DynamicInputType(value)[source]

An enumeration.

COMBO_BOX = 0
FLOAT_NO_UNITS = 1
FLOAT_UNITS = 2
INT_NO_UNITS = 3
INT_UNITS = 4
STRING = 5

TableDisplayWidget

A utility for plugin developers to easily display information in a table.

class wiser.gui.ui_library.TableDisplayWidget(parent=None)[source]
create_table(header: List[str], rows: List[List[Any]], title: str | None = None, description: str | None = None)[source]

Creates a GUI item that has a description at the top and a QTableWidget with the specified header and the given rows. The table widget is only for display, so no interaction can be done.

Args:
header (List[str]):

A list of each of the column header names in order

rows (List[List[Any]]):

Each of the rows to put into the table in order. The elements in the outer list correspond to rows in the table. The elements in the inner list correspond to columns for that row.

description (str, optional):

Optional text placed above the table.

title (str, optional):

Optional title displayed above the description.

closeEvent(self, event: PySide2.QtGui.QCloseEvent) None[source]

MatplotlibDisplayWidget

A utility for plugin developers to easily display matplotlib plots.

class wiser.gui.ui_library.MatplotlibDisplayWidget(parent=None)[source]
create_plot(figure: Figure, axes: Axes, window_title: str | None = None, description: str | None = None)[source]

Creates a QWidget that containts the figure and axes passed in. You can optionally set the window title and provide a description.

closeEvent(self, event: PySide2.QtGui.QCloseEvent) None[source]