Skip to content

Commit

Permalink
fix: FiberFUsing API update
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinPdeS committed Oct 23, 2024
1 parent 7d35485 commit 42b4831
Show file tree
Hide file tree
Showing 29 changed files with 1,689 additions and 954 deletions.
11 changes: 11 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[flake8]
max-line-length = 300
exclude =
.git
docs/build
docs/source/gallery
development

count = true
per-file-ignores =
__init__.py: F403, F401
1 change: 0 additions & 1 deletion SuPyMode/directories.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
'root_path',
'project_path',
'test_path',
'instance_directory',
'version_path',
'validation_data_path',
'doc_path',
Expand Down
78 changes: 78 additions & 0 deletions SuPyMode/helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from typing import Callable
from MPSPlots.styles import mps
import matplotlib.pyplot as plt
from SuPyMode.utils import interpret_mode_of_interest


def singular_plot_helper(function: Callable) -> Callable:
def wrapper(self, ax: plt.Axes = None, show: bool = True, mode_of_interest: str = 'all', **kwargs) -> plt.Figure:
if ax is None:
with plt.style.context(mps):
figure, ax = plt.subplots(1, 1)

mode_of_interest = interpret_mode_of_interest(superset=self, mode_of_interest=mode_of_interest)

function(self, ax=ax, mode_of_interest=mode_of_interest, **kwargs)

_, labels = ax.get_legend_handles_labels()

# Only add a legend if there are labels
if labels:
ax.legend()

if show:
plt.show()

return figure

return wrapper


def combination_plot_helper(function: Callable) -> Callable:
def wrapper(self, ax: plt.Axes = None, show: bool = True, mode_of_interest: str = 'all', combination: str = 'pairs', **kwargs) -> plt.Figure:
if ax is None:
with plt.style.context(mps):
figure, ax = plt.subplots(1, 1)

mode_of_interest = interpret_mode_of_interest(superset=self, mode_of_interest=mode_of_interest)

combination = self.interpret_combination(mode_of_interest=mode_of_interest, combination=combination)

function(self, ax=ax, mode_of_interest=mode_of_interest, combination=combination, **kwargs)

_, labels = ax.get_legend_handles_labels()

# Only add a legend if there are labels
if labels:
ax.legend()

if show:
plt.show()

return figure

return wrapper


def parse_mode_of_interest(plot_function: Callable) -> Callable:
def wrapper(self, *args, mode_of_interest='all', **kwargs):
mode_of_interest = interpret_mode_of_interest(
superset=self,
mode_of_interest=mode_of_interest
)

return plot_function(self, *args, mode_of_interest=mode_of_interest, **kwargs)

return wrapper


def parse_combination(plot_function: Callable) -> Callable:
def wrapper(self, *args, mode_of_interest='all', combination: str = 'pairs', **kwargs):
combination = self.interpret_combination(
mode_of_interest=mode_of_interest,
combination=combination
)

return plot_function(self, *args, mode_of_interest=mode_of_interest, combination=combination, **kwargs)

return wrapper
202 changes: 123 additions & 79 deletions SuPyMode/mode_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,126 +2,170 @@
# -*- coding: utf-8 -*-

from PyFinitDiff.finite_difference_2D import Boundaries
from enum import Enum


mode_dict = [
{'mode': (0, 1, ""), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (1, 1, r"_a"), 'x': 'symmetric', 'y': 'anti-symmetric'},
{'mode': (1, 1, "_b"), 'x': 'anti-symmetric', 'y': 'symmetric'},
{'mode': (2, 1, "_a"), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (2, 1, "_b"), 'x': 'anti-symmetric', 'y': 'anti-symmetric'},
{'mode': (0, 2, ""), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (3, 1, "_a"), 'x': 'symmetric', 'y': 'anti-symmetric'},
{'mode': (3, 1, "_b"), 'x': 'anti-symmetric', 'y': 'symmetric'},
{'mode': (1, 2, "_a"), 'x': 'symmetric', 'y': 'anti-symmetric'},
{'mode': (1, 2, "_b"), 'x': 'anti-symmetric', 'y': 'symmetric'},
{'mode': (4, 1, "_a"), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (4, 1, "_b"), 'x': 'anti-symmetric', 'y': 'anti-symmetric'},
{'mode': (2, 2, "_a"), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (2, 2, "_b"), 'x': 'anti-symmetric', 'y': 'anti-symmetric'},
{'mode': (0, 3, ""), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (5, 1, "_a"), 'x': 'symmetric', 'y': 'anti-symmetric'},
{'mode': (5, 1, "_b"), 'x': 'anti-symmetric', 'y': 'symmetric'},
{'mode': (3, 2, "_a"), 'x': 'symmetric', 'y': 'anti-symmetric'},
{'mode': (3, 2, "_b"), 'x': 'anti-symmetric', 'y': 'symmetric'},
{'mode': (1, 3, "_a"), 'x': 'symmetric', 'y': 'anti-symmetric'},
{'mode': (1, 3, "_b"), 'x': 'anti-symmetric', 'y': 'symmetric'},
{'mode': (6, 1, "_a"), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (6, 1, "_b"), 'x': 'anti-symmetric', 'y': 'anti-symmetric'},
{'mode': (4, 2, "_a"), 'x': 'symmetric', 'y': 'symmetric'},
{'mode': (4, 2, "_b"), 'x': 'anti-symmetric', 'y': 'anti-symmetric'},
]
class Parity(Enum):
SYMMETRIC = 'symmetric'
ANTI_SYMMETRIC = 'anti-symmetric'
ZERO = 'zero'


mode_dict = []


for azimuthal, radial in [(0, 1), (1, 1), (2, 1), (0, 2), (3, 1), (1, 2), (4, 1), (2, 2), (0, 3), (5, 1), (3, 2), (1, 3), (6, 1), ]:

if azimuthal == 0:
parities = [[Parity.SYMMETRIC.value, Parity.SYMMETRIC.value]]
sublabels = ['']

elif azimuthal % 2 == 1:
parities = [
[Parity.ANTI_SYMMETRIC.value, Parity.SYMMETRIC.value],
[Parity.SYMMETRIC.value, Parity.ANTI_SYMMETRIC.value],
]
sublabels = ['_a', '_b']

elif azimuthal % 2 == 0:
parities = [
[Parity.SYMMETRIC.value, Parity.SYMMETRIC.value],
[Parity.ANTI_SYMMETRIC.value, Parity.ANTI_SYMMETRIC.value],
]
sublabels = ['_a', '_b']

for (x_parity, y_parity), sublabel in zip(parities, sublabels):

mode = dict(mode=(azimuthal, radial, sublabel), x=x_parity, y=y_parity)

mode_dict.append(mode)


class ModeLabel:
"""
A class to represent the LP mode label of an optical fiber based on boundary conditions and mode number.
Attributes:
boundaries (Boundaries): The boundary conditions for the mode.
mode_number (int): The mode number.
x_parity (str): The parity in the x direction (symmetric, anti-symmetric, or zero).
y_parity (str): The parity in the y direction (symmetric, anti-symmetric, or zero).
azimuthal (int): The azimuthal mode number.
radial (int): The radial mode number.
sub_label (str): The sub-label for the mode.
Represents the LP mode label of an optical fiber based on boundary conditions and mode number.
The `ModeLabel` class encapsulates information about the optical mode based on the boundary conditions
of an optical fiber. It calculates and assigns labels such as `LP01`, `LP11_a`, etc., depending on the
given boundary conditions and mode number.
Parameters
----------
boundaries : Boundaries
The boundary conditions for the mode, indicating symmetries in different directions.
mode_number : int
The mode number to label, corresponding to the specific optical mode.
Attributes
----------
boundaries : Boundaries
The boundary conditions for the mode.
mode_number : int
The mode number to label.
x_parity : str
The parity in the x direction (symmetric, anti-symmetric, or zero).
y_parity : str
The parity in the y direction (symmetric, anti-symmetric, or zero).
azimuthal : int or None
The azimuthal mode number, extracted from the filtered mode list.
radial : int or None
The radial mode number, extracted from the filtered mode list.
sub_label : str or None
The sub-label for the mode, such as `_a` or `_b`.
raw_label : str
The base LP label without the sub-label.
label : str
The full LP label for the mode, including the sub-label.
"""

def __init__(self, boundaries: Boundaries, mode_number: int):
"""
Initializes the ModeLabel with given boundary conditions and mode number.
Args:
boundaries (Boundaries): The boundary conditions.
mode_number (int): The mode number.
Initializes the `ModeLabel` instance with given boundary conditions and mode number.
Parameters
----------
boundaries : Boundaries
The boundary conditions indicating symmetries in the left, right, top, and bottom directions.
mode_number : int
The mode number, used to identify the optical mode.
"""
self.boundaries = boundaries
self.mode_number = mode_number

self.initialize()

def initialize(self) -> None:
self.x_parity = self._get_x_parity()
self.y_parity = self._get_y_parity()
"""
Initialize and calculate the mode label based on boundary conditions and mode number.
This method sets the `x_parity` and `y_parity` based on the boundary conditions, filters the
mode list, and assigns appropriate labels for azimuthal and radial modes.
"""
self.x_parity = self._get_parity(self.boundaries.left, self.boundaries.right)
self.y_parity = self._get_parity(self.boundaries.top, self.boundaries.bottom)

filtered_modes = self.get_filtered_mode_list()

if self.mode_number >= len(filtered_modes):
self.azimuthal, self.radial, self.sub_label = None, None, None
self.raw_label = f"Mode{self.mode_number}"
self.label = self.raw_label
raise ValueError(f"Mode number {self.mode_number} exceeds available modes. Max allowed: {len(filtered_modes) - 1}")

else:
self.azimuthal, self.radial, self.sub_label = filtered_modes[self.mode_number]
self.raw_label = f"LP{self.azimuthal}{self.radial}"
self.label = f"{self.raw_label}{self.sub_label}"
self.azimuthal, self.radial, self.sub_label = filtered_modes[self.mode_number]
self.raw_label = f"LP{self.azimuthal}{self.radial}"
self.label = f"{self.raw_label}{self.sub_label}"

def get_filtered_mode_list(self) -> list[tuple]:
return [m['mode'] for m in mode_dict if self.x_parity in [m['x'], 'zero'] and self.y_parity in [m['y'], 'zero']]

def _get_x_parity(self) -> str:
"""
Determines the parity in the x direction based on boundary conditions.
Filters the list of available modes based on the x and y parity conditions.
Returns:
str: The x parity (symmetric, anti-symmetric, or zero).
Returns
-------
list of tuple
A list of filtered modes that match the specified x and y parity conditions.
"""
if self.boundaries.left == 'symmetric' or self.boundaries.right == 'symmetric':
return 'symmetric'
elif self.boundaries.left == 'anti-symmetric' or self.boundaries.right == 'anti-symmetric':
return 'anti-symmetric'
else:
return 'zero'
return [m['mode'] for m in mode_dict if self.x_parity in [m['x'], Parity.ZERO.value] and self.y_parity in [m['y'], Parity.ZERO.value]]

def _get_y_parity(self) -> str:
def _get_parity(self, boundary_1: str, boundary_2: str) -> str:
"""
Determines the parity in the y direction based on boundary conditions.
Returns:
str: The y parity (symmetric, anti-symmetric, or zero).
Determines the parity in a direction based on boundary conditions.
Parameters
----------
boundary_1 : str
The boundary condition for one side (e.g., left or top).
boundary_2 : str
The boundary condition for the opposite side (e.g., right or bottom).
Returns
-------
str
The parity ('symmetric', 'anti-symmetric', or 'zero').
"""
if self.boundaries.top == 'symmetric' or self.boundaries.bottom == 'symmetric':
return 'symmetric'
elif self.boundaries.top == 'anti-symmetric' or self.boundaries.bottom == 'anti-symmetric':
return 'anti-symmetric'
if Parity.SYMMETRIC.value in (boundary_1, boundary_2):
return Parity.SYMMETRIC.value
elif Parity.ANTI_SYMMETRIC.value in (boundary_1, boundary_2):
return Parity.ANTI_SYMMETRIC.value
else:
return 'zero'
return Parity.ZERO.value

def __repr__(self) -> str:
"""
Returns the string representation of the ModeLabel.
Returns the string representation of the `ModeLabel`.
Returns:
str: The LP mode label.
Returns
-------
str
The LP mode label, including the azimuthal and radial information.
"""
return self.label

def __str__(self) -> str:
"""
Returns the string representation of the ModeLabel.
Returns the string representation of the `ModeLabel`.
Returns:
str: The LP mode label.
Returns
-------
str
The LP mode label.
"""
return self.__repr__()

Expand Down
1 change: 0 additions & 1 deletion SuPyMode/profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
strict=True,
arbitrary_types_allowed=True,
kw_only=True,
frozen=True
)


Expand Down
Loading

0 comments on commit 42b4831

Please sign in to comment.