Je propose d’ajouter des opérations de dilatation/érosion et de morphologie simple (ouverture/fermeture) pour les objets portion.Interval. L’objectif est de permettre des extensions ou réductions d’intervalles directement via apply tout en restant cohérent avec l’esprit de portion.
Motivation :
Actuellement, il n’existe pas d’API native pour décaler facilement les bornes d’un intervalle de manière abstraite (temps, distance, etc.). L’implémentation proposée s’appuie sur apply, ce qui reste simple et performant.
Points clés :
- L’érosion est obtenue via dilate_intervals avec magnitude < 0.
- Ouverture/fermeture morphologique = deux dilatations successives.
- Conserve la simplicité et la flexibilité de portion tout en ajoutant des fonctionnalités utiles.
Questions / discussion :
- Serait-il pertinent d’ajouter ces méthodes directement à l’API Interval ?
-Devrait-on prévoir des tests unitaires spécifiques pour ces nouvelles opérations ?
import portion as P
from portion import Interval, closed
from datetime import timedelta
##### Dilatation (et érosion via magnitude négative) #####
def _shift_interval(interval: Interval, magnitude: float, bound: str):
"""Décale un intervalle selon la magnitude et le côté choisi.
Parameters
----------
interval : Interval
Intervalle à décaler.
magnitude : float
Quantité de décalage (abstraite, e.g., temps, distance...).
bound : str
Côté à décaler : 'both', 'low', ou 'high'.
Returns
-------
Interval
L'intervalle décalé.
"""
if bound == "both":
return closed(interval.lower - magnitude, interval.upper + magnitude)
elif bound == "low":
return closed(interval.lower - magnitude, interval.upper)
elif bound == "high":
return closed(interval.lower, interval.upper + magnitude)
else:
raise ValueError(f"Invalid value for 'bound': {bound!r}. Expected 'both', 'low', or 'high'.")
def dilate_intervals(intervals: Interval, magnitude: int | float, bound: str = "both") -> Interval:
"""Applique une dilatation (ou érosion si magnitude négative) à un ensemble d'intervalles.
Parameters
----------
intervals : Interval
Collection d'intervalles à modifier.
magnitude : float
Quantité de dilatation (positive) ou d'érosion (négative).
bound : str, optional
Côté à modifier : 'both', 'low', ou 'high'. Par défaut 'both'.
Returns
-------
Interval
Les intervalles modifiés.
"""
if not isinstance(magnitude, (int, float, timedelta)):
raise TypeError(f"'magnitude' must be numeric, not {type(magnitude).__name__}.")
return intervals.apply(lambda x: _shift_interval(x, magnitude, bound))
##### Opérations morphologiques simplifiées #####
def open_intervals(interval: Interval, magnitude: int | float) -> Interval:
"""Ouverture morphologique : érosion puis dilatation."""
# open = dilate(dilate(interval, -magnitude), +magnitude)
result = dilate_intervals(dilate_intervals(interval, -magnitude), +magnitude)
valid_intervals = P.empty()
for inter in result:
if inter.lower < inter.upper:
valid_intervals |= P.closed(inter.lower, inter.upper)
return valid_intervals
def close_intervals(interval: Interval, magnitude: int | float) -> Interval:
"""Fermeture morphologique : dilatation puis érosion."""
# close = dilate(dilate(interval, +magnitude), -magnitude)
result = dilate_intervals(dilate_intervals(interval, +magnitude), -magnitude)
valid_intervals = P.empty()
for inter in result:
if inter.lower < inter.upper:
valid_intervals |= P.closed(inter.lower, inter.upper)
return valid_intervals
Je propose d’ajouter des opérations de dilatation/érosion et de morphologie simple (ouverture/fermeture) pour les objets portion.Interval. L’objectif est de permettre des extensions ou réductions d’intervalles directement via apply tout en restant cohérent avec l’esprit de portion.
Motivation :
Actuellement, il n’existe pas d’API native pour décaler facilement les bornes d’un intervalle de manière abstraite (temps, distance, etc.). L’implémentation proposée s’appuie sur apply, ce qui reste simple et performant.
Points clés :
Questions / discussion :
-Devrait-on prévoir des tests unitaires spécifiques pour ces nouvelles opérations ?