Skip to content

Commit 245d305

Browse files
authored
Merge pull request #218 from siapy/fix
2 parents e5b21c9 + 4a0fcf7 commit 245d305

15 files changed

+284
-221
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ imageset = SpectralImageSet.spy_open(
7575
print(imageset)
7676
```
7777

78-
For an overview of the key concepts and functionalities of the SiaPy library, please refer to the [documentation](https://siapy.github.io/siapy-lib/examples/introduction/). Additionally, explore the use cases that demonstrate the library's capabilities [here](https://siapy.github.io/siapy-lib/examples/use_cases/).
78+
For an overview of the key concepts and functionalities of the SiaPy library, please refer to the [documentation](https://siapy.github.io/siapy-lib/latest/concepts/overview/). Additionally, explore the use cases that demonstrate the library's capabilities [here](https://siapy.github.io/siapy-lib/latest/examples/case_study/).
7979

8080
## 🔍 Contribution guidelines
8181

@@ -89,7 +89,7 @@ Contributing to SiaPy isn’t limited to coding. You can also:
8989

9090
Not sure where to start or how your skills might fit in? Don’t hesitate to reach out! You can contact us via email, or connect with us directly on GitHub by opening a new issue or commenting on an existing one.
9191

92-
If you’re new to open-source contributions, check out our [guide](https://siapy.github.io/siapy-lib/contributing/) for helpful tips on getting started.
92+
If you’re new to open-source contributions, check out our [guide](https://siapy.github.io/siapy-lib/latest/contributing/) for helpful tips on getting started.
9393

9494
## 🕐 Issues and new features
9595

@@ -101,4 +101,4 @@ Have a question? First, ensure that the setup process was completed successfully
101101

102102
## 🤝 License
103103

104-
This project is licensed under the MIT License. See [LICENSE](https://siapy.github.io/siapy-lib/license/) for more details.
104+
This project is licensed under the MIT License. See [LICENSE](https://siapy.github.io/siapy-lib/latest/permit/) for more details.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
::: siapy.entities.shapes.geometric_shapes

docs/concepts/entities.md

Lines changed: 47 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -1,257 +1,103 @@
11
# Entities
22

3-
Entities form the core data structures in SiaPy that represent fundamental elements of spectral image processing. They provide consistent interfaces for working with various kinds of spectral data and spatial information.
3+
Entities serve as the foundational data structures in SiaPy, representing key elements of spectral image analysis and processing workflows. They implement consistent, strongly-typed interfaces that allow seamless interaction between spectral data, spatial coordinates, and geometric information.
44

5-
## Overview
5+
## Design principles
66

7-
The SiaPy Entities module defines a set of interconnected classes that represent the foundational building blocks for spectral image analysis:
7+
SiaPy's architecture follows several key design principles:
88

9-
- **SpectralImage**: A generic container for different types of hyperspectral/multispectral images
10-
- **SpectralImageSet**: A collection of spectral images
11-
- **Pixels**: Spatial coordinates within an image
12-
- **Signatures**: Spectral signals associated with specific pixel locations
13-
- **Shape**: Geometric shapes associated with image locations (points, lines, polygons)
9+
**Specialized yet compatible**: Each entity is optimized for its specific role while maintaining compatibility with the broader SiaPy ecosystem
1410

15-
These entity classes are designed to work together, forming a cohesive system for analyzing spectral imagery.
11+
**Independence**: Most entities can function independently (with the exception of abstract base classes)
1612

17-
## SpectralImage
13+
**Composition over inheritance**:
1814

19-
A `SpectralImage` is the primary container for spectral image data. It's a generic class that can wrap different image backends:
15+
- The composition is preferred, so that one class can leverage another by injecting it into its architecture
16+
- Inheritance is primarily used to implement common interfaces through base classes
2017

21-
```python
22-
from siapy.entities import SpectralImage
23-
24-
# Load from ENVI format
25-
image = SpectralImage.spy_open(
26-
header_path="path/to/header.hdr",
27-
image_path="path/to/image.img"
28-
)
18+
**Extensibility**:
2919

30-
# Load from GeoTIFF or other raster formats
31-
image = SpectralImage.rasterio_open(filepath="path/to/image.tif")
20+
- The `SpectralImage` class supports multiple data sources through *spectral* or *rasterio* libraries, however, custom data loading can be implemented by creating your own driver
21+
- Basic geometric shapes (e.g. points, lines, polygons) are implemented using the *shapely* library, which could also be extended through base abstraction
3222

33-
# Create from NumPy array
34-
import numpy as np
35-
array = np.zeros((100, 100, 10)) # height, width, bands
36-
image = SpectralImage.from_numpy(array)
37-
```
23+
The class structure is depicted in the following diagram:
3824

39-
### Key Properties
25+
![Entities Schematics](images/entities_schematics.png)
4026

41-
- **shape**: Dimensions as (height, width, bands)
42-
- **width**, **height**: Image dimensions
43-
- **bands**: Number of spectral bands
44-
- **wavelengths**: List of wavelength values for each band
45-
- **default_bands**: Default bands for RGB visualization
46-
- **metadata**: Dictionary of metadata from the image file
47-
- **filepath**: Path to the source file
48-
- **camera_id**: Camera identifier (if available)
49-
- **geometric_shapes**: Associated geometric shapes collection
27+
## Spectral Image
5028

51-
### Key Methods
29+
A `SpectralImage` is the primary container for spectral image data. It's a generic class that can wrap different image backends, allowing you to work with various file formats through a unified interface.
5230

53-
- **to_numpy()**: Convert to NumPy array
54-
- **to_display()**: Convert to PIL Image for visualization
55-
- **to_xarray()**: Convert to xarray.DataArray
56-
- **to_signatures()**: Extract signatures at specified pixels
57-
- **to_subarray()**: Extract a subarray for a region of interest
58-
- **average_intensity()**: Calculate mean intensity across specified axes
31+
### Image Initialization Options
5932

60-
## Pixels
33+
#### 1. Load from ENVI format (using spectral python)
6134

62-
The `Pixels` class represents spatial coordinates within an image, typically stored as x,y pairs.
35+
This is commonly used for hyperspectral imagery from airborne or satellite sensors.
6336

6437
```python
65-
from siapy.entities import Pixels
66-
67-
# Create from list of coordinates
68-
pixels = Pixels.from_iterable([(10, 20), (30, 40), (50, 60)])
69-
70-
# Load from parquet file
71-
pixels = Pixels.load_from_parquet("pixels.parquet")
38+
--8<-- "docs/concepts/src/spectral_image_01.py"
7239
```
7340

74-
### Key Properties
75-
76-
- **df**: Underlying pandas DataFrame with x,y coordinates
77-
- **coords**: Coordinate system definition
41+
#### 2. Load from GeoTIFF or other geospatial formats (using rasterio)
7842

79-
### Key Methods
80-
81-
- **x()**, **y()**: Access x and y coordinates as pandas Series
82-
- **to_numpy()**: Convert to NumPy array
83-
- **to_list()**: Convert to list of coordinates
84-
- **as_type()**: Convert coordinates to a specific data type
85-
- **get_coordinate()**: Get a specific coordinate pair
86-
- **df_homogenious()**: Get homogeneous coordinates (x,y,1)
87-
88-
## Signatures
89-
90-
The `Signatures` class combines `Pixels` with their corresponding spectral signals.
43+
Perfect for georeferenced data with spatial information.
9144

9245
```python
93-
from siapy.entities import Signatures, Pixels, Signals
94-
95-
# Create from pixels and signals
96-
pixels = Pixels.from_iterable([(10, 20), (30, 40)])
97-
signals_df = pd.DataFrame([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) # 2 pixels, 3 bands
98-
signals = Signals(signals_df)
99-
signatures = Signatures(pixels, signals)
100-
101-
# Extract signatures from an image at specific pixels
102-
pixels = Pixels.from_iterable([(10, 20), (30, 40)])
103-
signatures = spectral_image.to_signatures(pixels)
46+
--8<-- "docs/concepts/src/spectral_image_02.py"
10447
```
10548

106-
### Key Properties
49+
#### 3. Create from numpy array
10750

108-
- **pixels**: The `Pixels` object with coordinate information
109-
- **signals**: The `Signals` object with spectral values
110-
111-
### Key Methods
112-
113-
- **to_dataframe()**: Convert to a pandas DataFrame
114-
- **to_dataframe_multiindex()**: Convert to a DataFrame with MultiIndex columns
115-
- **to_numpy()**: Convert to tuple of NumPy arrays (pixels, signals)
116-
- **to_dict()**: Convert to dictionary representation
117-
- **reset_index()**: Reset DataFrame indices
118-
- **copy()**: Create a deep copy
119-
120-
## Signals
121-
122-
The `Signals` class represents spectral values associated with pixels.
51+
Useful for testing or when you already have image data in memory.
12352

12453
```python
125-
from siapy.entities.signatures import Signals
126-
127-
# Create from DataFrame
128-
signals_df = pd.DataFrame([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]]) # 2 pixels, 3 bands
129-
signals = Signals(signals_df)
130-
131-
# Create from iterable
132-
signals = Signals.from_iterable([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
54+
--8<-- "docs/concepts/src/spectral_image_03.py"
13355
```
13456

135-
### Key Properties
136-
137-
- **df**: Underlying pandas DataFrame with spectral values
138-
139-
### Key Methods
57+
#### 4. Create your own custom image class
14058

141-
- **to_numpy()**: Convert to NumPy array
142-
- **average_signal()**: Calculate mean signal across specified axis
143-
- **save_to_parquet()**: Save to parquet file
144-
145-
## Shape
146-
147-
The `Shape` class represents geometric shapes that can be associated with images, such as points, lines, and polygons.
59+
For specialized file formats or custom processing needs, you can extend the ImageBase class.
14860

14961
```python
150-
from siapy.entities import Shape
151-
from siapy.entities import Pixels
62+
--8<-- "docs/concepts/src/spectral_image_04.py"
63+
```
15264

153-
# Create a point
154-
point = Shape.from_point(10, 20)
65+
## Pixels
15566

156-
# Create a polygon from pixels
157-
pixels = Pixels.from_iterable([(0, 0), (10, 0), (10, 10), (0, 10)])
158-
polygon = Shape.from_polygon(pixels)
67+
The `Pixels` class represents spatial coordinates within spectral image, providing a container for *(x, y)* coordinate pairs. It uses pandas DataFrame internally for storage, enabling high-performance operations. The class provides multiple initialization methods and conversion functions to work with different data representations (i.e. DataFrames, list, arrays)
15968

160-
# Load from shapefile
161-
shape = Shape.open_shapefile("path/to/shapefile.shp")
69+
```python
70+
--8<-- "docs/concepts/src/pixels_01.py"
16271
```
16372

164-
### Shape Types
73+
## Signals
16574

166-
- **Point**: Single coordinate point (x,y)
167-
- **LineString**: Series of connected points forming a line
168-
- **Polygon**: Closed shape with interior area
169-
- **MultiPoint**: Collection of independent points
170-
- **MultiLineString**: Collection of independent lines
171-
- **MultiPolygon**: Collection of independent polygons
75+
The `Signals` class stores spectral data for each pixel in a pandas DataFrame, allowing you to use any column names you choose (e.g. "band_1", "nir", "red_edge"). You can initialize it from a DataFrame, lists, dicts or NumPy arrays.
17276

173-
### Key Properties
77+
```python
78+
--8<-- "docs/concepts/src/signals_01.py"
79+
```
17480

175-
- **geometry**: The underlying shapely geometry
176-
- **label**: Optional label for the shape
177-
- **shape_type**: Type of geometry (point, line, polygon, etc.)
178-
- **bounds**: Bounding box of the shape
179-
- **centroid**: Centroid point of the shape
81+
## Signatures
18082

181-
### Key Methods
83+
The `Signatures` class represents spectral data collections by combining spatial coordinates (`Pixels`) with their corresponding spectral values (`Signals`). It provides a unified container that maintains the spatial-spectral relationship, allowing for analysis of spectral information at specific image locations. Internally, the data is stored as pandas DataFrames for efficient operations and indexing.
18284

183-
- **buffer()**: Create a buffered version of the shape
184-
- **intersection()**: Find intersection with another shape
185-
- **union()**: Combine with another shape
186-
- **to_file()**: Save to a shapefile
85+
```python
86+
--8<-- "docs/concepts/src/signatures_01.py"
87+
```
18788

188-
## GeometricShapes
89+
## Shape
18990

190-
The `GeometricShapes` class manages a collection of shapes associated with a spectral image.
91+
The `Shape` class represents geometric shapes that can be associated with images, such as points, lines, and polygons.
19192

19293
```python
193-
# Access shapes associated with an image
194-
image = SpectralImage.spy_open(header_path="...", image_path="...")
195-
shapes = image.geometric_shapes
196-
197-
# Add a shape
198-
polygon = Shape.from_rectangle(10, 20, 30, 40)
199-
shapes.append(polygon)
200-
201-
# Find a shape by name
202-
shape = shapes.get_by_name("vegetation")
94+
--8<-- "docs/concepts/src/shapes_01.py"
20395
```
20496

205-
### Key Methods
206-
207-
- **append()**, **extend()**: Add shapes to the collection
208-
- **remove()**, **pop()**, **clear()**: Remove shapes
209-
- **index()**, **count()**: Find and count shapes
210-
- **get_by_name()**: Find a shape by its label
211-
21297
## SpectralImageSet
21398

21499
The `SpectralImageSet` class manages a collection of spectral images.
215100

216101
```python
217-
from siapy.entities import SpectralImageSet
218-
from pathlib import Path
219-
220-
# Load multiple images
221-
header_paths = list(Path("data_dir").glob("*.hdr"))
222-
image_paths = list(Path("data_dir").glob("*.img"))
223-
image_set = SpectralImageSet.spy_open(
224-
header_paths=header_paths,
225-
image_paths=image_paths
226-
)
227-
228-
# Access images
229-
first_image = image_set[0]
230-
231-
# Sort images
232-
image_set.sort()
102+
--8<-- "docs/concepts/src/spectral_image_set_01.py"
233103
```
234-
235-
### Key Properties
236-
237-
- **images**: List of SpectralImage objects
238-
- **cameras_id**: List of unique camera IDs
239-
240-
### Key Methods
241-
242-
- **images_by_camera_id()**: Get images from a specific camera
243-
- **sort()**: Sort the images
244-
245-
## Relationship Between Entities
246-
247-
The entities in SiaPy form a cohesive system:
248-
249-
1. A `SpectralImage` contains pixel data across multiple spectral bands
250-
2. `Pixels` represent spatial coordinates within that image
251-
3. `Signals` contain spectral values at those coordinates
252-
4. `Signatures` combine pixels and signals to represent spectral signatures at specific locations
253-
5. `Shape` objects define geometric regions in the image
254-
6. `GeometricShapes` organize multiple shapes associated with an image
255-
7. `SpectralImageSet` manages multiple related spectral images
256-
257-
This modular design allows for flexible workflows in spectral image analysis - from loading image data, to selecting regions of interest, to extracting and analyzing spectral signatures.
50.3 KB
Loading

docs/concepts/overview.md

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,7 @@
22

33
## Architecture
44

5-
SiaPy follows a modular architecture organized around key components that work together to provide a comprehensive toolkit for spectral image analysis:
6-
7-
``` sh
8-
siapy/
9-
├── core/ # Core functionality
10-
├── datasets/ # Dataset handling and management
11-
├── entities/ # Key data structures and representations
12-
├── features/ # Feature extraction and analysis
13-
├── optimizers/ # Optimization algorithms and machine learning
14-
├── transformations/ # Transformation operations
15-
└── utils/ # Utility functions and helpers
16-
```
17-
18-
## Core Components
5+
SiaPy follows a modular architecture organized around key components that work together to provide a comprehensive toolkit for spectral image analysis.
196

207
### Core (`siapy.core`)
218

@@ -30,8 +17,8 @@ The foundation of the library providing essential functionality:
3017

3118
Fundamental data structures that represent spectral imaging data:
3219

33-
- **SpectralImage**: An abstraction for various image formats
34-
- **SpectralImageSet**: Collection of spectral images with batch operations
20+
- **Spectral image**: An abstraction for various image formats
21+
- **Spectral image set**: Collection of spectral images with batch operations
3522
- **Pixels**: Representation of pixel coordinates and groups
3623
- **Shapes**: Geometric shapes for images' regions selection and masking
3724
- **Signatures**: Spectral signatures extracted from images

docs/concepts/src/pixels_01.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import numpy as np
2+
import pandas as pd
3+
4+
from siapy.entities import Pixels
5+
6+
# Create from pandas DataFrame
7+
pixels1 = Pixels(pd.DataFrame({"x": [10, 20, 30], "y": [40, 50, 60]}))
8+
9+
# Create from numpy array
10+
pixels2 = Pixels.from_iterable(np.array([[10, 40], [20, 50], [30, 60]]))
11+
12+
# Create from list of coordinates
13+
pixels3 = Pixels.from_iterable([(10, 40), (20, 50), (30, 60)])
14+
15+
# Should be the same
16+
assert pixels1 == pixels2 == pixels3

docs/concepts/src/shapes_01.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from siapy.entities import Pixels, Shape
2+
3+
# Create a point
4+
point = Shape.from_point(10, 20)
5+
6+
# Create a polygon from pixels
7+
pixels = Pixels.from_iterable([(0, 0), (10, 0), (10, 10), (0, 10)])
8+
polygon = Shape.from_polygon(pixels)
9+
10+
# Load from shapefile
11+
shape = Shape.open_shapefile("path/to/shapefile.shp")

docs/concepts/src/signals_01.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from siapy.entities.signatures import Signals
2+
3+
signals = Signals.from_iterable([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])

0 commit comments

Comments
 (0)