Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Code Style and Standards

### General Principles

- Write clean, readable, and maintainable code
- Write self-documenting code with clear variable and function names
- Suggest improvements to code style, efficiency, and readability in pull
request reviews

### PEP 8 Compliance

- Follow [PEP 8](https://peps.python.org/pep-0008/) style guide for all Python code
Expand Down Expand Up @@ -42,6 +49,7 @@
#### Docstrings

- Use **Google Style** docstrings for all public functions, classes, and methods
- Don't add the args and return types in the docstring if they are already specified in the type hints.
- Format:

```python
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ reset_project.sh
.envrc
aimbat.log
.env
aimbat_test.log
12 changes: 0 additions & 12 deletions docs/api/cli.md

This file was deleted.

17 changes: 1 addition & 16 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,4 @@
show_root_toc_entry: true
inherited_members: true
show_submodules: true
members:
- config
- logger
summary: false
::: aimbat.cli
options:
heading_level: 2
show_root_heading: true
show_root_toc_entry: true
inherited_members: true
show_submodules: false
summary:
<!-- classes: true -->
<!-- attributes: true -->
<!-- functions: true -->
modules: true
summary: true
12 changes: 0 additions & 12 deletions docs/api/lib.md

This file was deleted.

90 changes: 44 additions & 46 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,54 @@
};

outputs = {
self,
nixpkgs,
systems,
nixgl,
...
}:
let
eachSystem = nixpkgs.lib.genAttrs (import systems);
}: let
eachSystem = nixpkgs.lib.genAttrs (import systems);
in {
devShells = eachSystem (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [nixgl.overlay];
};
in {
devShells = eachSystem (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [nixgl.overlay];
};
in {
default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
uv
ruff
(python314.withPackages (ps: with ps; [tox]))
python313
python312
gnumake
sqlitebrowser
];
default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
uv
ruff
(python314.withPackages (ps: with ps; [tox]))
python313
python312
gnumake
sqlitebrowser
];

shellHook = ''
export LD_LIBRARY_PATH=${with pkgs;
lib.makeLibraryPath [
stdenv.cc.cc.lib
zlib
zstd
libX11
libGL
glib
libxkbcommon
fontconfig
freetype
dbus
wayland
]}:$LD_LIBRARY_PATH
export UV_PYTHON=$(which python3.14)
export UV_NO_MANAGED_PYTHON=true
[ ! -d .venv ] && uv venv --system-site-packages
uv sync --locked --all-extras
export MPLBACKEND=QtAgg
source .venv/bin/activate
'';
};
});
formatter = eachSystem (system: (import nixpkgs {inherit system;}).nixpkgs-fmt);
};
shellHook = ''
export LD_LIBRARY_PATH=${with pkgs;
lib.makeLibraryPath [
stdenv.cc.cc.lib
zlib
zstd
libX11
libGL
glib
libxkbcommon
fontconfig
freetype
dbus
wayland
]}:$LD_LIBRARY_PATH
export UV_PYTHON=$(which python3.14)
export UV_NO_MANAGED_PYTHON=true
[ ! -d .venv ] && uv venv --system-site-packages
uv sync --locked --all-extras
export MPLBACKEND=QtAgg
source .venv/bin/activate
'';
};
});
formatter = eachSystem (system: (import nixpkgs {inherit system;}).nixpkgs-fmt);
};
}
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ dependencies = [
"pyqtgraph>=0.13.7",
"cyclopts>=3.24.0",
"pydantic-settings>=2.10.1",
"pandas>=3.0.1",
"pandas-stubs>=3.0.0.260204",
]

[project.urls]
Expand Down
2 changes: 2 additions & 0 deletions src/aimbat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@

"""

from ._config import settings as settings

name = "aimbat"
43 changes: 30 additions & 13 deletions src/aimbat/config.py → src/aimbat/_config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""Global configuration options for the AIMBAT application."""

from aimbat.lib._validators import EventParametersValidatorMixin
from aimbat._lib._mixins import EventParametersValidatorMixin
from aimbat.aimbat_types import PydanticNegativeTimedelta, PydanticPositiveTimedelta
from pysmo.tools.iccs._defaults import ICCS_DEFAULTS
from pydantic import Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from pathlib import Path
from datetime import timedelta
from pysmo.tools.iccs._defaults import ICCS_DEFAULTS
from typing import Self
from typing import Literal, Self
import numpy as np


Expand All @@ -28,26 +28,43 @@ class Settings(EventParametersValidatorMixin, BaseSettings):
logfile: Path = Field(default=Path("aimbat.log"), description="Log file location.")
"""Log file location."""

debug: bool = Field(default=False, description="Enable debug logging.")
"""Enable debug logging."""
log_level: Literal[
"TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL"
] = Field(
default="INFO",
description=(
"Logging level. "
"Valid levels (from most to least verbose): "
"TRACE, DEBUG, INFO, SUCCESS, WARNING, ERROR, CRITICAL."
),
)
"""Logging level.

Valid loguru levels, from most to least verbose:

window_pre: timedelta = Field(
- ``TRACE``
- ``DEBUG``
- ``INFO``
- ``SUCCESS``
- ``WARNING``
- ``ERROR``
- ``CRITICAL``
"""

window_pre: PydanticNegativeTimedelta = Field(
default=ICCS_DEFAULTS.window_pre,
lt=0,
description="Initial relative begin time of window.",
)
"""Initial relative begin time of window."""

window_post: timedelta = Field(
window_post: PydanticPositiveTimedelta = Field(
default=ICCS_DEFAULTS.window_post,
ge=0,
description="Initial relative end time of window.",
)
"""Initial relative end time of window."""

context_width: timedelta = Field(
context_width: PydanticPositiveTimedelta = Field(
default=ICCS_DEFAULTS.context_width,
gt=0,
description="Context padding to apply before and after the time window.",
)
"""Context padding to apply before and after the time window."""
Expand Down Expand Up @@ -116,7 +133,7 @@ def set_computed_defaults(self) -> Self:

def print_settings_table(pretty: bool) -> None:
"""Print a pretty table with AIMBAT configuration options."""
from aimbat.lib.common import make_table, TABLE_STYLING
from aimbat.utils import make_table, TABLE_STYLING
from rich.console import Console

env_prefix = Settings.model_config.get("env_prefix")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import Self
from pydantic import BaseModel, model_validator
from typing import Self


class EventParametersValidatorMixin(BaseModel):
Expand Down
15 changes: 15 additions & 0 deletions src/aimbat/_lib/validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from pandas import Timedelta


def must_be_negative_pd_timedelta(v: Timedelta) -> Timedelta:
"""Validator to ensure a Timedelta is negative."""
if v.total_seconds() >= 0:
raise ValueError(f"Duration must be negative, got {v}")
return v


def must_be_positive_pd_timedelta(v: Timedelta) -> Timedelta:
"""Validator to ensure a Timedelta is positive."""
if v.total_seconds() <= 0:
raise ValueError(f"Duration must be positive, got {v}")
return v
20 changes: 20 additions & 0 deletions src/aimbat/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
def export_module_names(globals_dict: dict, module_name: str) -> None:
"""
Updates the __module__ attribute of all objects in __all__ to match
the current module name.

Args:
globals_dict: The globals() dictionary of the calling module.
module_name: The name of the calling module (usually __name__).
"""
all_names = globals_dict.get("__all__", [])

for name in all_names:
obj = globals_dict.get(name)
if obj is not None and hasattr(obj, "__module__"):
try:
# Attempt to write the module name
obj.__module__ = module_name
except (AttributeError, TypeError):
# Safely ignore objects with read-only __module__ attributes
pass
17 changes: 17 additions & 0 deletions src/aimbat/aimbat_types/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# flake8: noqa: E402, F403
"""Custom types used in AIMBAT."""

from .._utils import export_module_names

_internal_names = set(dir())

from ._data import *
from ._event import *
from ._pydantic import *
from ._seismogram import *

__all__ = [s for s in dir() if not s.startswith("_") and s not in _internal_names]

export_module_names(globals(), __name__)

del _internal_names
11 changes: 11 additions & 0 deletions src/aimbat/aimbat_types/_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from enum import StrEnum, auto

__all__ = [
"DataType",
]


class DataType(StrEnum):
"""Valid AIMBAT data types."""

SAC = auto()
22 changes: 1 addition & 21 deletions src/aimbat/lib/typing.py → src/aimbat/aimbat_types/_event.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"""Custom types used in AIMBAT."""

from typing import Literal
from enum import StrEnum, auto

Expand Down Expand Up @@ -35,22 +33,4 @@ class EventParameter(StrEnum):
type EventParameterTimedelta = Literal[
EventParameter.WINDOW_PRE, EventParameter.WINDOW_POST
]
"[`TypeAlias`][typing.TypeAlias] for [`AimbatEvent`][aimbat.lib.models.AimbatEvent] attributes with [`timedelta`][datetime.timedelta] values."


class SeismogramParameter(StrEnum):
"""[`AimbatSeismograParameters`][aimbat.lib.models.AimbatSeismogramParameters] enum class for typing.

This enum class is used for typing, cli args etc. The attributes must be
the same as in the [`AimbatParameters`][aimbat.lib.models.AimbatParameters] model.
"""

SELECT = auto()
FLIP = auto()
T1 = auto()


type SeismogramParameterBool = Literal[
SeismogramParameter.SELECT, SeismogramParameter.FLIP
]
type SeismogramParameterDatetime = Literal[SeismogramParameter.T1]
"[`TypeAlias`][typing.TypeAlias] for [`AimbatEvent`][aimbat.lib.models.AimbatEvent] attributes with [`Timedelta`][pandas.Timedelta] values."
Loading
Loading