Source code for rsoft_cad.utils.fiber_layout.visualise_layout

# lantern/visualization.py
"""
Visualisation module for RSoft CAD utilities
"""

import numpy as np
import matplotlib.pyplot as plt

from rsoft_cad.utils.fiber_layout.circular import lantern_layout
from rsoft_cad.utils.fiber_layout.hexagonal import (
    hexagonal_fiber_layout,
    calculate_capillary_diameter,
)


[docs] def visualise_lantern(n, cladding_dia=125, show_scale_factor_plot=True): """ Visualize a lantern layout with n cladding circles. Parameters: ----------- n : int Number of cladding circles cladding_dia : float Diameter of the cladding circles in microns (default: 125) show_scale_factor_plot : bool If True, shows the scale factor vs radius plot (default: True) Returns: -------- tuple (fig, ax) for the main lantern layout plot (fig1, ax1) for the scale factor plot (if show_scale_factor_plot=True) """ # Calculate lantern layout R, centres_x, centres_y = lantern_layout(cladding_dia, n) # Print information print(f"Radius of lantern modes: {R:.2f} micron") print(f"Radius of center core: {R - (cladding_dia / 2):.2f} micron") print(f"Radius of capillary: {R + (cladding_dia / 2):.2f} micron") # Create main plot fig, ax = plt.subplots(figsize=(6, 6)) ax.set_xlim(-R - cladding_dia, R + cladding_dia) ax.set_ylim(-R - cladding_dia, R + cladding_dia) ax.set_aspect("equal") # Draw larger reference circle lantern = plt.Circle( (0, 0), R, color="blue", fill=False, linestyle="dashed", ) center_core = plt.Circle( (0, 0), R - (cladding_dia / 2), color="green", fill=False, linestyle="dashed", ) capillary = plt.Circle( (0, 0), R + (cladding_dia / 2), color="orange", fill=False, linestyle="solid", ) ax.add_patch(capillary) ax.add_patch(center_core) ax.add_patch(lantern) # Draw smaller cladding circles for x, y in zip(centres_x, centres_y): cladding = plt.Circle((x, y), cladding_dia / 2, color="red", fill=False) ax.add_patch(cladding) # Plot centre points ax.scatter(centres_x, centres_y, color="black", label="Centres of cladding circles") ax.scatter(0, 0, color="blue", marker="x", label="Centre of reference circle") # Labels and legend ax.set_title(f"{n} Cladding Circles in a Lantern Layout") ax.legend() plt.grid(True, linestyle="--", alpha=0.5) return (fig, ax)
[docs] def plot_hexagonal_fibers(fiber_dia, num_rings=3, spacing_factor=1.0): """ Plots the fibers in a hexagonal pattern. Parameters: fiber_dia (float): Diameter of the fibers. num_rings (int): Number of hexagonal rings around the central fiber. spacing_factor (float): Factor to adjust spacing between fibers (1.0 = touching). """ centers_x, centers_y = hexagonal_fiber_layout(fiber_dia, num_rings, spacing_factor) cap_dia = calculate_capillary_diameter(fiber_dia, num_rings, spacing_factor) # Create figure fig, ax = plt.subplots(figsize=(10, 10)) ax.set_aspect("equal") # Plot each fiber as a circle for x, y in zip(centers_x, centers_y): circle = plt.Circle((x, y), fiber_dia / 2, fill=False, edgecolor="blue") ax.add_patch(circle) circle = plt.Circle((0, 0), cap_dia / 2, fill=False, edgecolor="green") ax.add_patch(circle) # Set limits with some padding max_extent = max( max(abs(centers_x) + fiber_dia / 2), max(abs(centers_y) + fiber_dia / 2) ) ax.set_xlim(-max_extent * 1.1, max_extent * 1.1) ax.set_ylim(-max_extent * 1.1, max_extent * 1.1) # Add grid and labels ax.grid(True, linestyle="--", alpha=0.7) ax.set_title(f"Hexagonal Fiber Layout - {len(centers_x)} fibers") ax.set_xlabel("X position") ax.set_ylabel("Y position") # Show fiber count and parameters info_text = ( f"Diameter: {fiber_dia}\nSpacing factor: {spacing_factor}\nRings: {num_rings}" ) ax.text( 0.02, 0.98, info_text, transform=ax.transAxes, verticalalignment="top", bbox=dict(boxstyle="round", facecolor="white", alpha=0.8), ) plt.tight_layout() return fig, ax
[docs] def visualise_lp_lantern(lp_modes_dict, cladding_dia=125): """ Visualize a lantern layout with LP modes positioned according to the provided dictionary. Parameters: ----------- lp_modes_dict : dict Dictionary containing LP mode names as keys and coordinate tuples as values Example: {'LP01': (x1, y1), 'LP11a': (x2, y2), ...} cladding_dia : float Diameter of the cladding circles in microns (default: 125) Returns: -------- tuple (fig, ax) for the main lantern layout plot """ # Create main plot fig, ax = plt.subplots(figsize=(10, 10)) ax.set_aspect("equal") # Draw cladding circles for each LP mode for mode_name, coords in lp_modes_dict.items(): x, y = coords # Convert numpy float64 to regular float if needed if hasattr(x, "item"): x = x.item() if hasattr(y, "item"): y = y.item() # Draw the cladding circle cladding = plt.Circle((x, y), cladding_dia / 2, color="red", fill=False) ax.add_patch(cladding) # Annotate with the LP mode name ax.annotate(mode_name, (x, y), ha="center", va="center", fontsize=8) # Set axis limits based on the data all_x = [coords[0] for coords in lp_modes_dict.values()] all_y = [coords[1] for coords in lp_modes_dict.values()] # Calculate appropriate limits with some padding max_abs_x = max(abs(np.array(all_x).max()), abs(np.array(all_x).min())) max_abs_y = max(abs(np.array(all_y).max()), abs(np.array(all_y).min())) max_radius = max(max_abs_x, max_abs_y) + cladding_dia ax.set_xlim(-max_radius, max_radius) ax.set_ylim(-max_radius, max_radius) # Labels and grid ax.set_title("LP Modes in a Lantern Layout") ax.set_xlabel("x-axis (micron)") ax.set_ylabel("y-axis (micron)") plt.grid(True, linestyle="--", alpha=0.5) return (fig, ax)