diff --git a/gnpy/core/network.py b/gnpy/core/network.py index 5616c2b8a..1aec09fe6 100644 --- a/gnpy/core/network.py +++ b/gnpy/core/network.py @@ -12,7 +12,7 @@ from collections import namedtuple from functools import reduce from logging import getLogger -from typing import Tuple, List, Optional, Union, Dict +from typing import Tuple, List, Optional, Union, Dict, Iterator from networkx import DiGraph from numpy import allclose import warnings @@ -29,6 +29,9 @@ logger = getLogger(__name__) +ELEMENT_TYPES = Union[elements.Fiber, elements.Roadm, elements.Fused, elements.Edfa, elements.Transceiver, elements.Transceiver] +PASSIVE_ELEMENT_TYPES = Union[elements.Fiber, elements.Roadm, elements.Fused] + def edfa_nf(gain_target: float, amp_params) -> float: """Calculates the noise figure (NF) of an EDFA (Erbium-Doped Fiber Amplifier) @@ -37,17 +40,15 @@ def edfa_nf(gain_target: float, amp_params) -> float: This function creates an EDFA instance with the given parameters and computes its noise figure using the internal calculation method. - Parameters: - ----------- - gain_target : float - The target gain for which the noise figure is to be calculated. - amp_params : object - An object containing the amplifier parameters. + :param gain_target: The target gain for which the noise figure is to be calculated. + :type gain_target: float + :param amp_params: An object containing the amplifier parameters. + :type amp_params: gnpy.tools.json_io.Amp - Returns: - -------- - float - The calculated noise figure (NF) of the EDFA in dB. + :return: The calculated noise figure (NF) of the EDFA in dB. + :rtype: float + + :raises ValueError: If the gain_target is not achievable with the given parameters. """ amp = elements.Edfa( uid='calc_NF', @@ -73,35 +74,27 @@ def select_edfa(raman_allowed: bool, gain_target: float, power_target: float, ed edfa_eqpt dict has already filtered out the amplifiers that do not match any other restrictions such as ROADM booster or preamp restrictions or frequency constraints. - Parameters: - ----------- - raman_allowed : bool - Indicates whether Raman amplifiers are permitted in the selection. - gain_target : float - The target gain that the selected amplifier should achieve. - power_target : float - The target power level for the amplifier. - edfa_eqpt : dict - A dictionary containing available EDFA equipment, where keys are - amplifier names and values are amplifier objects. - uid : str - A unique identifier for the node where the amplifier will be used. - target_extended_gain : float - The extended gain target derived from configuration settings. - verbose : Optional[bool], default=True - If True, enables verbose logging of warnings and information. - - Returns: - -------- - Tuple[str, float] - A tuple containing the selected amplifier's variety and the power - reduction applied (if any). - - Raises: - ------- - ConfigurationError - If no amplifiers meet the minimum gain requirement for the specified - node. + :param raman_allowed: Indicates whether Raman amplifiers are permitted in the selection. + :type raman_allowed: bool + :param gain_target: The target gain that the selected amplifier should achieve. + :type gain_target: float + :param power_target: The target power level for the amplifier. + :type power_target: float + :param edfa_eqpt: A dictionary containing available EDFA equipment, where keys are + amplifier names and values are amplifier objects. + :type edfa_eqpt: dict + :param uid: A unique identifier for the node where the amplifier will be used. + :type uid: str + :param target_extended_gain: The extended gain target derived from configuration settings. + :type target_extended_gain: float + :param verbose: If True, enables verbose logging of warnings and information. + :type verbose: Optional[bool], default=True + + :return: A tuple containing the selected amplifier's variety and the power + reduction applied (if any). + :rtype: Tuple[str, float] + + :raises ConfigurationError: If no amplifiers meet the minimum gain requirement for the specified node. Notes: ------ @@ -138,10 +131,31 @@ def select_edfa(raman_allowed: bool, gain_target: float, power_target: float, ed return selected_edfa.variety, power_reduction -def target_power(network, node, equipment, deviation_db): # get_fiber_dp - """Computes target power using J. -L. Auge, V. Curri and E. Le Rouzic, - Open Design for Multi-Vendor Optical Networks, OFC 2019. - equation 4 +def target_power(network: DiGraph, node: PASSIVE_ELEMENT_TYPES, + equipment: Dict, deviation_db: float) -> float: # get_fiber_dp + """Computes the target power for a given node in the network. + + This function uses the methodology described by J. -L. Auge, V. Curri, and E. Le Rouzic + in "Open Design for Multi-Vendor Optical Networks," OFC 2019, specifically equation 4. + + :param network: The network object containing the topology and elements. + :type network: DiGraph + :param node: The node for which the target power is being calculated. + :type node: elements.Fiber + :param equipment: A dictionary containing equipment parameters and configurations. + :type equipment: dict + :param deviation_db: The deviation in dB to be applied to the calculated power. + :type deviation_db: float + + :return: The computed target power in dB. + :rtype: float + + :raises ConfigurationError: If the delta power range is not defined correctly in the equipment configuration. + + Notes: + ------ + - If the node is a ROADM, the function returns 0. + - The target power is calculated based on the span loss and adjusted by the specified deviation. """ if isinstance(node, elements.Roadm): return 0 @@ -165,9 +179,26 @@ def target_power(network, node, equipment, deviation_db): # get_fiber_dp _fiber_fused_types = (elements.Fused, elements.Fiber) -def prev_node_generator(network, node): - """fused spans interest: - iterate over all predecessors while they are either Fused or Fibers succeeded by Fused""" +def prev_node_generator(network: DiGraph, node: ELEMENT_TYPES) -> Iterator[Union[elements.Fiber, elements.Fused]]: + """Generates predecessor nodes in the network that are either Fused or Fibers succeeded by Fused. + + This function iterates over all predecessors of the specified node, yielding nodes that meet the criteria + of being either a Fused element or a Fiber that is succeeded by a Fused element. + + :param network: The directed graph representing the network topology. + :type network: DiGraph + :param node: The current node for which predecessors are being generated. + :type node: Union[elements.Fiber, elements.Roadm, elements.Fused, elements.Edfa, elements.Transceiver, elements.Transceiver] + + :yield: The predecessor nodes that are either Fused or Fibers succeeded by Fused. + :rtype: Iterator[Union[elements.Fiber, elements.Fused] + + :raises NetworkTopologyError: If the node is not properly connected in the network topology. + + Notes: + ------ + - If the node is a Transceiver and has no predecessors, the function will return without yielding any nodes. + """ try: prev_node = next(network.predecessors(node)) except StopIteration: