Skip to content

Commit

Permalink
doc(ruff): #81 comply with pydocstyle (D) (#88)
Browse files Browse the repository at this point in the history
* chore(ruff): #81 update

* chore: #81 enable most of D rules

* doc: #81 comply with ruff D rules. Work in progress.

* doc(pendulum): #81 D100, D101, D103

* doc(pytest): #81 D100

* doc: #81 D101

* doc: #81 D104

* doc: #81 D103

* doc: #81 D102

* chore(pyproject): #81 ignore D100 for tutorials
  • Loading branch information
cmp0xff authored Aug 31, 2024
1 parent 9222420 commit 1947407
Show file tree
Hide file tree
Showing 29 changed files with 327 additions and 64 deletions.
1 change: 1 addition & 0 deletions hamilflow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Hamilflow package."""
5 changes: 5 additions & 0 deletions hamilflow/maths/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Package for mathematical functions."""

from .trigonometrics import acos_with_shift

__all__ = ["acos_with_shift"]
3 changes: 3 additions & 0 deletions hamilflow/maths/trigonometrics.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Trigonometric functions."""

from typing import TYPE_CHECKING

import numpy as np
Expand All @@ -12,6 +14,7 @@ def acos_with_shift(
x: "Collection[float] | npt.ArrayLike",
shift: "Collection[float] | npt.ArrayLike | None" = None,
) -> "npt.ArrayLike":
"""Arccos with shift."""
x = np.array(x, copy=False)
value = np.arccos(x)
shift = np.array(shift, copy=False)
Expand Down
1 change: 1 addition & 0 deletions hamilflow/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Package for the models."""
34 changes: 18 additions & 16 deletions hamilflow/models/brownian_motion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module for Brownian motion."""

from functools import cached_property
from typing import Mapping, Sequence

Expand All @@ -11,7 +13,7 @@


class BrownianMotionSystem(BaseModel):
r"""Definition of the Brownian Motion system
r"""Definition of the Brownian Motion system.
For consistency, we always use
$\mathbf x$ for displacement, and
Expand All @@ -24,8 +26,8 @@ class BrownianMotionSystem(BaseModel):
\end{align}
$$
References:
References
----------
1. Brownian motion and random walks. [cited 13 Mar 2024].
Available: https://web.mit.edu/8.334/www/grades/projects/projects17/OscarMickelin/brownian.html
2. Contributors to Wikimedia projects. Brownian motion.
Expand All @@ -35,6 +37,7 @@ class BrownianMotionSystem(BaseModel):
:cvar sigma: base standard deviation
to be used to compute the variance
:cvar delta_t: time granunality of the motion
"""

sigma: float = Field(ge=0.0)
Expand All @@ -43,14 +46,12 @@ class BrownianMotionSystem(BaseModel):
@computed_field # type: ignore[misc]
@cached_property
def gaussian_scale(self) -> float:
"""The scale (standard deviation) of the Gaussian term
in Brownian motion
"""
"""The scale (standard deviation) of the Gaussian term in Brownian motion."""
return self.sigma**2 * self.delta_t


class BrownianMotionIC(BaseModel):
"""The initial condition for a Brownian motion
"""The initial condition for a Brownian motion.
:cvar x0: initial displacement of the particle,
the diminsion of this initial condition determines
Expand All @@ -61,7 +62,7 @@ class BrownianMotionIC(BaseModel):

@field_validator("x0")
@classmethod
def check_x0_types(cls, v: float | Sequence[float]) -> float | Sequence[float]:
def _check_x0_types(cls, v: float | Sequence[float]) -> float | Sequence[float]:
if not isinstance(v, (float, int, Sequence)):
# TODO I do not think this raise can be reached
raise ValueError(f"Value of x0 should be int/float/list of int/float: {v=}")
Expand All @@ -70,8 +71,8 @@ def check_x0_types(cls, v: float | Sequence[float]) -> float | Sequence[float]:


class BrownianMotion:
r"""Brownian motion describes motion of small particles
with stochastic forces applied to them.
r"""Brownian motion describes motion of small particles with stochastic forces applied to them.
The math of Brownian motion can be modeled
with Wiener process.
Expand All @@ -86,8 +87,8 @@ class BrownianMotion:
\end{align}
$$
References:
References
----------
1. Brownian motion and random walks. [cited 13 Mar 2024].
Available: https://web.mit.edu/8.334/www/grades/projects/projects17/OscarMickelin/brownian.html
2. Contributors to Wikimedia projects. Brownian motion.
Expand Down Expand Up @@ -142,6 +143,7 @@ class BrownianMotion:
:param system: the Brownian motion system definition
:param initial_condition: the initial condition for the simulation
"""

def __init__(
Expand All @@ -157,15 +159,15 @@ def __init__(

@property
def dim(self) -> int:
"""Dimension of the Brownian motion"""
"""Dimension of the Brownian motion."""
return np.array(self.initial_condition.x0, copy=False).size

@property
def _axis_names(self) -> list[str]:
return [f"x_{i}" for i in range(self.dim)]

def _trajectory(self, n_new_steps: int, seed: int) -> "npt.NDArray[np.float64]":
"""The trajectory of the particle.
"""Give the trajectory of the particle.
We first compute the delta displacement in each step.
With the displacement at each step, we perform a cumsum
Expand All @@ -189,7 +191,7 @@ def _trajectory(self, n_new_steps: int, seed: int) -> "npt.NDArray[np.float64]":
return trajectory

def generate_from(self, n_steps: int, seed: int = 42) -> pd.DataFrame:
"""generate data from a set of interpretable params for this model
"""Generate data from a set of interpretable params for this model.
:param n_steps: total number of steps to be simulated, including the inital step.
:param seed: random generator seed for the stochastic process.
Expand All @@ -200,7 +202,7 @@ def generate_from(self, n_steps: int, seed: int = 42) -> pd.DataFrame:
return self(t=time_steps, seed=seed)

def __call__(self, t: TypeTime, seed: int = 42) -> pd.DataFrame:
"""Simulate the coordinates of the particle
"""Simulate the coordinates of the particle.
:param t: the time sequence to be used to generate data, 1-D array like
:param seed: random generator seed for the stochastic process.
Expand Down
9 changes: 5 additions & 4 deletions hamilflow/models/free_particle.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module for a free particle."""

from functools import cached_property
from typing import Mapping, Sequence, cast

Expand All @@ -13,7 +15,7 @@


class FreeParticleIC(BaseModel):
"""The initial condition for a free particle
"""The initial condition for a free particle.
:cvar x0: the initial displacement
:cvar v0: the initial velocity
Expand All @@ -23,7 +25,7 @@ class FreeParticleIC(BaseModel):
v0: float | Sequence[float] = Field()

@model_validator(mode="after")
def check_dimensions_match(self) -> Self:
def _check_dimensions_match(self) -> Self:
if (x0_seq := isinstance(self.x0, Sequence)) != isinstance(self.v0, Sequence):
raise TypeError("x0 and v0 need both to be scalars or Sequences")
elif x0_seq and len(cast(Sequence, self.x0)) != len(cast(Sequence, self.v0)):
Expand All @@ -46,7 +48,7 @@ def __init__(

@cached_property
def definition(self) -> dict[str, dict[str, float | list[float]]]:
"""model params and initial conditions defined as a dictionary."""
"""Model params and initial conditions defined as a dictionary."""
return dict(initial_condition=self.initial_condition.model_dump())

def _x(self, t: "Sequence[float] | npt.ArrayLike") -> "npt.NDArray[np.float64]":
Expand All @@ -60,7 +62,6 @@ def __call__(self, t: "Sequence[float] | npt.ArrayLike") -> pd.DataFrame:
:param t: time(s).
"""

data = self._x(t)
columns = [f"x{i+1}" for i in range(data.shape[1])]

Expand Down
38 changes: 18 additions & 20 deletions hamilflow/models/harmonic_oscillator.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module for undamped and damped hamornic oscillators."""

from abc import ABC, abstractmethod
from functools import cached_property
from typing import Literal, Mapping, Sequence
Expand All @@ -9,7 +11,7 @@


class HarmonicOscillatorSystem(BaseModel):
"""The params for the harmonic oscillator
"""The params for the harmonic oscillator.
:cvar omega: angular frequency of the harmonic oscillator
:cvar zeta: damping ratio
Expand All @@ -21,21 +23,21 @@ class HarmonicOscillatorSystem(BaseModel):
@computed_field # type: ignore[misc]
@cached_property
def period(self) -> float:
"""period of the oscillator"""
"""Period of the oscillator."""
return 2 * np.pi / self.omega

@computed_field # type: ignore[misc]
@cached_property
def frequency(self) -> float:
"""frequency of the oscillator"""
"""Frequency of the oscillator."""
return 1 / self.period

@computed_field # type: ignore[misc]
@cached_property
def type(
self,
) -> Literal["simple", "under_damped", "critical_damped", "over_damped"]:
"""which type of harmonic oscillators"""
"""Which type of harmonic oscillators."""
if self.zeta == 0:
return "simple"
elif self.zeta < 1:
Expand All @@ -47,15 +49,15 @@ def type(

@field_validator("zeta")
@classmethod
def check_zeta_non_negative(cls, v: float) -> float:
def _check_zeta_non_negative(cls, v: float) -> float:
if v < 0:
raise ValueError(f"Value of zeta should be positive: {v=}")

return v


class HarmonicOscillatorIC(BaseModel):
"""The initial condition for a harmonic oscillator
"""The initial condition for a harmonic oscillator.
:cvar x0: the initial displacement
:cvar v0: the initial velocity
Expand All @@ -68,8 +70,7 @@ class HarmonicOscillatorIC(BaseModel):


class HarmonicOscillatorBase(ABC):
r"""Base class to generate time series data
for a [harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator).
r"""Base class to generate time series data for a [harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator).
:param system: all the params that defines the harmonic oscillator.
:param initial_condition: the initial condition of the harmonic oscillator.
Expand All @@ -86,7 +87,7 @@ def __init__(

@cached_property
def definition(self) -> dict[str, dict[str, float]]:
"""model params and initial conditions defined as a dictionary."""
"""Model params and initial conditions defined as a dictionary."""
return {
"system": self.system.model_dump(),
"initial_condition": self.initial_condition.model_dump(),
Expand Down Expand Up @@ -114,9 +115,7 @@ def __call__(self, n_periods: int, n_samples_per_period: int) -> pd.DataFrame:


class SimpleHarmonicOscillator(HarmonicOscillatorBase):
r"""Generate time series data for a
[simple harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator).
r"""Generate time series data for a [simple harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator).
In a one dimensional world, a mass $m$, driven by a force $F=-kx$, is described as
Expand Down Expand Up @@ -163,7 +162,7 @@ def __init__(
)

def _x(self, t: "Sequence[float] | npt.ArrayLike") -> np.ndarray:
r"""Solution to simple harmonic oscillators:
r"""Solution to simple harmonic oscillators.
$$
x(t) = x_0 \cos(\omega t + \phi).
Expand Down Expand Up @@ -236,7 +235,7 @@ def __init__(
)

def _x_under_damped(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayLike:
r"""Solution to under damped harmonic oscillators:
r"""Solution to under damped harmonic oscillators.
$$
x(t) = \left( x_0 \cos(\Omega t) + \frac{\zeta \omega x_0 + v_0}{\Omega} \sin(\Omega t) \right)
Expand All @@ -262,7 +261,7 @@ def _x_under_damped(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayLike
) * np.exp(-self.system.zeta * self.system.omega * t)

def _x_critical_damped(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayLike:
r"""Solution to critical damped harmonic oscillators:
r"""Solution to critical damped harmonic oscillators.
$$
x(t) = \left( x_0 \cos(\Omega t) + \frac{\zeta \omega x_0 + v_0}{\Omega} \sin(\Omega t) \right)
Expand All @@ -281,7 +280,7 @@ def _x_critical_damped(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayL
)

def _x_over_damped(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayLike:
r"""Solution to over harmonic oscillators:
r"""Solution to over harmonic oscillators.
$$
x(t) = \left( x_0 \cosh(\Gamma t) + \frac{\zeta \omega x_0 + v_0}{\Gamma} \sinh(\Gamma t) \right)
Expand Down Expand Up @@ -325,7 +324,7 @@ def _x(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayLike:


class ComplexSimpleHarmonicOscillatorIC(BaseModel):
"""The initial condition for a complex harmonic oscillator
"""The initial condition for a complex harmonic oscillator.
:cvar x0: the initial displacements
:cvar phi: initial phases
Expand Down Expand Up @@ -360,15 +359,14 @@ def __init__(
def definition(
self,
) -> dict[str, dict[str, float | tuple[float, float]]]:
"""model params and initial conditions defined as a dictionary."""

"""Model params and initial conditions defined as a dictionary."""
return dict(
system=self.system.model_dump(),
initial_condition=self.initial_condition.model_dump(),
)

def _z(self, t: "Sequence[float] | npt.ArrayLike") -> npt.ArrayLike:
r"""Solution to complex simple harmonic oscillators:
r"""Solution to complex simple harmonic oscillators.
$$
x(t) = x_+ \exp(-\mathbb{i} (\omega t + \phi_+)) + x_- \exp(+\mathbb{i} (\omega t + \phi_-)).
Expand Down
7 changes: 4 additions & 3 deletions hamilflow/models/harmonic_oscillator_chain.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Main module for a harmonic oscillator chain."""

from functools import cached_property
from typing import Mapping, Sequence, cast

Expand All @@ -11,8 +13,7 @@


class HarmonicOscillatorsChain:
r"""Generate time series data for a coupled harmonic oscillator chain
with periodic boundary condition.
r"""Generate time series data for a coupled harmonic oscillator chain with periodic boundary condition.
A one-dimensional circle of $N$ interacting harmonic oscillators can be described by the Lagrangian action
$$S_L[x_i] = \int_{t_0}^{t_1}\mathbb{d} t \left\{ \sum_{i=0}^{N-1} \frac{1}{2}m \dot x_i^2 - \frac{1}{2}m\omega^2\left(x_i - x_{i+1}\right)^2 \right\}\,,$$
Expand Down Expand Up @@ -81,7 +82,7 @@ def definition(
| dict[str, dict[str, float | list[float]]]
| list[dict[str, dict[str, float | tuple[float, float]]]],
]:
"""model params and initial conditions defined as a dictionary."""
"""Model params and initial conditions defined as a dictionary."""
return dict(
omega=self.omega,
n_dof=self.n_dof,
Expand Down
2 changes: 2 additions & 0 deletions hamilflow/models/kepler_problem/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Package for the Kepler problem."""

from .model import Kepler2D, Kepler2DIoM, Kepler2DSystem

__all__ = ["Kepler2D", "Kepler2DIoM", "Kepler2DSystem"]
Loading

0 comments on commit 1947407

Please sign in to comment.