Skip to content

Commit

Permalink
Merge pull request #53 from siapy/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
janezlapajne authored Jul 4, 2024
2 parents 59d975c + 6a65658 commit 712ca83
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Closes organization/repo#number

<!-- List issues for GitHub to automatically close after merge to default branch. Type `#` and select from the list. See the [GitHub docs on linking PRs to issues](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) for more. -->

- [ ] I have reviewed the [Guidelines for Contributing](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md).
- [ ] I have reviewed the [Guidelines for Contributing](../CONTRIBUTING.md) and the [Code of Conduct](../CODE_OF_CONDUCT.md).
2 changes: 1 addition & 1 deletion .github/workflows/gitleaks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
name: gitleaks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ jobs:
contents: read
id-token: write
steps:
- uses: actions/checkout@v3
- uses: pdm-project/setup-pdm@v3
- uses: actions/checkout@v4
- uses: pdm-project/setup-pdm@v4
with:
version: "head"
- name: Publish package distributions to PyPI
Expand Down
File renamed without changes.
File renamed without changes.
38 changes: 38 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Security Policy

Security is very important for SiaPy and its community. 🔒

Learn more about it below. 👇

## Versions

The latest version of SiaPy is supported.

You are encouraged to update your SiaPy version frequently. This way you will benefit from the latest features, bug fixes, and **security fixes**.

## Reporting a Vulnerability

We take the security of our project seriously. If you have discovered a security vulnerability, we appreciate your cooperation in disclosing it to us in a responsible manner.

Please report any security vulnerabilities by emailing us at [[email protected]]([email protected]).

We will acknowledge receipt of your vulnerability report, assess it for validity and severity, and decide on the next steps. We ask that you do not publicly disclose the vulnerability until we have had a chance to address it.

## What to include in your report

To help us triage and prioritize the issue, please include as much information as possible, such as:

- The version of our project you are using
- A step-by-step description of how to reproduce the vulnerability
- Any relevant logs or output
- Any other information you think might be relevant

## Public Discussions

Please refrain from publicly discussing a potential security vulnerability.

Discussing vulnerabilities in public forums before they are properly assessed and fixed can significantly increase the risk to the project and its users. It's better to discuss issues privately and work together to find a solution first, to limit the potential impact as much as possible. We appreciate your cooperation and understanding in handling sensitive matters with discretion.

---

Thank you for helping to keep SiaPy and its users safe. 🏅
10 changes: 2 additions & 8 deletions siapy/entities/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
from .containers import (
SpectralImageContainer,
SpectralImageContainerConfig,
SpectralImageMultiCameraContainer,
)
from .images import SpectralImage
from .imagesets import SpectralImageSet
from .pixels import Pixels
from .shapes import Shape
from .signatures import Signatures

__all__ = [
"SpectralImage",
"SpectralImageContainer",
"SpectralImageContainerConfig",
"SpectralImageMultiCameraContainer",
"SpectralImageSet",
"Pixels",
"Signatures",
"Shape",
Expand Down
84 changes: 0 additions & 84 deletions siapy/entities/containers.py

This file was deleted.

50 changes: 42 additions & 8 deletions siapy/entities/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ def __str__(self) -> str:

@classmethod
def envi_open(
cls, *, hdr_path: str | Path, img_path: str | Path | None = None
cls, *, header_path: str | Path, image_path: str | Path | None = None
) -> "SpectralImage":
sp_file = sp.envi.open(file=hdr_path, image=img_path)
sp_file = sp.envi.open(file=header_path, image=image_path)
if isinstance(sp_file, sp.io.envi.SpectralLibrary):
raise ValueError("Opened file of type SpectralLibrary")
return cls(sp_file)
Expand Down Expand Up @@ -165,18 +165,23 @@ def bands(self) -> int:

@property
def default_bands(self) -> list[int]:
if "default bands" not in self.metadata.keys():
return []
db = self.metadata["default bands"]
db = self.metadata.get("default bands", [])
return list(map(int, db))

@property
def wavelengths(self) -> list[float]:
if "wavelength" not in self.metadata.keys():
return []
wavelength_data = self.metadata["wavelength"]
wavelength_data = self.metadata.get("wavelength", [])
return list(map(float, wavelength_data))

@property
def description(self) -> dict[str, Any]:
description_str = self.metadata.get("description", {})
return _parse_description(description_str)

@property
def camera_id(self) -> str:
return self.description.get("ID", "")

@property
def geometric_shapes(self) -> GeometricShapes:
return self._geometric_shapes
Expand Down Expand Up @@ -212,3 +217,32 @@ def _remove_nan(self, image: np.ndarray, nan_value: float = 0.0) -> np.ndarray:
image_mask = np.bitwise_not(np.bool_(np.isnan(image).sum(axis=2)))
image[~image_mask] = nan_value
return image


def _parse_description(description: str) -> dict[str, Any]:
def _parse():
data_dict = {}
for line in description.split("\n"):
key, value = line.split("=", 1)
key = key.strip()
value = value.strip()
if "," in value: # Special handling for values with commas
value = [
float(v) if v.replace(".", "", 1).isdigit() else v
for v in value.split(",")
]
elif value.isdigit():
value = int(value)
elif value.replace(".", "", 1).isdigit():
value = float(value)
data_dict[key] = value
return data_dict

try:
return _parse()
except ValueError as e:
raise ValueError(f"Error parsing description: {e}") from e
except KeyError as e:
raise KeyError(f"Missing key in description: {e}") from e
except Exception as e:
raise Exception(f"Unexpected error parsing description: {e}") from e
59 changes: 59 additions & 0 deletions siapy/entities/imagesets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from dataclasses import dataclass
from pathlib import Path
from typing import Iterator

from rich.progress import track

from siapy.core import logger

from .images import SpectralImage


@dataclass
class SpectralImageSet:
def __init__(self, spectral_images: list[SpectralImage] | None = None):
self._images = spectral_images if spectral_images is not None else []

def __len__(self) -> int:
return len(self.images)

def __str__(self) -> str:
return f"<{self.__class__.__name__} object with {len(self)} spectral images>"

def __iter__(self) -> Iterator[SpectralImage]:
return iter(self.images)

def __getitem__(self, index) -> SpectralImage:
return self.images[index]

@classmethod
def from_paths(
cls,
*,
header_paths: list[str | Path],
image_paths: list[str | Path] | None = None,
):
if image_paths is not None and len(header_paths) != len(image_paths):
raise ValueError("The length of hdr_paths and img_path must be equal.")

if image_paths is None:
spectral_images = [
SpectralImage.envi_open(header_path=hdr_path)
for hdr_path in track(
header_paths, description="Loading spectral images..."
)
]
else:
spectral_images = [
SpectralImage.envi_open(header_path=hdr_path, image_path=img_path)
for hdr_path, img_path in track(
zip(header_paths, image_paths),
description="Loading spectral images...",
)
]
logger.info("Spectral images loaded into memory.")
return cls(spectral_images)

@property
def images(self) -> list[SpectralImage]:
return self._images
2 changes: 1 addition & 1 deletion siapy/utils/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def accept(event):
enter_clicked = 1
plt.close()

LassoSelector(ax, onselect)
lasso = LassoSelector(ax, onselect) # noqa: F841
fig.canvas.mpl_connect("button_release_event", onrelease)
fig.canvas.mpl_connect("close_event", onexit)
fig.canvas.mpl_connect("key_press_event", accept)
Expand Down
Loading

0 comments on commit 712ca83

Please sign in to comment.