FiberFusing 1.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of FiberFusing might be problematic. Click here for more details.
- fiberfusing-1.3.4/FiberFusing/VERSION +1 -0
- fiberfusing-1.3.4/FiberFusing/__init__.py +79 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/background.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/base_fused.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/buffer.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/connection.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/coordinate_system.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/geometry.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/__pycache__/utils.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/background.py +88 -0
- fiberfusing-1.3.4/FiberFusing/base_fused.py +510 -0
- fiberfusing-1.3.4/FiberFusing/buffer.py +95 -0
- fiberfusing-1.3.4/FiberFusing/components/__init__.py +0 -0
- fiberfusing-1.3.4/FiberFusing/components/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/components/__pycache__/base_class.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/components/__pycache__/linestring.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/components/__pycache__/point.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/components/__pycache__/polygon.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/components/__pycache__/utils.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/components/base_class.py +161 -0
- fiberfusing-1.3.4/FiberFusing/components/linestring.py +117 -0
- fiberfusing-1.3.4/FiberFusing/components/point.py +105 -0
- fiberfusing-1.3.4/FiberFusing/components/polygon.py +443 -0
- fiberfusing-1.3.4/FiberFusing/components/utils.py +59 -0
- fiberfusing-1.3.4/FiberFusing/configuration/__init__.py +7 -0
- fiberfusing-1.3.4/FiberFusing/configuration/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__init__.py +10 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__pycache__/configuration_01x01.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__pycache__/configuration_02x02.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__pycache__/configuration_03x03.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__pycache__/configuration_04x04.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/__pycache__/configuration_05x05.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/configuration_01x01.py +30 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/configuration_02x02.py +37 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/configuration_03x03.py +36 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/configuration_04x04.py +36 -0
- fiberfusing-1.3.4/FiberFusing/configuration/line/configuration_05x05.py +36 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__init__.py +15 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_01x01.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_02x02.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_03x03.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_04x04.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_05x05.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_06x06.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_07x07.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_10x10.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_12x12.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/__pycache__/configuration_19x19.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_01x01.py +30 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_02x02.py +35 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_03x03.py +43 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_04x04.py +43 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_05x05.py +43 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_06x06.py +43 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_07x07.py +44 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_10x10.py +50 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_12x12.py +55 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/configuration_19x19.py +57 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/mode_groupe_pl_6.py +48 -0
- fiberfusing-1.3.4/FiberFusing/configuration/ring/scaling_photonic_lantern_10.py +56 -0
- fiberfusing-1.3.4/FiberFusing/connection.py +340 -0
- fiberfusing-1.3.4/FiberFusing/coordinate_system.py +165 -0
- fiberfusing-1.3.4/FiberFusing/directories.py +42 -0
- fiberfusing-1.3.4/FiberFusing/fiber/__init__.py +0 -0
- fiberfusing-1.3.4/FiberFusing/fiber/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/fiber/__pycache__/catalogue.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/fiber/__pycache__/generic_fiber.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/fiber/__pycache__/structure_collection.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/fiber/catalogue.py +131 -0
- fiberfusing-1.3.4/FiberFusing/fiber/generic_fiber.py +406 -0
- fiberfusing-1.3.4/FiberFusing/fiber/structure_collection.py +173 -0
- fiberfusing-1.3.4/FiberFusing/geometry.py +342 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/__init__.py +0 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/__pycache__/base_class.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/__pycache__/line.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/__pycache__/ring.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/base_class.py +139 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/line.py +78 -0
- fiberfusing-1.3.4/FiberFusing/sub_structures/ring.py +75 -0
- fiberfusing-1.3.4/FiberFusing/utility/__init__.py +0 -0
- fiberfusing-1.3.4/FiberFusing/utility/__pycache__/__init__.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/utility/__pycache__/connection_optimization.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/utility/__pycache__/overlay_structure_on_mesh.cpython-311.pyc +0 -0
- fiberfusing-1.3.4/FiberFusing/utility/connection_optimization.py +232 -0
- fiberfusing-1.3.4/FiberFusing/utility/overlay_structure_on_mesh.py +38 -0
- fiberfusing-1.3.4/FiberFusing/utils.py +174 -0
- fiberfusing-1.3.4/FiberFusing.egg-info/PKG-INFO +140 -0
- fiberfusing-1.3.4/FiberFusing.egg-info/SOURCES.txt +109 -0
- fiberfusing-1.3.4/FiberFusing.egg-info/dependency_links.txt +1 -0
- fiberfusing-1.3.4/FiberFusing.egg-info/requires.txt +22 -0
- fiberfusing-1.3.4/FiberFusing.egg-info/top_level.txt +1 -0
- fiberfusing-1.3.4/LICENSE +21 -0
- fiberfusing-1.3.4/MANIFEST.in +19 -0
- fiberfusing-1.3.4/PKG-INFO +140 -0
- fiberfusing-1.3.4/README.rst +96 -0
- fiberfusing-1.3.4/pyproject.toml +11 -0
- fiberfusing-1.3.4/setup.cfg +79 -0
- fiberfusing-1.3.4/setup.py +6 -0
- fiberfusing-1.3.4/tests/__pycache__/test_boundaries.cpython-311-pytest-8.3.1.pyc +0 -0
- fiberfusing-1.3.4/tests/__pycache__/test_fiber.cpython-311-pytest-8.3.1.pyc +0 -0
- fiberfusing-1.3.4/tests/__pycache__/test_fused_structure.cpython-311-pytest-8.3.1.pyc +0 -0
- fiberfusing-1.3.4/tests/__pycache__/test_geometries.cpython-311-pytest-8.3.1.pyc +0 -0
- fiberfusing-1.3.4/tests/test_boundaries.py +42 -0
- fiberfusing-1.3.4/tests/test_fiber.py +52 -0
- fiberfusing-1.3.4/tests/test_fused_structure.py +36 -0
- fiberfusing-1.3.4/tests/test_geometries.py +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.3.4
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from .geometry import Geometry # noqa: F401
|
|
2
|
+
from .components.point import Point # noqa: F401
|
|
3
|
+
from .components.linestring import LineString # noqa: F401
|
|
4
|
+
from .components.polygon import Polygon, EmptyPolygon # noqa: F401
|
|
5
|
+
from .buffer import Circle, Square # noqa: F401
|
|
6
|
+
from .background import BackGround # noqa: F401
|
|
7
|
+
from pydantic.dataclasses import dataclass
|
|
8
|
+
from pydantic import ConfigDict
|
|
9
|
+
|
|
10
|
+
from typing import Optional, Tuple
|
|
11
|
+
import numpy
|
|
12
|
+
|
|
13
|
+
micro = 1e-6
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(config=ConfigDict(extra='forbid'), kw_only=True)
|
|
17
|
+
class CircleOpticalStructure():
|
|
18
|
+
"""
|
|
19
|
+
Initialize a CircleOpticalStructure instance.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
name (str): Name of the structure.
|
|
23
|
+
index (float): Refractive index of the structure.
|
|
24
|
+
radius (float): Radius of the circle representing the slice of the structure.
|
|
25
|
+
position (Tuple[float, float]): Center position of the circle.
|
|
26
|
+
is_graded (Optional[bool], optional): True if the structure has a graded refractive index. Defaults to False.
|
|
27
|
+
delta_n (Optional[float], optional): Delta refractive index of the grading. Defaults to None.
|
|
28
|
+
"""
|
|
29
|
+
name: str
|
|
30
|
+
index: float
|
|
31
|
+
radius: float
|
|
32
|
+
position: Tuple[float, float]
|
|
33
|
+
is_graded: Optional[bool] = False
|
|
34
|
+
delta_n: Optional[float] = None
|
|
35
|
+
|
|
36
|
+
def __post_init__(self) -> None:
|
|
37
|
+
self.polygon = Circle(position=self.position, radius=self.radius)
|
|
38
|
+
|
|
39
|
+
def compute_index_from_NA(self, NA: float, exterior_index: float) -> float:
|
|
40
|
+
"""
|
|
41
|
+
Compute the refractive index from the numerical aperture (NA).
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
NA (float): Numerical aperture.
|
|
45
|
+
exterior_index (float): Refractive index of the exterior structure.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
float: Computed refractive index.
|
|
49
|
+
"""
|
|
50
|
+
return numpy.sqrt(NA**2 + exterior_index**2)
|
|
51
|
+
|
|
52
|
+
def get_V_number(self, wavelength: float) -> float:
|
|
53
|
+
"""
|
|
54
|
+
Compute the V-number for the optical structure.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
wavelength (float): Wavelength of the light.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
float: Computed V-number.
|
|
61
|
+
"""
|
|
62
|
+
delta_index = numpy.sqrt(self.index**2 - self.exterior_structure.index**2)
|
|
63
|
+
|
|
64
|
+
V = 2 * numpy.pi / wavelength * delta_index * self.radius
|
|
65
|
+
|
|
66
|
+
return V
|
|
67
|
+
|
|
68
|
+
def scale(self, factor: float) -> None:
|
|
69
|
+
"""
|
|
70
|
+
Scale the radius of the optical structure by a given factor.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
factor (float): Scaling factor.
|
|
74
|
+
"""
|
|
75
|
+
self.radius *= factor
|
|
76
|
+
self.__post_init__()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# -
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
from typing import Tuple, Optional
|
|
5
|
+
from pydantic.dataclasses import dataclass
|
|
6
|
+
from pydantic import ConfigDict
|
|
7
|
+
|
|
8
|
+
import numpy
|
|
9
|
+
|
|
10
|
+
from FiberFusing.coordinate_system import CoordinateSystem
|
|
11
|
+
from FiberFusing.utility.overlay_structure_on_mesh import OverlayStructureBaseClass
|
|
12
|
+
from FiberFusing import Circle
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NameSpace:
|
|
16
|
+
"""
|
|
17
|
+
A flexible class that allows the dynamic addition of attributes via keyword arguments.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, **kwargs):
|
|
21
|
+
"""
|
|
22
|
+
Initializes an instance with attributes specified by the keyword arguments.
|
|
23
|
+
|
|
24
|
+
:param kwargs: Arbitrary keyword arguments to set as attributes.
|
|
25
|
+
"""
|
|
26
|
+
for key, value in kwargs.items():
|
|
27
|
+
setattr(self, key, value)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(config=ConfigDict(extra='forbid'), kw_only=True)
|
|
31
|
+
class BackGround(OverlayStructureBaseClass):
|
|
32
|
+
"""
|
|
33
|
+
Represents a background structure to be overlayed on a mesh, characterized by a circular shape.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
index (float): Refractive index of the background.
|
|
37
|
+
radius (float): Radius of the circular structure. Defaults to 1000.
|
|
38
|
+
position (Optional[Tuple[float, float]]): A tuple (x, y) specifying the position of the circle's center. Defaults to (0, 0).
|
|
39
|
+
structure_list (list): List of namespaces containing structure data.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
index: float
|
|
43
|
+
radius: float = 1000
|
|
44
|
+
position: Optional[Tuple[float, float]] = (0, 0)
|
|
45
|
+
|
|
46
|
+
def __post_init__(self):
|
|
47
|
+
"""
|
|
48
|
+
Initializes the background structure by creating a circular polygon.
|
|
49
|
+
"""
|
|
50
|
+
# Create the circular structure
|
|
51
|
+
polygon = Circle(
|
|
52
|
+
position=self.position,
|
|
53
|
+
radius=self.radius,
|
|
54
|
+
index=self.index
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
background = NameSpace(index=self.index, polygon=polygon, name='background')
|
|
58
|
+
self.structure_list = [background]
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def refractive_index_list(self) -> list:
|
|
62
|
+
"""
|
|
63
|
+
Returns the list of refractive indices for the structures.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
list: A list containing the refractive index of the background.
|
|
67
|
+
"""
|
|
68
|
+
return [self.index]
|
|
69
|
+
|
|
70
|
+
def overlay_structures_on_mesh(self, mesh: numpy.ndarray, coordinate_system: CoordinateSystem) -> numpy.ndarray:
|
|
71
|
+
"""
|
|
72
|
+
Overlays all the structures onto the given mesh using the specified coordinate system.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
mesh (numpy.ndarray): A numpy ndarray representing the mesh to overlay on.
|
|
76
|
+
coordinate_system (CoordinateSystem): The coordinate system to use for overlaying.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
numpy.ndarray: A numpy ndarray with the structures overlayed onto the original mesh.
|
|
80
|
+
"""
|
|
81
|
+
return self._overlay_structure_on_mesh_(
|
|
82
|
+
structure_list=self.structure_list,
|
|
83
|
+
mesh=mesh,
|
|
84
|
+
coordinate_system=coordinate_system
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# -
|
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
from typing import Union, Optional
|
|
6
|
+
import logging
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
# Third-party imports
|
|
10
|
+
import numpy
|
|
11
|
+
import shapely.geometry as geo
|
|
12
|
+
|
|
13
|
+
# Local imports
|
|
14
|
+
from MPSPlots.render2D import Axis, SceneList
|
|
15
|
+
from FiberFusing import utils
|
|
16
|
+
from FiberFusing.utility.overlay_structure_on_mesh import OverlayStructureBaseClass
|
|
17
|
+
from FiberFusing.coordinate_system import CoordinateSystem
|
|
18
|
+
from FiberFusing.buffer import Circle
|
|
19
|
+
from FiberFusing.sub_structures.ring import FiberRing
|
|
20
|
+
from FiberFusing.sub_structures.line import FiberLine
|
|
21
|
+
|
|
22
|
+
logging.basicConfig(level=logging.INFO)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class NameSpace:
|
|
26
|
+
"""
|
|
27
|
+
A flexible class that allows the dynamic addition of attributes via keyword arguments.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, **kwargs):
|
|
31
|
+
"""
|
|
32
|
+
Initializes an instance with attributes specified by the keyword arguments.
|
|
33
|
+
|
|
34
|
+
:param kwargs: Arbitrary keyword arguments to set as attributes.
|
|
35
|
+
"""
|
|
36
|
+
for key, value in kwargs.items():
|
|
37
|
+
setattr(self, key, value)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class BaseFused(OverlayStructureBaseClass):
|
|
42
|
+
"""
|
|
43
|
+
Represents a base class for managing the fusion of optical fiber structures, allowing customization of fiber properties and spatial configuration. This class facilitates the dynamic assembly of fiber optics structures and automates the overlay of these structures on a given mesh.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
fiber_radius (float): Radius of individual fibers in the structure.
|
|
47
|
+
index (float): Refractive index of the fibers' cladding.
|
|
48
|
+
tolerance_factor (float): A tolerance value used in optimization algorithms to balance the area difference between added and removed sections during the fusion process.
|
|
49
|
+
fusion_degree (float | str): Specifies the degree of fusion, ranging from 0 (no fusion) to 1 (full fusion), or 'auto' to automatically determine based on geometry.
|
|
50
|
+
core_position_scrambling (float): Introduces randomness to core positions to simulate practical imperfections.
|
|
51
|
+
scale_down_position (float): Scaling factor to adjust the overall size of the assembly.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
fiber_radius: float
|
|
55
|
+
index: float
|
|
56
|
+
tolerance_factor: Optional[float] = 1e-2
|
|
57
|
+
fusion_degree: Optional[Union[float | str]] = 'auto'
|
|
58
|
+
core_position_scrambling: Optional[float] = 0
|
|
59
|
+
scale_down_position: Optional[float] = 1
|
|
60
|
+
|
|
61
|
+
def __post_init__(self):
|
|
62
|
+
"""
|
|
63
|
+
Initializes the fiber and core lists and any required structures immediately after the dataclass fields have been populated.
|
|
64
|
+
"""
|
|
65
|
+
self.fiber_list = []
|
|
66
|
+
self.core_list = []
|
|
67
|
+
self._clad_structure = None
|
|
68
|
+
self.structure_list = []
|
|
69
|
+
self.removed_section_list = []
|
|
70
|
+
self.added_section_list = []
|
|
71
|
+
|
|
72
|
+
self.compute_parametrized_fusion_degree()
|
|
73
|
+
|
|
74
|
+
def compute_parametrized_fusion_degree(self) -> float:
|
|
75
|
+
"""
|
|
76
|
+
Calculates a fusion degree adjusted to the specific requirements of the structure's geometry.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
float: The adjusted fusion degree, mapping an abstract range [0, 1] to the actual usable range defined by the structure's physical constraints.
|
|
80
|
+
"""
|
|
81
|
+
if str(self.fusion_degree).lower() == 'auto':
|
|
82
|
+
self.fusion_degree = 0.8 if self.fusion_range is not None else None
|
|
83
|
+
|
|
84
|
+
self.asserts_fusion_degree()
|
|
85
|
+
|
|
86
|
+
if self.fusion_degree is not None:
|
|
87
|
+
self.parametrized_fusion_degree = self.fusion_range[0] * (1 - self.fusion_degree) + self.fusion_degree * self.fusion_range[-1]
|
|
88
|
+
else:
|
|
89
|
+
self.parametrized_fusion_degree = None
|
|
90
|
+
|
|
91
|
+
def asserts_fusion_degree(self) -> None:
|
|
92
|
+
"""
|
|
93
|
+
Validates the fusion degree to ensure it lies within acceptable bounds.
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
ValueError: If the fusion degree is not a scalar when required, or is out of the acceptable bounds [0, 1].
|
|
97
|
+
TypeError: If the fusion degree is required but None is provided.
|
|
98
|
+
"""
|
|
99
|
+
if self.fusion_range is None:
|
|
100
|
+
if self.fusion_degree is not None:
|
|
101
|
+
raise ValueError(f"This instance of {self.__class__.__name__} does not take 'fusion_degree' as an argument.")
|
|
102
|
+
else:
|
|
103
|
+
if not numpy.isscalar(self.fusion_degree):
|
|
104
|
+
raise TypeError(f"Fusion degree: [{self.fusion_degree}] must be a scalar value.")
|
|
105
|
+
|
|
106
|
+
if not 0 <= self.fusion_degree <= 1:
|
|
107
|
+
raise ValueError(f"User provided fusion degree: {self.fusion_degree} must be in the range [0, 1].")
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def refractive_index_list(self) -> list[float]:
|
|
111
|
+
return [self.index]
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def is_multi(self) -> bool:
|
|
115
|
+
return isinstance(self.clad_structure._shapely_object, geo.MultiPolygon)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def clad_structure(self):
|
|
119
|
+
if self._clad_structure is None:
|
|
120
|
+
return utils.Union(*self.structure_list)
|
|
121
|
+
else:
|
|
122
|
+
return self._clad_structure
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def structure_dictionary(self) -> dict:
|
|
126
|
+
return {'name': {'index': self.index, 'polygon': self.clad_structure}}
|
|
127
|
+
|
|
128
|
+
def overlay_structures_on_mesh(self, mesh: numpy.ndarray, coordinate_system: CoordinateSystem) -> numpy.ndarray:
|
|
129
|
+
"""
|
|
130
|
+
Applies the current fiber structure configuration onto a provided mesh, considering the specified coordinate system.
|
|
131
|
+
|
|
132
|
+
Parameters:
|
|
133
|
+
mesh (numpy.ndarray): The mesh on which to overlay the structure.
|
|
134
|
+
coordinate_system (CoordinateSystem): The coordinate system to use for the overlay.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
numpy.ndarray: A mesh with the fiber structures applied.
|
|
138
|
+
"""
|
|
139
|
+
structure_list = [
|
|
140
|
+
NameSpace(index=self.index, polygon=self.clad_structure)
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
return self._overlay_structure_on_mesh_(
|
|
144
|
+
structure_list=structure_list,
|
|
145
|
+
mesh=mesh,
|
|
146
|
+
coordinate_system=coordinate_system
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def get_shapely_object(self):
|
|
150
|
+
return self.clad_structure._shapely_object
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def bounds(self) -> tuple:
|
|
154
|
+
"""
|
|
155
|
+
Return the boundaries of the structure.
|
|
156
|
+
"""
|
|
157
|
+
return self.clad_structure.bounds
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def boundaries(self) -> tuple:
|
|
161
|
+
"""
|
|
162
|
+
Return the boundaries of the structure.
|
|
163
|
+
"""
|
|
164
|
+
return self.clad_structure.bounds
|
|
165
|
+
|
|
166
|
+
def get_structure_max_min_boundaries(self) -> tuple:
|
|
167
|
+
return self.clad_structure.bounds
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def center(self):
|
|
171
|
+
return self.clad_structure.center
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def fiber(self) -> list:
|
|
175
|
+
"""
|
|
176
|
+
Return list of all the fiber in the structure
|
|
177
|
+
|
|
178
|
+
:returns: List of the structure fiber components
|
|
179
|
+
:rtype: list
|
|
180
|
+
"""
|
|
181
|
+
return self.fiber_list
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def cores(self) -> list:
|
|
185
|
+
"""
|
|
186
|
+
Return a list of the cores
|
|
187
|
+
|
|
188
|
+
:returns: List of the cores
|
|
189
|
+
:rtype: list
|
|
190
|
+
"""
|
|
191
|
+
return [fiber.core for fiber in self.fiber_list]
|
|
192
|
+
|
|
193
|
+
def add_single_fiber(self, fiber_radius: float, position: tuple = (0, 0)) -> BaseFused:
|
|
194
|
+
"""
|
|
195
|
+
Adds a single fiber to the structure at the specified position.
|
|
196
|
+
|
|
197
|
+
Parameters:
|
|
198
|
+
fiber_radius (float): The radius of the fiber to add.
|
|
199
|
+
position (tuple, optional): The x, y coordinates for the fiber. Defaults to (0, 0).
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
BaseFused: Returns the instance to allow for method chaining.
|
|
203
|
+
"""
|
|
204
|
+
fiber = Circle(
|
|
205
|
+
radius=fiber_radius,
|
|
206
|
+
position=position
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
fiber.shifted_core = fiber.center
|
|
210
|
+
|
|
211
|
+
self.structure_list.append(fiber)
|
|
212
|
+
|
|
213
|
+
self.fiber_list.append(fiber)
|
|
214
|
+
|
|
215
|
+
return self
|
|
216
|
+
|
|
217
|
+
def add_single_circle_structure(self, fiber_radius: float, position: tuple = (0, 0)) -> BaseFused:
|
|
218
|
+
"""
|
|
219
|
+
Adds a single structure.
|
|
220
|
+
|
|
221
|
+
:param fiber_radius: The fiber radius
|
|
222
|
+
:type fiber_radius: float
|
|
223
|
+
:param position: The position
|
|
224
|
+
:type position: tuple
|
|
225
|
+
|
|
226
|
+
:returns: The self instance
|
|
227
|
+
:rtype: BaseFused
|
|
228
|
+
"""
|
|
229
|
+
fiber = Circle(
|
|
230
|
+
radius=fiber_radius,
|
|
231
|
+
position=position
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
self.structure_list.append(fiber)
|
|
235
|
+
|
|
236
|
+
return self
|
|
237
|
+
|
|
238
|
+
def add_center_fiber(self, fiber_radius: float) -> BaseFused:
|
|
239
|
+
"""
|
|
240
|
+
Add a single fiber of given radius at the center of the structure.
|
|
241
|
+
|
|
242
|
+
:param fiber_radius: The fiber radius
|
|
243
|
+
:type fiber_radius: float
|
|
244
|
+
|
|
245
|
+
:returns: The self instance
|
|
246
|
+
:rtype: BaseFused
|
|
247
|
+
"""
|
|
248
|
+
return self.add_single_fiber(fiber_radius=fiber_radius, position=(0, 0))
|
|
249
|
+
|
|
250
|
+
def add_center_structure(self, fiber_radius: float) -> BaseFused:
|
|
251
|
+
"""
|
|
252
|
+
Add a single structure of given radius at the center of the structure.
|
|
253
|
+
|
|
254
|
+
:param fiber_radius: The fiber radius
|
|
255
|
+
:type fiber_radius: float
|
|
256
|
+
|
|
257
|
+
:returns: The self instance
|
|
258
|
+
:rtype: BaseFused
|
|
259
|
+
"""
|
|
260
|
+
return self.add_single_circle_structure(fiber_radius=fiber_radius, position=(0, 0))
|
|
261
|
+
|
|
262
|
+
def _add_structure_to_instance_(
|
|
263
|
+
self,
|
|
264
|
+
structure: FiberRing | FiberLine,
|
|
265
|
+
fusion_degree: float = 0.0,
|
|
266
|
+
scale_position: float = 1.0,
|
|
267
|
+
position_shift: list = [0, 0],
|
|
268
|
+
compute_fusing: bool = False) -> BaseFused:
|
|
269
|
+
|
|
270
|
+
if compute_fusing:
|
|
271
|
+
structure.set_fusion_degree(fusion_degree=fusion_degree)
|
|
272
|
+
|
|
273
|
+
structure.scale_position(factor=scale_position)
|
|
274
|
+
structure.shift_position(shift=position_shift)
|
|
275
|
+
structure.initialize_cores()
|
|
276
|
+
|
|
277
|
+
self.fiber_list += structure.fiber_list
|
|
278
|
+
|
|
279
|
+
if compute_fusing:
|
|
280
|
+
structure.init_connected_fibers()
|
|
281
|
+
structure.compute_optimal_structure()
|
|
282
|
+
self.removed_section_list.append(structure.removed_section)
|
|
283
|
+
self.added_section_list.append(structure.added_section)
|
|
284
|
+
self.structure_list.append(structure.fused_structure)
|
|
285
|
+
|
|
286
|
+
else:
|
|
287
|
+
self.structure_list.append(structure.unfused_structure)
|
|
288
|
+
|
|
289
|
+
return self
|
|
290
|
+
|
|
291
|
+
def add_structure(
|
|
292
|
+
self,
|
|
293
|
+
structure_type: str,
|
|
294
|
+
number_of_fibers: int,
|
|
295
|
+
fiber_radius: float,
|
|
296
|
+
fusion_degree: float = 0.0,
|
|
297
|
+
scale_position: float = 1.0,
|
|
298
|
+
position_shift: list = [0, 0],
|
|
299
|
+
compute_fusing: bool = False,
|
|
300
|
+
angle_shift: float = 0.0) -> BaseFused:
|
|
301
|
+
"""
|
|
302
|
+
Adds a predefined structure of fibers, such as a ring or line, with customizable properties and spatial configuration.
|
|
303
|
+
|
|
304
|
+
Parameters:
|
|
305
|
+
structure_type (str): The type of structure to add ('ring' or 'line').
|
|
306
|
+
number_of_fibers (int): Number of fibers in the structure.
|
|
307
|
+
fiber_radius (float): Radius of each fiber in the structure.
|
|
308
|
+
fusion_degree (float): The degree of fusion for this structure.
|
|
309
|
+
scale_position (float): Factor to scale the position of each fiber.
|
|
310
|
+
position_shift (list): A 2D vector [x, y] to shift the entire structure.
|
|
311
|
+
compute_fusing (bool): Whether to compute the fusing operation for the structure.
|
|
312
|
+
angle_shift (float): The angle by which to rotate the structure.
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
BaseFused: Returns the instance to allow for method chaining.
|
|
316
|
+
"""
|
|
317
|
+
match structure_type.lower():
|
|
318
|
+
case 'ring':
|
|
319
|
+
StructureClass = FiberRing
|
|
320
|
+
case 'line':
|
|
321
|
+
StructureClass = FiberRing
|
|
322
|
+
|
|
323
|
+
structure = StructureClass(
|
|
324
|
+
number_of_fibers=number_of_fibers,
|
|
325
|
+
fiber_radius=fiber_radius,
|
|
326
|
+
angle_shift=angle_shift
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
return self._add_structure_to_instance_(
|
|
330
|
+
structure=structure,
|
|
331
|
+
fusion_degree=fusion_degree,
|
|
332
|
+
scale_position=scale_position,
|
|
333
|
+
position_shift=position_shift,
|
|
334
|
+
compute_fusing=compute_fusing
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
def add_custom_fiber(self, *fibers) -> None:
|
|
338
|
+
"""
|
|
339
|
+
Add any custom defined fiber
|
|
340
|
+
|
|
341
|
+
:param fibers: The custom fibers
|
|
342
|
+
:type fibers: list
|
|
343
|
+
"""
|
|
344
|
+
for fiber in fibers:
|
|
345
|
+
self.fiber_list.append(fiber)
|
|
346
|
+
|
|
347
|
+
def get_core_positions(self) -> list:
|
|
348
|
+
"""
|
|
349
|
+
Return a list of the core positions
|
|
350
|
+
|
|
351
|
+
:returns: The core positions.
|
|
352
|
+
:rtype: list
|
|
353
|
+
"""
|
|
354
|
+
return [fiber.core for fiber in self.fiber_list]
|
|
355
|
+
|
|
356
|
+
def randomize_core_position(self, random_factor: float = 0) -> BaseFused:
|
|
357
|
+
"""
|
|
358
|
+
Shuffle the position of the fiber cores.
|
|
359
|
+
It can be used to add realism to the fusion process.
|
|
360
|
+
|
|
361
|
+
:param random_factor: The randomize position
|
|
362
|
+
:type random_factor: float
|
|
363
|
+
|
|
364
|
+
:returns: The self instance
|
|
365
|
+
:rtype: BaseFused
|
|
366
|
+
"""
|
|
367
|
+
if random_factor == 0:
|
|
368
|
+
return
|
|
369
|
+
|
|
370
|
+
logging.info("Randomizing the core positions")
|
|
371
|
+
|
|
372
|
+
if random_factor != 0:
|
|
373
|
+
for fiber in self.fiber_list:
|
|
374
|
+
random_xy = numpy.random.rand(2) * random_factor
|
|
375
|
+
fiber.core.translate(random_xy, in_place=True)
|
|
376
|
+
|
|
377
|
+
return self
|
|
378
|
+
|
|
379
|
+
def get_rasterized_mesh(self, coordinate_system: CoordinateSystem) -> numpy.ndarray:
|
|
380
|
+
return self.clad_structure.get_rasterized_mesh(coordinate_system=coordinate_system)
|
|
381
|
+
|
|
382
|
+
def rotate(self, *args, **kwargs) -> BaseFused:
|
|
383
|
+
"""
|
|
384
|
+
Rotates the full structure, including the fiber cores.
|
|
385
|
+
|
|
386
|
+
:returns: The self instance
|
|
387
|
+
:rtype: BaseFused
|
|
388
|
+
"""
|
|
389
|
+
for fiber in self.fiber_list:
|
|
390
|
+
fiber.core.rotate(*args, **kwargs, in_place=True)
|
|
391
|
+
|
|
392
|
+
self._clad_structure = self.clad_structure.rotate(*args, **kwargs)
|
|
393
|
+
|
|
394
|
+
return self
|
|
395
|
+
|
|
396
|
+
def shift(self, *args, **kwargs) -> BaseFused:
|
|
397
|
+
"""
|
|
398
|
+
Rotates the full structure, including the fiber cores.
|
|
399
|
+
|
|
400
|
+
:returns: The self instance
|
|
401
|
+
:rtype: BaseFused
|
|
402
|
+
"""
|
|
403
|
+
for fiber in self.fiber_list:
|
|
404
|
+
fiber.core.shift(*args, **kwargs, in_place=True)
|
|
405
|
+
|
|
406
|
+
self._clad_structure = self.clad_structure.shift(*args, **kwargs)
|
|
407
|
+
|
|
408
|
+
return self
|
|
409
|
+
|
|
410
|
+
def scale_position(self, factor: float) -> BaseFused:
|
|
411
|
+
"""
|
|
412
|
+
Scale down the distance between each cores.
|
|
413
|
+
|
|
414
|
+
:param factor: The scaling factor
|
|
415
|
+
:type factor: float
|
|
416
|
+
|
|
417
|
+
:returns: The self instance
|
|
418
|
+
:rtype: BaseFused
|
|
419
|
+
"""
|
|
420
|
+
for fiber in self.fiber_list:
|
|
421
|
+
fiber.scale_position(factor=factor)
|
|
422
|
+
|
|
423
|
+
return self
|
|
424
|
+
|
|
425
|
+
def plot(self, **kwargs) -> SceneList:
|
|
426
|
+
|
|
427
|
+
figure = SceneList(unit_size=(6, 6))
|
|
428
|
+
|
|
429
|
+
ax = figure.append_ax(
|
|
430
|
+
x_label=r'x',
|
|
431
|
+
y_label=r'y',
|
|
432
|
+
show_grid=True,
|
|
433
|
+
equal_limits=True,
|
|
434
|
+
show_legend=True,
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
self.render_patch_on_ax(ax=ax, **kwargs)
|
|
438
|
+
|
|
439
|
+
return figure
|
|
440
|
+
|
|
441
|
+
def render_patch_on_ax(
|
|
442
|
+
self,
|
|
443
|
+
ax: Axis,
|
|
444
|
+
show_structure: bool = True,
|
|
445
|
+
show_fibers: bool = False,
|
|
446
|
+
show_shifted_cores: bool = True,
|
|
447
|
+
show_added: bool = True,
|
|
448
|
+
show_removed: bool = True) -> None:
|
|
449
|
+
"""
|
|
450
|
+
Add the geometry patches to the axis.
|
|
451
|
+
Base patch is the clad representation.
|
|
452
|
+
The boolean paraemters defines which other patch is added
|
|
453
|
+
to the ax.
|
|
454
|
+
|
|
455
|
+
:param ax: The axis to which add the patches
|
|
456
|
+
:type ax: Axis
|
|
457
|
+
:param show_structure: Added the fused structure to ax
|
|
458
|
+
:type show_structure: bool
|
|
459
|
+
:param show_fibers: Added the unfused fibers to ax
|
|
460
|
+
:type show_fibers: bool
|
|
461
|
+
:param show_shifted_cores: Added the shifted cores to ax
|
|
462
|
+
:type show_shifted_cores: bool
|
|
463
|
+
:param show_added: Added the added section to ax
|
|
464
|
+
:type show_added: bool
|
|
465
|
+
:param show_removed: Added the removed section to ax
|
|
466
|
+
:type show_removed: bool
|
|
467
|
+
|
|
468
|
+
:returns: The scene list.
|
|
469
|
+
:rtype: SceneList
|
|
470
|
+
"""
|
|
471
|
+
if show_structure:
|
|
472
|
+
self.clad_structure._render_on_ax_(ax)
|
|
473
|
+
|
|
474
|
+
ax.set_style(
|
|
475
|
+
x_label=r'x-distance [$\mu$m]',
|
|
476
|
+
y_label=r'y-distance [$\mu$m]',
|
|
477
|
+
x_scale_factor=1e6,
|
|
478
|
+
y_scale_factor=1e6,
|
|
479
|
+
equal_limits=True,
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
if show_added:
|
|
483
|
+
added_section = utils.Union(*self.added_section_list)
|
|
484
|
+
added_section._render_on_ax_(ax=ax, facecolor='green', label='added section')
|
|
485
|
+
|
|
486
|
+
# if show_removed:
|
|
487
|
+
# removed_section = utils.Union(*self.removed_section_list)
|
|
488
|
+
# removed_section._render_on_ax_(ax=ax, facecolor='red', label='removed section')
|
|
489
|
+
|
|
490
|
+
# if show_fibers:
|
|
491
|
+
# for n, fiber in enumerate(self.fiber_list):
|
|
492
|
+
# fiber._render_on_ax_(ax)
|
|
493
|
+
# fiber.center._render_on_ax_(
|
|
494
|
+
# ax,
|
|
495
|
+
# marker='o',
|
|
496
|
+
# marker_size=40,
|
|
497
|
+
# label='core',
|
|
498
|
+
# )
|
|
499
|
+
|
|
500
|
+
# if show_shifted_cores:
|
|
501
|
+
# for n, fiber in enumerate(self.fiber_list):
|
|
502
|
+
# fiber.shifted_core.render_on_axis(
|
|
503
|
+
# ax,
|
|
504
|
+
# marker='x',
|
|
505
|
+
# marker_size=40,
|
|
506
|
+
# edge_color=None,
|
|
507
|
+
# label='shifted core',
|
|
508
|
+
# )
|
|
509
|
+
|
|
510
|
+
# -
|