Skip to content

Spectral Library

siapy.entities.images.spectral_lib

SpectralLibImage dataclass

SpectralLibImage(file: SpectralLibType)

Bases: ImageBase

PARAMETER DESCRIPTION
file

A SpectralPython file object representing the opened spectral image.

TYPE: SpectralLibType

Source code in siapy/entities/images/spectral_lib.py
26
27
28
29
30
31
32
33
34
35
def __init__(
    self,
    file: "SpectralLibType",
):
    """Initialize a SpectralLibImage wrapper around a SpectralPython file object.

    Args:
        file: A SpectralPython file object representing the opened spectral image.
    """
    self._file = file

file property

Get the underlying SpectralPython file object.

RETURNS DESCRIPTION
SpectralLibType

The wrapped SpectralPython file object.

filepath property

filepath: Path

Get the file path of the spectral image.

RETURNS DESCRIPTION
Path

A Path object representing the location of the image file.

metadata property

metadata: dict[str, Any]

Get the image metadata from the ENVI header.

RETURNS DESCRIPTION
dict[str, Any]

A dictionary containing image metadata such as coordinate reference system, wavelength information, and other image properties from the ENVI header.

shape property

shape: tuple[int, int, int]

Get the dimensions of the spectral image.

RETURNS DESCRIPTION
tuple[int, int, int]

A tuple (rows, samples, bands) representing the image dimensions.

rows property

rows: int

Get the number of rows (height) in the image.

RETURNS DESCRIPTION
int

The number of rows in the spectral image.

cols property

cols: int

Get the number of columns (width) in the image.

RETURNS DESCRIPTION
int

The number of columns in the spectral image.

bands property

bands: int

Get the number of spectral bands in the image.

RETURNS DESCRIPTION
int

The number of spectral bands (channels) in the image.

default_bands property

default_bands: list[int]

Get the default band indices for RGB display.

RETURNS DESCRIPTION
list[int]

A list of 0-based band indices from the ENVI metadata, typically used for red, green, and blue channels when displaying the image as an RGB composite. These indices are extracted from the "default bands" field in the ENVI header file.

Note

Unlike rasterio which uses 1-based indexing, SpectralPython uses 0-based indexing for band access. The returned indices can be used directly with numpy array indexing.

wavelengths property

wavelengths: list[float]

Get the wavelengths corresponding to each spectral band.

RETURNS DESCRIPTION
list[float]

A list of wavelength values (typically in nanometers) for each band as stored in the ENVI metadata. The length equals the number of bands.

description property

description: dict[str, Any]

Get parsed description metadata from the ENVI header.

RETURNS DESCRIPTION
dict[str, Any]

A dictionary containing parsed key-value pairs from the description field in the ENVI metadata, with automatic type conversion for numeric values and comma-separated lists.

camera_id property

camera_id: str

Get the camera or sensor identifier from the description metadata.

RETURNS DESCRIPTION
str

A string identifying the camera or sensor used to capture the image, extracted from the "ID" field in the parsed description metadata.

open classmethod

open(
    *,
    header_path: str | Path,
    image_path: str | Path | None = None,
) -> SpectralLibImage

Open a spectral image using the SpectralPython ENVI library.

PARAMETER DESCRIPTION
header_path

Path to the ENVI header file (.hdr) containing image metadata.

TYPE: str | Path

image_path

Optional path to the image data file. If None, the path is inferred from the header file.

TYPE: str | Path | None DEFAULT: None

RETURNS DESCRIPTION
SpectralLibImage

A SpectralLibImage instance wrapping the opened spectral file.

RAISES DESCRIPTION
InvalidFilepathError

If the header file path does not exist.

InvalidInputError

If the file cannot be opened or if it's a SpectralLibrary instead of an Image.

Example
# Open an ENVI format image
image = SpectralLibImage.open(header_path="image.hdr")

# Open with explicit image file path
image = SpectralLibImage.open(
    header_path="image.hdr",
    image_path="image.dat"
)
Source code in siapy/entities/images/spectral_lib.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@classmethod
def open(cls, *, header_path: str | Path, image_path: str | Path | None = None) -> "SpectralLibImage":
    """Open a spectral image using the SpectralPython ENVI library.

    Args:
        header_path: Path to the ENVI header file (.hdr) containing image metadata.
        image_path: Optional path to the image data file. If None, the path is inferred from the header file.

    Returns:
        A SpectralLibImage instance wrapping the opened spectral file.

    Raises:
        InvalidFilepathError: If the header file path does not exist.
        InvalidInputError: If the file cannot be opened or if it's a SpectralLibrary instead of an Image.

    Example:
        ```python
        # Open an ENVI format image
        image = SpectralLibImage.open(header_path="image.hdr")

        # Open with explicit image file path
        image = SpectralLibImage.open(
            header_path="image.hdr",
            image_path="image.dat"
        )
        ```
    """
    header_path = Path(header_path)
    if not header_path.exists():
        raise InvalidFilepathError(header_path)

    try:
        sp_file = sp.envi.open(file=header_path, image=image_path)
    except Exception as e:
        raise InvalidInputError({"filepath": str(header_path)}, f"Failed to open spectral file: {e}") from e

    if isinstance(sp_file, sp.io.envi.SpectralLibrary):
        raise InvalidInputError({"file_type": type(sp_file).__name__}, "Expected Image, got SpectralLibrary")

    return cls(sp_file)

to_display

to_display(equalize: bool = True) -> Image

Convert the image to a PIL Image for display purposes.

PARAMETER DESCRIPTION
equalize

Whether to apply histogram equalization to enhance contrast. Defaults to True.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
Image

A PIL Image object suitable for display, created from the default RGB bands with normalized values and optional histogram equalization.

Example
# Display the image with default settings
pil_image = spectral_image.to_display()
pil_image.show()

# Display without histogram equalization
pil_image = spectral_image.to_display(equalize=False)
Source code in siapy/entities/images/spectral_lib.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
def to_display(self, equalize: bool = True) -> Image.Image:
    """Convert the image to a PIL Image for display purposes.

    Args:
        equalize: Whether to apply histogram equalization to enhance contrast. Defaults to True.

    Returns:
        A PIL Image object suitable for display, created from the default RGB bands with normalized values and optional histogram equalization.

    Example:
        ```python
        # Display the image with default settings
        pil_image = spectral_image.to_display()
        pil_image.show()

        # Display without histogram equalization
        pil_image = spectral_image.to_display(equalize=False)
        ```
    """
    max_uint8 = 255.0
    image_3ch = self.file.read_bands(self.default_bands)
    image_3ch = self._remove_nan(image_3ch, nan_value=0)
    image_3ch[:, :, 0] = image_3ch[:, :, 0] / image_3ch[:, :, 0].max() / max_uint8
    image_3ch[:, :, 1] = image_3ch[:, :, 1] / (image_3ch[:, :, 1].max() / max_uint8)
    image_3ch[:, :, 2] = image_3ch[:, :, 2] / (image_3ch[:, :, 2].max() / max_uint8)
    image = Image.fromarray(image_3ch.astype("uint8"))
    if equalize:
        image = ImageOps.equalize(image)
    return image

to_numpy

to_numpy(
    nan_value: float | None = None,
) -> NDArray[floating[Any]]

Convert the image to a numpy array.

PARAMETER DESCRIPTION
nan_value

Optional value to replace NaN values with. If None, NaN values are preserved.

TYPE: float | None DEFAULT: None

RETURNS DESCRIPTION
NDArray[floating[Any]]

A 3D numpy array with shape (rows, cols, bands) containing the spectral data.

Example
# Get the raw data with NaN values preserved
data = spectral_image.to_numpy()

# Replace NaN values with zero
data = spectral_image.to_numpy(nan_value=0.0)
Source code in siapy/entities/images/spectral_lib.py
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
def to_numpy(self, nan_value: float | None = None) -> NDArray[np.floating[Any]]:
    """Convert the image to a numpy array.

    Args:
        nan_value: Optional value to replace NaN values with. If None, NaN values are preserved.

    Returns:
        A 3D numpy array with shape (rows, cols, bands) containing the spectral data.

    Example:
        ```python
        # Get the raw data with NaN values preserved
        data = spectral_image.to_numpy()

        # Replace NaN values with zero
        data = spectral_image.to_numpy(nan_value=0.0)
        ```
    """
    image = self.file[:, :, :]
    if nan_value is not None:
        image = self._remove_nan(image, nan_value)
    return image

to_xarray

to_xarray() -> XarrayType

Convert the image to an xarray DataArray.

RETURNS DESCRIPTION
XarrayType

An xarray DataArray with labeled dimensions (y, x, band) and coordinates, including wavelength information and metadata attributes.

Example
# Convert to xarray for analysis
xr_data = spectral_image.to_xarray()

# Access specific bands or wavelengths
red_band = xr_data.sel(band=650, method='nearest')
Source code in siapy/entities/images/spectral_lib.py
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def to_xarray(self) -> "XarrayType":
    """Convert the image to an xarray DataArray.

    Returns:
        An xarray DataArray with labeled dimensions (y, x, band) and coordinates, including wavelength information and metadata attributes.

    Example:
        ```python
        # Convert to xarray for analysis
        xr_data = spectral_image.to_xarray()

        # Access specific bands or wavelengths
        red_band = xr_data.sel(band=650, method='nearest')
        ```
    """
    data = self._file[:, :, :]
    xarray = xr.DataArray(
        data,
        dims=["y", "x", "band"],
        coords={
            "y": np.arange(self.rows),
            "x": np.arange(self.cols),
            "band": self.wavelengths,
        },
        attrs=self._file.metadata,
    )
    return xarray