FiberFusing 1.7.0__tar.gz → 1.9.0__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.
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/.github/workflows/deploy_anaconda.yml +3 -3
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/.github/workflows/deploy_coverage.yml +2 -2
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/.github/workflows/deploy_documentation.yml +3 -3
- fiberfusing-1.9.0/FiberFusing/__init__.py +15 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/_version.py +16 -3
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/background.py +8 -23
- fiberfusing-1.9.0/FiberFusing/connection/connection.py +459 -0
- {fiberfusing-1.7.0/FiberFusing → fiberfusing-1.9.0/FiberFusing/connection}/connection_optimization.py +7 -7
- fiberfusing-1.9.0/FiberFusing/connection/utils.py +16 -0
- fiberfusing-1.9.0/FiberFusing/coordinate_system.py +944 -0
- fiberfusing-1.9.0/FiberFusing/fiber/__init__.py +2 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/generic_fiber.py +237 -45
- fiberfusing-1.9.0/FiberFusing/fiber/loader.py +318 -0
- fiberfusing-1.9.0/FiberFusing/geometries/__init__.py +3 -0
- {fiberfusing-1.7.0/FiberFusing/components → fiberfusing-1.9.0/FiberFusing/geometries}/base_class.py +3 -3
- {fiberfusing-1.7.0/FiberFusing/components → fiberfusing-1.9.0/FiberFusing/geometries}/linestring.py +3 -3
- {fiberfusing-1.7.0/FiberFusing/components → fiberfusing-1.9.0/FiberFusing/geometries}/point.py +9 -9
- {fiberfusing-1.7.0/FiberFusing/components → fiberfusing-1.9.0/FiberFusing/geometries}/polygon.py +3 -3
- {fiberfusing-1.7.0/FiberFusing/components → fiberfusing-1.9.0/FiberFusing/geometries}/utils.py +2 -2
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/geometry.py +159 -186
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/helper.py +3 -3
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/optical_structure.py +8 -9
- fiberfusing-1.7.0/FiberFusing/base_fused.py → fiberfusing-1.9.0/FiberFusing/profile.py +54 -80
- fiberfusing-1.9.0/FiberFusing/shapes/__init__.py +3 -0
- fiberfusing-1.9.0/FiberFusing/shapes/base.py +6 -0
- fiberfusing-1.9.0/FiberFusing/shapes/circle.py +54 -0
- fiberfusing-1.9.0/FiberFusing/shapes/ellipse.py +68 -0
- fiberfusing-1.9.0/FiberFusing/shapes/square.py +55 -0
- fiberfusing-1.7.0/FiberFusing/fiber_structure.py → fiberfusing-1.9.0/FiberFusing/structures.py +52 -18
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/utils.py +15 -3
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing.egg-info/PKG-INFO +61 -12
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing.egg-info/SOURCES.txt +26 -48
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing.egg-info/requires.txt +7 -8
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/PKG-INFO +61 -12
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/README.rst +53 -3
- fiberfusing-1.9.0/docs/examples/extra/README.rst +4 -0
- fiberfusing-1.9.0/docs/examples/extra/custom_graded_index_fiber.py +42 -0
- fiberfusing-1.9.0/docs/examples/extra/custom_step_index_fiber.py +40 -0
- fiberfusing-1.9.0/docs/examples/extra/loading_fiber.py +18 -0
- fiberfusing-1.9.0/docs/examples/extra/randomize_core.py +32 -0
- fiberfusing-1.9.0/docs/examples/extra/structure_shift.py +29 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_line_3.py +55 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_line_4.py +48 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_line_5.py +48 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_ring_10.py +48 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_ring_2.py +49 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_ring_3.py +48 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_ring_4.py +52 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_ring_5.py +49 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_ring_7.py +49 -0
- fiberfusing-1.9.0/docs/examples/geometry/plot_single.py +45 -0
- fiberfusing-1.9.0/docs/source/code/components.rst +10 -0
- fiberfusing-1.9.0/docs/source/code/shapes.rst +9 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/code.rst +1 -1
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/conf.py +0 -5
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/gallery/index.rst +28 -138
- fiberfusing-1.9.0/docs/source/sg_execution_times.rst +79 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/meta.yaml +6 -5
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/pyproject.toml +7 -8
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/tests/fiber_loader.py +39 -13
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/tests/test_boundaries.py +21 -12
- fiberfusing-1.9.0/tests/test_cooordinate_system.py +536 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/tests/test_fiber.py +28 -22
- fiberfusing-1.9.0/tests/test_fused_structure.py +105 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/tests/test_generic_fiber.py +4 -19
- fiberfusing-1.9.0/tests/test_geometries.py +191 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/tests/test_polygon.py +2 -2
- fiberfusing-1.7.0/.readthedocs.yml +0 -35
- fiberfusing-1.7.0/FiberFusing/__init__.py +0 -15
- fiberfusing-1.7.0/FiberFusing/buffer.py +0 -163
- fiberfusing-1.7.0/FiberFusing/configuration/__init__.py +0 -7
- fiberfusing-1.7.0/FiberFusing/configuration/line/__init__.py +0 -10
- fiberfusing-1.7.0/FiberFusing/configuration/line/configuration_01x01.py +0 -14
- fiberfusing-1.7.0/FiberFusing/configuration/line/configuration_02x02.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/line/configuration_03x03.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/line/configuration_04x04.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/line/configuration_05x05.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/ring/__init__.py +0 -15
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_01x01.py +0 -14
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_02x02.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_03x03.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_04x04.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_05x05.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_06x06.py +0 -18
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_07x07.py +0 -20
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_10x10.py +0 -31
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_12x12.py +0 -30
- fiberfusing-1.7.0/FiberFusing/configuration/ring/configuration_19x19.py +0 -34
- fiberfusing-1.7.0/FiberFusing/connection.py +0 -366
- fiberfusing-1.7.0/FiberFusing/coordinate_system.py +0 -256
- fiberfusing-1.7.0/FiberFusing/fiber/catalogue.py +0 -165
- fiberfusing-1.7.0/FiberFusing/fiber/loader.py +0 -120
- fiberfusing-1.7.0/FiberFusing/fiber/structure_collection.py +0 -173
- fiberfusing-1.7.0/docs/examples/clad/README.rst +0 -4
- fiberfusing-1.7.0/docs/examples/clad/fusion_degree.py +0 -26
- fiberfusing-1.7.0/docs/examples/clad/plot_line_3.py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_line_4.py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_line_5.py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_ring_12.py +0 -21
- fiberfusing-1.7.0/docs/examples/clad/plot_ring_19.py +0 -21
- fiberfusing-1.7.0/docs/examples/clad/plot_ring_2.py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_ring_3py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_ring_4.py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_ring_7.py +0 -22
- fiberfusing-1.7.0/docs/examples/clad/plot_single.py +0 -16
- fiberfusing-1.7.0/docs/examples/clad/radomize_core.py +0 -33
- fiberfusing-1.7.0/docs/examples/clad/structure_shift.py +0 -28
- fiberfusing-1.7.0/docs/examples/geometry/plot_line_3.py +0 -51
- fiberfusing-1.7.0/docs/examples/geometry/plot_line_4.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_line_5.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_ring_10.py +0 -44
- fiberfusing-1.7.0/docs/examples/geometry/plot_ring_2.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_ring_3.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_ring_4.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_ring_5.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_ring_7.py +0 -45
- fiberfusing-1.7.0/docs/examples/geometry/plot_single.py +0 -44
- fiberfusing-1.7.0/docs/source/code/buffer.rst +0 -19
- fiberfusing-1.7.0/docs/source/code/components.rst +0 -33
- fiberfusing-1.7.0/tests/__init__.py +0 -0
- fiberfusing-1.7.0/tests/test_cooordinate_system.py +0 -155
- fiberfusing-1.7.0/tests/test_fused_structure.py +0 -57
- fiberfusing-1.7.0/tests/test_geometries.py +0 -154
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/.flake8 +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/.github/dependabot.yml +0 -0
- /fiberfusing-1.7.0/.github/workflows/deploy_PyPI.yml → /fiberfusing-1.9.0/.github/workflows/deploy_PyPi.yml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/.gitignore +0 -0
- {fiberfusing-1.7.0/FiberFusing/components → fiberfusing-1.9.0/FiberFusing/connection}/__init__.py +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/directories.py +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/1550BHP.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/DCF13.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/DCF1300S_20.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/DCF1300S_26.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/DCF1300S_33.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/DCF1300S_42.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/F2028M12.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/F2028M21.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/F2028M24.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/F2058G1.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/F2058L1.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/HI1060.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/HP630.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/SM1950.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/SMF28.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/fluorine_doped_1%_capillary.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/fluorine_doped_2%_capillary.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/test_fiber.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/fiber/fiber_files/test_multimode_fiber.yaml +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing/plottings.py +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing.egg-info/dependency_links.txt +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/FiberFusing.egg-info/top_level.txt +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/LICENSE +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/Makefile +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/examples/README.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/examples/geometry/README.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/images/example_3x3.png +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/images/logo.png +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/make.bat +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/_static/default.css +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/_static/thumbnail.png +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/code/coordinate_system.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/code/geometry.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/code/utils.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/index.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/references.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/docs/source/theory.rst +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/notebook.ipynb +0 -0
- {fiberfusing-1.7.0 → fiberfusing-1.9.0}/setup.cfg +0 -0
- {fiberfusing-1.7.0/FiberFusing/fiber → fiberfusing-1.9.0/tests}/__init__.py +0 -0
|
@@ -3,8 +3,7 @@ name: Deploy Conda Packages
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
5
|
branches: [ "master" ]
|
|
6
|
-
tags:
|
|
7
|
-
- '*'
|
|
6
|
+
tags: '*'
|
|
8
7
|
pull_request:
|
|
9
8
|
branches: [ "master" ]
|
|
10
9
|
|
|
@@ -15,7 +14,8 @@ jobs:
|
|
|
15
14
|
ManyLinux_x86_64:
|
|
16
15
|
uses: MartinPdeS/MPSActions/.github/workflows/publish_compiled_package_to_anaconda.yml@master
|
|
17
16
|
with:
|
|
18
|
-
python-versions: '["3.11", "3.12"]'
|
|
17
|
+
python-versions: '["3.11", "3.12", "3.13"]'
|
|
18
|
+
apt-package: ""
|
|
19
19
|
secrets:
|
|
20
20
|
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_API_TOKEN }}
|
|
21
21
|
|
|
@@ -4,8 +4,7 @@ name: Deploy coverage
|
|
|
4
4
|
on:
|
|
5
5
|
push:
|
|
6
6
|
branches: [ "master" ]
|
|
7
|
-
tags:
|
|
8
|
-
- '*'
|
|
7
|
+
tags: '*'
|
|
9
8
|
pull_request:
|
|
10
9
|
branches: [ "master" ]
|
|
11
10
|
|
|
@@ -21,5 +20,6 @@ jobs:
|
|
|
21
20
|
uses: MartinPdeS/MPSActions/.github/workflows/publish_coverage.yml@master
|
|
22
21
|
with:
|
|
23
22
|
python-version: "3.11"
|
|
23
|
+
apt-package: xvfb
|
|
24
24
|
secrets:
|
|
25
25
|
_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# Simple workflow for deploying static content to GitHub Pages
|
|
2
|
-
name:
|
|
2
|
+
name: Documentation
|
|
3
3
|
|
|
4
4
|
on:
|
|
5
5
|
push:
|
|
6
6
|
branches: [ "master" ]
|
|
7
|
-
tags:
|
|
8
|
-
- '*'
|
|
7
|
+
tags: '*'
|
|
9
8
|
pull_request:
|
|
10
9
|
branches: [ "master" ]
|
|
11
10
|
|
|
@@ -22,3 +21,4 @@ jobs:
|
|
|
22
21
|
with:
|
|
23
22
|
python-version: "3.11"
|
|
24
23
|
package-name: "FiberFusing"
|
|
24
|
+
apt-package: xvfb jq
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .geometry import Geometry, DomainAlignment # noqa: F401
|
|
2
|
+
from .geometries.point import Point # noqa: F401
|
|
3
|
+
from .geometries.linestring import LineString # noqa: F401
|
|
4
|
+
from .geometries.polygon import Polygon, EmptyPolygon # noqa: F401
|
|
5
|
+
from .shapes import Circle, Square # noqa: F401
|
|
6
|
+
from .background import BackGround # noqa: F401
|
|
7
|
+
from .optical_structure import CircleOpticalStructure # noqa: F401
|
|
8
|
+
micro = 1e-6
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from ._version import version as __version__ # noqa: F401
|
|
13
|
+
|
|
14
|
+
except ImportError:
|
|
15
|
+
__version__ = "0.0.0"
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '1.
|
|
21
|
-
__version_tuple__ = version_tuple = (1,
|
|
31
|
+
__version__ = version = '1.9.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 9, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'gf07a7ef48'
|
|
@@ -8,22 +8,7 @@ import numpy as np
|
|
|
8
8
|
|
|
9
9
|
from FiberFusing.coordinate_system import CoordinateSystem
|
|
10
10
|
from FiberFusing.helper import OverlayStructureBaseClass
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class NameSpace:
|
|
14
|
-
"""
|
|
15
|
-
A flexible class that allows dynamic addition of attributes via keyword arguments.
|
|
16
|
-
"""
|
|
17
|
-
def __init__(self, **kwargs):
|
|
18
|
-
"""
|
|
19
|
-
Initializes an instance with attributes specified by keyword arguments.
|
|
20
|
-
|
|
21
|
-
Parameters
|
|
22
|
-
----------
|
|
23
|
-
**kwargs : dict
|
|
24
|
-
Arbitrary keyword arguments to set as attributes.
|
|
25
|
-
"""
|
|
26
|
-
self.__dict__.update(kwargs)
|
|
11
|
+
from FiberFusing.utils import NameSpace
|
|
27
12
|
|
|
28
13
|
|
|
29
14
|
@dataclass(config=ConfigDict(extra='forbid', kw_only=True))
|
|
@@ -33,15 +18,15 @@ class BackGround(OverlayStructureBaseClass):
|
|
|
33
18
|
|
|
34
19
|
Attributes
|
|
35
20
|
----------
|
|
36
|
-
|
|
37
|
-
Refractive
|
|
21
|
+
refractive_index : float
|
|
22
|
+
Refractive refractive_index of the background.
|
|
38
23
|
radius : float, optional
|
|
39
24
|
Radius of the circular structure, by default 1000.
|
|
40
25
|
position : Optional[Tuple[float, float]], optional
|
|
41
26
|
A tuple (x, y) specifying the position of the circle's center, by default (0, 0).
|
|
42
27
|
"""
|
|
43
28
|
|
|
44
|
-
|
|
29
|
+
refractive_index: float
|
|
45
30
|
radius: float = 1000
|
|
46
31
|
position: Optional[Tuple[float, float]] = (0, 0)
|
|
47
32
|
|
|
@@ -51,8 +36,8 @@ class BackGround(OverlayStructureBaseClass):
|
|
|
51
36
|
"""
|
|
52
37
|
from FiberFusing import Circle
|
|
53
38
|
|
|
54
|
-
polygon = Circle(position=self.position, radius=self.radius,
|
|
55
|
-
self.structure_list = [NameSpace(
|
|
39
|
+
polygon = Circle(position=self.position, radius=self.radius, refractive_index=self.refractive_index)
|
|
40
|
+
self.structure_list = [NameSpace(refractive_index=self.refractive_index, polygon=polygon, name='background')]
|
|
56
41
|
|
|
57
42
|
@property
|
|
58
43
|
def refractive_index_list(self) -> list:
|
|
@@ -64,7 +49,7 @@ class BackGround(OverlayStructureBaseClass):
|
|
|
64
49
|
list
|
|
65
50
|
A list containing the refractive index of the background.
|
|
66
51
|
"""
|
|
67
|
-
return [self.
|
|
52
|
+
return [self.refractive_index]
|
|
68
53
|
|
|
69
54
|
def overlay_structures_on_mesh(self, mesh: np.ndarray, coordinate_system: CoordinateSystem) -> np.ndarray:
|
|
70
55
|
"""
|
|
@@ -89,4 +74,4 @@ class BackGround(OverlayStructureBaseClass):
|
|
|
89
74
|
)
|
|
90
75
|
|
|
91
76
|
def rotate(self, *args, **kwargs) -> None:
|
|
92
|
-
pass
|
|
77
|
+
pass
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
from typing import List, Tuple, Optional
|
|
6
|
+
import numpy as np
|
|
7
|
+
import logging
|
|
8
|
+
from scipy.optimize import minimize_scalar
|
|
9
|
+
from pydantic.dataclasses import dataclass
|
|
10
|
+
from pydantic import ConfigDict
|
|
11
|
+
|
|
12
|
+
import FiberFusing as ff
|
|
13
|
+
from FiberFusing import utils
|
|
14
|
+
from FiberFusing.shapes.circle import Circle
|
|
15
|
+
from FiberFusing.connection.utils import TopologyType, ConscriptedCircleType
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(config=ConfigDict(extra='forbid', arbitrary_types_allowed=True, strict=True, frozen=False))
|
|
20
|
+
class Connection:
|
|
21
|
+
"""
|
|
22
|
+
Represents a connection between two optical fiber circles.
|
|
23
|
+
|
|
24
|
+
This class manages the geometric relationship between two fibers, including
|
|
25
|
+
their fusion topology, area calculations, and core positioning optimization.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
fiber0 : Circle
|
|
30
|
+
The first fiber in the connection.
|
|
31
|
+
fiber1 : Circle
|
|
32
|
+
The second fiber in the connection.
|
|
33
|
+
|
|
34
|
+
Attributes
|
|
35
|
+
----------
|
|
36
|
+
topology : TopologyType
|
|
37
|
+
The connection topology (convex, concave, or undefined).
|
|
38
|
+
shift : float
|
|
39
|
+
The shift value for the connection geometry.
|
|
40
|
+
added_section : ff.Polygon
|
|
41
|
+
The area added during fiber fusion.
|
|
42
|
+
removed_section : ff.Polygon
|
|
43
|
+
The area removed during fiber fusion.
|
|
44
|
+
virtual_circles : tuple[Circle, Circle] | None
|
|
45
|
+
Pair of virtual circles used for geometry calculations.
|
|
46
|
+
mask : ff.Polygon | None
|
|
47
|
+
Geometric mask for connection calculations.
|
|
48
|
+
core_shift : tuple[ff.Point, ff.Point] | None
|
|
49
|
+
Optimized core position shifts for both fibers.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
fiber0: Circle
|
|
53
|
+
fiber1: Circle
|
|
54
|
+
|
|
55
|
+
def __post_init__(self) -> None:
|
|
56
|
+
"""Initialize connection properties with default values."""
|
|
57
|
+
self._topology = TopologyType.UNDEFINED
|
|
58
|
+
self._shift: float = 0.0
|
|
59
|
+
self.added_section = ff.EmptyPolygon()
|
|
60
|
+
self.removed_section = ff.EmptyPolygon()
|
|
61
|
+
self.virtual_circles: Optional[Tuple[Circle, Circle]] = None
|
|
62
|
+
self.mask: Optional[ff.Polygon] = None
|
|
63
|
+
self.core_shift: Optional[Tuple[ff.Point, ff.Point]] = None
|
|
64
|
+
|
|
65
|
+
logging.info(f"Created connection between fibers at {self.fiber0.center} and {self.fiber1.center}")
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def topology(self) -> TopologyType:
|
|
69
|
+
"""Get the connection topology."""
|
|
70
|
+
return self._topology
|
|
71
|
+
|
|
72
|
+
@topology.setter
|
|
73
|
+
def topology(self, value: TopologyType) -> None:
|
|
74
|
+
"""Set the connection topology with validation."""
|
|
75
|
+
if not isinstance(value, TopologyType):
|
|
76
|
+
raise TypeError(f"Topology must be a TopologyType enum, got {type(value).__name__}")
|
|
77
|
+
self._topology = value
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def shift(self) -> float:
|
|
81
|
+
"""Get the connection shift value."""
|
|
82
|
+
return self._shift
|
|
83
|
+
|
|
84
|
+
@shift.setter
|
|
85
|
+
def shift(self, value: float) -> None:
|
|
86
|
+
"""Set the connection shift value."""
|
|
87
|
+
self._shift = float(value)
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def fibers(self) -> List[Circle]:
|
|
91
|
+
"""Get list of connected fibers."""
|
|
92
|
+
return [self.fiber0, self.fiber1]
|
|
93
|
+
|
|
94
|
+
def __getitem__(self, idx: int) -> Circle:
|
|
95
|
+
"""Get fiber by index."""
|
|
96
|
+
if idx not in (0, 1):
|
|
97
|
+
raise IndexError(f"Fiber index must be 0 or 1, got {idx}")
|
|
98
|
+
return self.fibers[idx]
|
|
99
|
+
|
|
100
|
+
def __setitem__(self, idx: int, fiber: Circle) -> None:
|
|
101
|
+
"""Set fiber by index."""
|
|
102
|
+
if idx not in (0, 1):
|
|
103
|
+
raise IndexError(f"Fiber index must be 0 or 1, got {idx}")
|
|
104
|
+
if idx == 0:
|
|
105
|
+
self.fiber0 = fiber
|
|
106
|
+
else:
|
|
107
|
+
self.fiber1 = fiber
|
|
108
|
+
|
|
109
|
+
# =============================================================================
|
|
110
|
+
# GEOMETRIC PROPERTIES
|
|
111
|
+
# =============================================================================
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def distance_between_cores(self) -> float:
|
|
115
|
+
"""Calculate distance between fiber centers."""
|
|
116
|
+
return self.fiber0.center.distance(self.fiber1.center)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def center_line(self) -> ff.LineString:
|
|
120
|
+
"""Get line connecting fiber centers."""
|
|
121
|
+
return ff.LineString(coordinates=[self.fiber0.center, self.fiber1.center])
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def extended_center_line(self) -> ff.LineString:
|
|
125
|
+
"""Get extended line connecting fiber centers."""
|
|
126
|
+
line = self.center_line
|
|
127
|
+
extension = self.fiber0.radius + self.fiber1.radius
|
|
128
|
+
return line.make_length(line.length + extension)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def limit_added_area(self) -> ff.Polygon:
|
|
132
|
+
"""Calculate the theoretical maximum added area."""
|
|
133
|
+
union_hull = self.fiber0.union(self.fiber1).convex_hull
|
|
134
|
+
return union_hull - self.fiber0 - self.fiber1
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def total_area(self) -> ff.Polygon:
|
|
138
|
+
"""Get total area including both fibers and added section."""
|
|
139
|
+
output = utils.union_geometries(self.fiber0, self.fiber1, self.added_section)
|
|
140
|
+
output.remove_non_polygon_elements()
|
|
141
|
+
return output
|
|
142
|
+
|
|
143
|
+
# =============================================================================
|
|
144
|
+
# CONNECTION CONFIGURATION
|
|
145
|
+
# =============================================================================
|
|
146
|
+
|
|
147
|
+
def configure_connection(self, shift: float, topology: TopologyType) -> None:
|
|
148
|
+
"""
|
|
149
|
+
Configure connection with shift and topology parameters.
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
shift : float
|
|
154
|
+
The shift value for connection geometry.
|
|
155
|
+
topology : TopologyType
|
|
156
|
+
The connection topology type.
|
|
157
|
+
"""
|
|
158
|
+
self.shift = shift
|
|
159
|
+
self.topology = topology
|
|
160
|
+
|
|
161
|
+
self._compute_all_geometry()
|
|
162
|
+
|
|
163
|
+
logging.info(f"Configured connection: shift={shift:.3f}, topology={self.topology.value}")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _compute_all_geometry(self) -> None:
|
|
167
|
+
"""Compute all geometric components in correct order."""
|
|
168
|
+
if self.topology == TopologyType.UNDEFINED:
|
|
169
|
+
raise ValueError("Cannot compute geometry with undefined topology")
|
|
170
|
+
|
|
171
|
+
self._compute_virtual_circles()
|
|
172
|
+
self._compute_mask()
|
|
173
|
+
self._compute_added_section()
|
|
174
|
+
self._compute_removed_section()
|
|
175
|
+
|
|
176
|
+
# =============================================================================
|
|
177
|
+
# GEOMETRIC CALCULATIONS
|
|
178
|
+
# =============================================================================
|
|
179
|
+
|
|
180
|
+
def _compute_virtual_circles(self) -> None:
|
|
181
|
+
"""Compute conscripted virtual circles based on topology."""
|
|
182
|
+
circle_type = (
|
|
183
|
+
ConscriptedCircleType.EXTERIOR if self.topology == TopologyType.CONCAVE
|
|
184
|
+
else ConscriptedCircleType.INTERIOR
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
primary_circle = self._get_conscripted_circle(circle_type)
|
|
188
|
+
secondary_circle = primary_circle.rotate(
|
|
189
|
+
angle=180,
|
|
190
|
+
origin=self.center_line.mid_point,
|
|
191
|
+
in_place=False
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
self.virtual_circles = (primary_circle, secondary_circle)
|
|
195
|
+
|
|
196
|
+
def _get_conscripted_circle(self, circle_type: ConscriptedCircleType) -> Circle:
|
|
197
|
+
"""
|
|
198
|
+
Create conscripted circle based on type.
|
|
199
|
+
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
circle_type : ConscriptedCircleType
|
|
203
|
+
Type of conscripted circle to create.
|
|
204
|
+
|
|
205
|
+
Returns
|
|
206
|
+
-------
|
|
207
|
+
Circle
|
|
208
|
+
The conscripted circle.
|
|
209
|
+
"""
|
|
210
|
+
line = self.center_line
|
|
211
|
+
perpendicular = self.extended_center_line.get_perpendicular().get_vector()
|
|
212
|
+
center_point = line.mid_point.translate(perpendicular * self.shift)
|
|
213
|
+
|
|
214
|
+
base_radius = np.sqrt(self.shift**2 + (line.length / 2)**2)
|
|
215
|
+
|
|
216
|
+
if circle_type == ConscriptedCircleType.EXTERIOR:
|
|
217
|
+
radius = base_radius - self.fiber0.radius
|
|
218
|
+
else: # INTERIOR
|
|
219
|
+
radius = base_radius + self.fiber0.radius
|
|
220
|
+
|
|
221
|
+
return Circle(position=(center_point.x, center_point.y), radius=radius)
|
|
222
|
+
|
|
223
|
+
def _compute_mask(self) -> None:
|
|
224
|
+
"""Compute geometric mask for connection."""
|
|
225
|
+
if not self.virtual_circles:
|
|
226
|
+
raise ValueError("Virtual circles must be computed before mask")
|
|
227
|
+
|
|
228
|
+
contact_points = self._get_contact_points()
|
|
229
|
+
|
|
230
|
+
if self.topology == TopologyType.CONCAVE:
|
|
231
|
+
self.mask = self._compute_concave_mask(contact_points)
|
|
232
|
+
else: # CONVEX
|
|
233
|
+
self.mask = self._compute_convex_mask(contact_points)
|
|
234
|
+
|
|
235
|
+
def _get_contact_points(self) -> List[ff.Point]:
|
|
236
|
+
"""Get contact points between fibers and virtual circles."""
|
|
237
|
+
if not self.virtual_circles:
|
|
238
|
+
raise ValueError("Virtual circles not computed")
|
|
239
|
+
|
|
240
|
+
v0, v1 = self.virtual_circles
|
|
241
|
+
|
|
242
|
+
contacts = [
|
|
243
|
+
utils.nearest_points_exterior(v0, self.fiber0),
|
|
244
|
+
utils.nearest_points_exterior(v1, self.fiber0),
|
|
245
|
+
utils.nearest_points_exterior(v0, self.fiber1),
|
|
246
|
+
utils.nearest_points_exterior(v1, self.fiber1)
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
return [ff.Point(position=(p.x, p.y)) for p in contacts]
|
|
250
|
+
|
|
251
|
+
def _compute_concave_mask(self, contact_points: List[ff.Point]) -> ff.Polygon:
|
|
252
|
+
"""Compute mask for concave topology."""
|
|
253
|
+
p0, p1, p2, p3 = contact_points
|
|
254
|
+
coordinates = [(p._shapely_object.x, p._shapely_object.y) for p in [p0, p1, p3, p2]]
|
|
255
|
+
|
|
256
|
+
mask = ff.Polygon(coordinates=coordinates)
|
|
257
|
+
v0, v1 = self.virtual_circles
|
|
258
|
+
return mask - v0 - v1
|
|
259
|
+
|
|
260
|
+
def _compute_convex_mask(self, contact_points: List[ff.Point]) -> ff.Polygon:
|
|
261
|
+
"""Compute mask for convex topology."""
|
|
262
|
+
p0, p1, p2, p3 = contact_points
|
|
263
|
+
mid_point = self.center_line.mid_point
|
|
264
|
+
|
|
265
|
+
# Create two mask triangles
|
|
266
|
+
coords0 = [(p._shapely_object.x, p._shapely_object.y) for p in [mid_point, p0, p2]]
|
|
267
|
+
coords1 = [(p._shapely_object.x, p._shapely_object.y) for p in [mid_point, p1, p3]]
|
|
268
|
+
|
|
269
|
+
mask0 = ff.Polygon(coordinates=coords0)
|
|
270
|
+
mask1 = ff.Polygon(coordinates=coords1)
|
|
271
|
+
|
|
272
|
+
# Scale masks
|
|
273
|
+
scale_factor = 1000
|
|
274
|
+
mask0.scale(factor=scale_factor, origin=mid_point._shapely_object, in_place=True)
|
|
275
|
+
mask1.scale(factor=scale_factor, origin=mid_point._shapely_object, in_place=True)
|
|
276
|
+
|
|
277
|
+
# Combine masks with virtual circles
|
|
278
|
+
v0, v1 = self.virtual_circles
|
|
279
|
+
combined_mask = utils.union_geometries(mask0, mask1)
|
|
280
|
+
combined_virtual = utils.union_geometries(v0, v1)
|
|
281
|
+
|
|
282
|
+
return combined_mask & combined_virtual
|
|
283
|
+
|
|
284
|
+
def _compute_added_section(self) -> None:
|
|
285
|
+
"""Compute the area added during fiber fusion."""
|
|
286
|
+
if not self.virtual_circles or not self.mask:
|
|
287
|
+
raise ValueError("Virtual circles and mask must be computed first")
|
|
288
|
+
|
|
289
|
+
v0, v1 = self.virtual_circles
|
|
290
|
+
base_section = self.mask - self.fiber0 - self.fiber1
|
|
291
|
+
|
|
292
|
+
if self.topology == TopologyType.CONVEX:
|
|
293
|
+
intersection = v0.intersection(v1, in_place=False)
|
|
294
|
+
self.added_section = base_section & intersection
|
|
295
|
+
else: # CONCAVE
|
|
296
|
+
union = v0.union(v1, in_place=False)
|
|
297
|
+
self.added_section = base_section - union
|
|
298
|
+
|
|
299
|
+
self.added_section.remove_non_polygon_elements()
|
|
300
|
+
|
|
301
|
+
def _compute_removed_section(self) -> None:
|
|
302
|
+
"""Compute the area removed during fiber fusion."""
|
|
303
|
+
self.removed_section = utils.intersection_geometries(self.fiber0, self.fiber1)
|
|
304
|
+
|
|
305
|
+
# Calculate actual removed area
|
|
306
|
+
total_individual_area = self.fiber0.area + self.fiber1.area
|
|
307
|
+
union_area = utils.union_geometries(self.fiber0, self.fiber1).area
|
|
308
|
+
self.removed_section.Area = total_individual_area - union_area
|
|
309
|
+
|
|
310
|
+
def determine_topology(self) -> TopologyType:
|
|
311
|
+
"""
|
|
312
|
+
Automatically determine connection topology based on geometry.
|
|
313
|
+
|
|
314
|
+
Returns
|
|
315
|
+
-------
|
|
316
|
+
TopologyType
|
|
317
|
+
The determined topology type.
|
|
318
|
+
"""
|
|
319
|
+
if self.removed_section.Area > self.limit_added_area.area:
|
|
320
|
+
return TopologyType.CONVEX
|
|
321
|
+
else:
|
|
322
|
+
return TopologyType.CONCAVE
|
|
323
|
+
|
|
324
|
+
# =============================================================================
|
|
325
|
+
# GEOMETRY OPERATIONS
|
|
326
|
+
# =============================================================================
|
|
327
|
+
|
|
328
|
+
def split_geometry(self,
|
|
329
|
+
geometry: ff.Polygon,
|
|
330
|
+
position: ff.Point,
|
|
331
|
+
return_largest: bool = True) -> ff.Polygon:
|
|
332
|
+
"""
|
|
333
|
+
Split geometry at specified position.
|
|
334
|
+
|
|
335
|
+
Parameters
|
|
336
|
+
----------
|
|
337
|
+
geometry : ff.Polygon
|
|
338
|
+
Geometry to split.
|
|
339
|
+
position : ff.Point
|
|
340
|
+
Position for splitting.
|
|
341
|
+
return_largest : bool, default True
|
|
342
|
+
Whether to return the largest split section.
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
ff.Polygon
|
|
347
|
+
The split geometry section.
|
|
348
|
+
"""
|
|
349
|
+
# Create perpendicular split line
|
|
350
|
+
split_line = self.center_line.centering(center=position)
|
|
351
|
+
split_line = split_line.rotate(angle=90, origin=split_line.mid_point)
|
|
352
|
+
split_line = split_line.extend(factor=2)
|
|
353
|
+
|
|
354
|
+
# Prepare geometry and split
|
|
355
|
+
clean_geometry = (utils.union_geometries(geometry.copy())
|
|
356
|
+
.remove_non_polygon_elements()
|
|
357
|
+
.keep_largest_polygon())
|
|
358
|
+
|
|
359
|
+
return clean_geometry.split_with_line(line=split_line, return_largest=return_largest)
|
|
360
|
+
|
|
361
|
+
# =============================================================================
|
|
362
|
+
# CORE POSITION OPTIMIZATION
|
|
363
|
+
# =============================================================================
|
|
364
|
+
|
|
365
|
+
def optimize_core_positions(self, tolerance: float = 1e-10) -> None:
|
|
366
|
+
"""
|
|
367
|
+
Optimize core positions to minimize area mismatch.
|
|
368
|
+
|
|
369
|
+
Parameters
|
|
370
|
+
----------
|
|
371
|
+
tolerance : float, default 1e-10
|
|
372
|
+
Optimization tolerance.
|
|
373
|
+
"""
|
|
374
|
+
logging.info("Starting core position optimization...")
|
|
375
|
+
|
|
376
|
+
result = minimize_scalar(
|
|
377
|
+
self._compute_area_mismatch_cost,
|
|
378
|
+
bounds=(0.50001, 0.99),
|
|
379
|
+
method='bounded',
|
|
380
|
+
options={'xatol': tolerance}
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
if result.success:
|
|
384
|
+
logging.info(f"Optimization successful: cost={result.fun:.2e}")
|
|
385
|
+
# Apply optimized shifts
|
|
386
|
+
if self.core_shift:
|
|
387
|
+
self.fiber0.shifted_core += self.core_shift[0]
|
|
388
|
+
self.fiber1.shifted_core += self.core_shift[1]
|
|
389
|
+
else:
|
|
390
|
+
logging.warning(f"Optimization failed: {result.message}")
|
|
391
|
+
|
|
392
|
+
def _compute_area_mismatch_cost(self, x: float) -> float:
|
|
393
|
+
"""
|
|
394
|
+
Compute area mismatch cost for optimization.
|
|
395
|
+
|
|
396
|
+
Parameters
|
|
397
|
+
----------
|
|
398
|
+
x : float
|
|
399
|
+
Optimization parameter (0 to 1).
|
|
400
|
+
|
|
401
|
+
Returns
|
|
402
|
+
-------
|
|
403
|
+
float
|
|
404
|
+
Cost value to minimize.
|
|
405
|
+
"""
|
|
406
|
+
# Get split positions
|
|
407
|
+
line = self.extended_center_line
|
|
408
|
+
position0 = line.get_position_parametrization(1 - x)
|
|
409
|
+
position1 = line.get_position_parametrization(x)
|
|
410
|
+
|
|
411
|
+
# Calculate small section area
|
|
412
|
+
small_section = self.split_geometry(
|
|
413
|
+
geometry=self.total_area,
|
|
414
|
+
position=position0,
|
|
415
|
+
return_largest=False
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
# Compute cost and store shifts
|
|
419
|
+
target_area = self.fiber0.area / 2.0
|
|
420
|
+
cost = abs(small_section.area - target_area)
|
|
421
|
+
|
|
422
|
+
self.core_shift = (
|
|
423
|
+
position0 - self.fiber0.center,
|
|
424
|
+
position1 - self.fiber1.center
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
logging.debug(f"Optimization step: x={x:.3f}, cost={cost:.2e}")
|
|
428
|
+
|
|
429
|
+
return cost
|
|
430
|
+
|
|
431
|
+
# =============================================================================
|
|
432
|
+
# UTILITY METHODS
|
|
433
|
+
# =============================================================================
|
|
434
|
+
|
|
435
|
+
def get_connection_summary(self) -> dict:
|
|
436
|
+
"""
|
|
437
|
+
Get summary of connection properties.
|
|
438
|
+
|
|
439
|
+
Returns
|
|
440
|
+
-------
|
|
441
|
+
dict
|
|
442
|
+
Dictionary containing connection summary.
|
|
443
|
+
"""
|
|
444
|
+
return {
|
|
445
|
+
'distance_between_cores': self.distance_between_cores,
|
|
446
|
+
'topology': self.topology.value,
|
|
447
|
+
'shift': self.shift,
|
|
448
|
+
'added_area': self.added_section.area if hasattr(self.added_section, 'area') else 0,
|
|
449
|
+
'removed_area': getattr(self.removed_section, 'Area', 0),
|
|
450
|
+
'total_area': self.total_area.area,
|
|
451
|
+
'fiber0_center': (self.fiber0.center.x, self.fiber0.center.y),
|
|
452
|
+
'fiber1_center': (self.fiber1.center.x, self.fiber1.center.y),
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
def __repr__(self) -> str:
|
|
456
|
+
"""String representation of the connection."""
|
|
457
|
+
return (f"Connection(fiber0=Circle({self.fiber0.center.x:.2f}, {self.fiber0.center.y:.2f}), "
|
|
458
|
+
f"fiber1=Circle({self.fiber1.center.x:.2f}, {self.fiber1.center.y:.2f}), "
|
|
459
|
+
f"topology={self.topology.value})")
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from typing import Tuple
|
|
2
1
|
import logging
|
|
3
2
|
from scipy.optimize import minimize_scalar
|
|
4
3
|
from itertools import combinations
|
|
5
|
-
from FiberFusing.connection import Connection
|
|
6
|
-
from FiberFusing.
|
|
4
|
+
from FiberFusing.connection.connection import Connection
|
|
5
|
+
from FiberFusing.connection.utils import TopologyType
|
|
6
|
+
from FiberFusing.shapes.circle import Polygon
|
|
7
7
|
from FiberFusing import utils
|
|
8
8
|
|
|
9
9
|
|
|
@@ -70,7 +70,7 @@ class ConnectionOptimization:
|
|
|
70
70
|
self._removed_section = self.get_removed_section()
|
|
71
71
|
return self._removed_section
|
|
72
72
|
|
|
73
|
-
def iterate_over_connected_fibers(self)
|
|
73
|
+
def iterate_over_connected_fibers(self):
|
|
74
74
|
"""
|
|
75
75
|
Generator that iterates over all connected fibers in the structure.
|
|
76
76
|
|
|
@@ -95,7 +95,7 @@ class ConnectionOptimization:
|
|
|
95
95
|
self.virtual_shift = virtual_shift
|
|
96
96
|
topology = self.get_overall_topology()
|
|
97
97
|
for connection in self.connected_fibers:
|
|
98
|
-
connection.
|
|
98
|
+
connection.configure_connection(shift=virtual_shift, topology=topology)
|
|
99
99
|
|
|
100
100
|
def get_added_section(self) -> Polygon:
|
|
101
101
|
"""
|
|
@@ -154,7 +154,7 @@ class ConnectionOptimization:
|
|
|
154
154
|
limit = [conn.limit_added_area for conn in self.connected_fibers]
|
|
155
155
|
overall_limit = utils.union_geometries(*limit) - utils.union_geometries(*self.fiber_list)
|
|
156
156
|
total_removed_area = self.get_removed_area()
|
|
157
|
-
return
|
|
157
|
+
return TopologyType.CONVEX if total_removed_area > overall_limit.area else TopologyType.CONCAVE
|
|
158
158
|
|
|
159
159
|
def optimize_core_positions(self) -> None:
|
|
160
160
|
"""
|
|
@@ -162,7 +162,7 @@ class ConnectionOptimization:
|
|
|
162
162
|
"""
|
|
163
163
|
logging.info("Computing the optimal core positions")
|
|
164
164
|
for connection in self.connected_fibers:
|
|
165
|
-
connection.
|
|
165
|
+
connection.optimize_core_positions()
|
|
166
166
|
|
|
167
167
|
def get_cost_value(self, virtual_shift: float) -> float:
|
|
168
168
|
"""
|