Skip to content

Heaters

pychilaslasers.laser_components.heaters

Heater components package for laser thermal control.

This package provides heater component classes for controlling thermal elements of the laser. Includes channel definitions and individual heater types.

Classes:

  • HeaterChannel

    Enum representing the different heater channels

  • TunableCoupler

    Tunable coupler section heater for wavelength fine-tuning

  • LargeRing

    Large ring section heater for coarse wavelength adjustment

  • SmallRing

    Small ring section heater for fine wavelength adjustment

  • PhaseSection

    Phase section heater for phase adjustment and mode control

Authors: SDU

Classes

Heater(laser: Laser)

Bases: Driver


              flowchart TD
              pychilaslasers.laser_components.heaters.Heater[Heater]
              pychilaslasers.laser_components.driver.Driver[Driver]
              pychilaslasers.laser_components.laser_component.LaserComponent[LaserComponent]

                              pychilaslasers.laser_components.driver.Driver --> pychilaslasers.laser_components.heaters.Heater
                                pychilaslasers.laser_components.laser_component.LaserComponent --> pychilaslasers.laser_components.driver.Driver
                



              click pychilaslasers.laser_components.heaters.Heater href "" "pychilaslasers.laser_components.heaters.Heater"
              click pychilaslasers.laser_components.driver.Driver href "" "pychilaslasers.laser_components.driver.Driver"
              click pychilaslasers.laser_components.laser_component.LaserComponent href "" "pychilaslasers.laser_components.laser_component.LaserComponent"
            

Base class for laser heater components.

Provides common functionality for all heater types including value setting and channel management.

Attributes:

  • channel (HeaterChannel) –

    The heater channel identifier.

  • value (float) –

    The current heater drive value.

  • min_value (float) –

    Minimum heater value.

  • max_value (float) –

    Maximum heater value.

  • unit (str) –

    Heater value unit.

Sets up the heater with its operating limits and units by querying the laser hardware.

Parameters:

  • laser (Laser) –

    The laser instance to control.

Source code in src/pychilaslasers/laser_components/heaters/heaters.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def __init__(self, laser: Laser) -> None:
    """Initialize the heater component.

    Sets up the heater with its operating limits and units by
    querying the laser hardware.

    Args:
        laser: The laser instance to control.

    """
    super().__init__(laser)
    self._min: float = float(self._comm.query(f"DRV:LIM:MIN? {self.channel.value}"))
    self._max: float = float(self._comm.query(f"DRV:LIM:MAX? {self.channel.value}"))
    self._unit: str = self._comm.query(f"DRV:UNIT? {self.channel.value}").strip()
Attributes
channel: HeaterChannel abstractmethod property

Get the heater channel identifier.

Must be implemented by subclasses to specify which heater channel this component controls.

Returns:

value: float property writable

Get the current heater drive value.

Returns:

  • float

    The current heater drive value.

temp: float property

Returns the temperature measured by the sensor on the heater driver.

Notes

This temperature is the same regardless of instance the method is called on. There is only one sensor for all drivers.

Functions
get_value() -> float

Alias for the value property getter.

Returns:

  • float

    The current heater drive value.

Source code in src/pychilaslasers/laser_components/heaters/heaters.py
117
118
119
120
121
122
123
124
def get_value(self) -> float:
    """Alias for the `value` property getter.

    Returns:
        The current heater drive value.

    """
    return self.value
set_value(value: float) -> None

Alias for the value property setter.

Parameters:

  • value (float) –

    The heater drive value to set.

Raises:

  • ValueError

    If value is not a number or outside valid range.

Source code in src/pychilaslasers/laser_components/heaters/heaters.py
126
127
128
129
130
131
132
133
134
135
136
def set_value(self, value: float) -> None:
    """Alias for the `value` property setter.

    Args:
        value: The heater drive value to set.

    Raises:
        ValueError: If value is not a number or outside valid range.

    """
    self.value = value

LargeRing(laser: Laser)

Bases: Heater


              flowchart TD
              pychilaslasers.laser_components.heaters.LargeRing[LargeRing]
              pychilaslasers.laser_components.heaters.heaters.Heater[Heater]
              pychilaslasers.laser_components.driver.Driver[Driver]
              pychilaslasers.laser_components.laser_component.LaserComponent[LaserComponent]

                              pychilaslasers.laser_components.heaters.heaters.Heater --> pychilaslasers.laser_components.heaters.LargeRing
                                pychilaslasers.laser_components.driver.Driver --> pychilaslasers.laser_components.heaters.heaters.Heater
                                pychilaslasers.laser_components.laser_component.LaserComponent --> pychilaslasers.laser_components.driver.Driver
                




              click pychilaslasers.laser_components.heaters.LargeRing href "" "pychilaslasers.laser_components.heaters.LargeRing"
              click pychilaslasers.laser_components.heaters.heaters.Heater href "" "pychilaslasers.laser_components.heaters.heaters.Heater"
              click pychilaslasers.laser_components.driver.Driver href "" "pychilaslasers.laser_components.driver.Driver"
              click pychilaslasers.laser_components.laser_component.LaserComponent href "" "pychilaslasers.laser_components.laser_component.LaserComponent"
            

Large ring heater component.

Source code in src/pychilaslasers/laser_components/heaters/heaters.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def __init__(self, laser: Laser) -> None:
    """Initialize the heater component.

    Sets up the heater with its operating limits and units by
    querying the laser hardware.

    Args:
        laser: The laser instance to control.

    """
    super().__init__(laser)
    self._min: float = float(self._comm.query(f"DRV:LIM:MIN? {self.channel.value}"))
    self._max: float = float(self._comm.query(f"DRV:LIM:MAX? {self.channel.value}"))
    self._unit: str = self._comm.query(f"DRV:UNIT? {self.channel.value}").strip()
Attributes
channel: HeaterChannel property

Get the large ring channel.

SmallRing(laser: Laser)

Bases: Heater


              flowchart TD
              pychilaslasers.laser_components.heaters.SmallRing[SmallRing]
              pychilaslasers.laser_components.heaters.heaters.Heater[Heater]
              pychilaslasers.laser_components.driver.Driver[Driver]
              pychilaslasers.laser_components.laser_component.LaserComponent[LaserComponent]

                              pychilaslasers.laser_components.heaters.heaters.Heater --> pychilaslasers.laser_components.heaters.SmallRing
                                pychilaslasers.laser_components.driver.Driver --> pychilaslasers.laser_components.heaters.heaters.Heater
                                pychilaslasers.laser_components.laser_component.LaserComponent --> pychilaslasers.laser_components.driver.Driver
                




              click pychilaslasers.laser_components.heaters.SmallRing href "" "pychilaslasers.laser_components.heaters.SmallRing"
              click pychilaslasers.laser_components.heaters.heaters.Heater href "" "pychilaslasers.laser_components.heaters.heaters.Heater"
              click pychilaslasers.laser_components.driver.Driver href "" "pychilaslasers.laser_components.driver.Driver"
              click pychilaslasers.laser_components.laser_component.LaserComponent href "" "pychilaslasers.laser_components.laser_component.LaserComponent"
            

Small ring heater component.

Source code in src/pychilaslasers/laser_components/heaters/heaters.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def __init__(self, laser: Laser) -> None:
    """Initialize the heater component.

    Sets up the heater with its operating limits and units by
    querying the laser hardware.

    Args:
        laser: The laser instance to control.

    """
    super().__init__(laser)
    self._min: float = float(self._comm.query(f"DRV:LIM:MIN? {self.channel.value}"))
    self._max: float = float(self._comm.query(f"DRV:LIM:MAX? {self.channel.value}"))
    self._unit: str = self._comm.query(f"DRV:UNIT? {self.channel.value}").strip()
Attributes
channel: HeaterChannel property

Get the small ring channel.

TunableCoupler(laser: Laser)

Bases: Heater


              flowchart TD
              pychilaslasers.laser_components.heaters.TunableCoupler[TunableCoupler]
              pychilaslasers.laser_components.heaters.heaters.Heater[Heater]
              pychilaslasers.laser_components.driver.Driver[Driver]
              pychilaslasers.laser_components.laser_component.LaserComponent[LaserComponent]

                              pychilaslasers.laser_components.heaters.heaters.Heater --> pychilaslasers.laser_components.heaters.TunableCoupler
                                pychilaslasers.laser_components.driver.Driver --> pychilaslasers.laser_components.heaters.heaters.Heater
                                pychilaslasers.laser_components.laser_component.LaserComponent --> pychilaslasers.laser_components.driver.Driver
                




              click pychilaslasers.laser_components.heaters.TunableCoupler href "" "pychilaslasers.laser_components.heaters.TunableCoupler"
              click pychilaslasers.laser_components.heaters.heaters.Heater href "" "pychilaslasers.laser_components.heaters.heaters.Heater"
              click pychilaslasers.laser_components.driver.Driver href "" "pychilaslasers.laser_components.driver.Driver"
              click pychilaslasers.laser_components.laser_component.LaserComponent href "" "pychilaslasers.laser_components.laser_component.LaserComponent"
            

Tunable coupler heater component.

Source code in src/pychilaslasers/laser_components/heaters/heaters.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def __init__(self, laser: Laser) -> None:
    """Initialize the heater component.

    Sets up the heater with its operating limits and units by
    querying the laser hardware.

    Args:
        laser: The laser instance to control.

    """
    super().__init__(laser)
    self._min: float = float(self._comm.query(f"DRV:LIM:MIN? {self.channel.value}"))
    self._max: float = float(self._comm.query(f"DRV:LIM:MAX? {self.channel.value}"))
    self._unit: str = self._comm.query(f"DRV:UNIT? {self.channel.value}").strip()
Attributes
channel: HeaterChannel property

Get the tunable coupler channel.

PhaseSection(laser: Laser)

Bases: Heater


              flowchart TD
              pychilaslasers.laser_components.heaters.PhaseSection[PhaseSection]
              pychilaslasers.laser_components.heaters.heaters.Heater[Heater]
              pychilaslasers.laser_components.driver.Driver[Driver]
              pychilaslasers.laser_components.laser_component.LaserComponent[LaserComponent]

                              pychilaslasers.laser_components.heaters.heaters.Heater --> pychilaslasers.laser_components.heaters.PhaseSection
                                pychilaslasers.laser_components.driver.Driver --> pychilaslasers.laser_components.heaters.heaters.Heater
                                pychilaslasers.laser_components.laser_component.LaserComponent --> pychilaslasers.laser_components.driver.Driver
                




              click pychilaslasers.laser_components.heaters.PhaseSection href "" "pychilaslasers.laser_components.heaters.PhaseSection"
              click pychilaslasers.laser_components.heaters.heaters.Heater href "" "pychilaslasers.laser_components.heaters.heaters.Heater"
              click pychilaslasers.laser_components.driver.Driver href "" "pychilaslasers.laser_components.driver.Driver"
              click pychilaslasers.laser_components.laser_component.LaserComponent href "" "pychilaslasers.laser_components.laser_component.LaserComponent"
            

Phase section heater component.

Source code in src/pychilaslasers/laser_components/heaters/phase_section.py
41
42
43
44
45
46
47
48
49
50
def __init__(self, laser: Laser) -> None:
    """Initialize the phase section heater component."""
    super().__init__(laser)

    self._anti_hyst_enabled = True

    self._volts: None | list[float] = None
    self._time_steps: None | list[float] = None

    self._anti_hyst = self.get_antihyst_method(laser=laser)
Attributes
anti_hyst: bool property writable

Get the anti-hysteresis flag.

channel: HeaterChannel property

Get the phase section channel.

value: float property writable

Get the current phase section heater drive value.

Returns:

  • float

    The current heater drive value.

Functions
calibrate(laser: Laser, calibration: Calibration) -> None

Calibrate the phase section heater with the given laser and calibration.

Parameters:

  • laser (Laser) –

    The laser instance to use for calibration.

  • calibration (Calibration) –

    The calibration object containing calibration data.

Source code in src/pychilaslasers/laser_components/heaters/phase_section.py
67
68
69
70
71
72
73
74
75
76
77
78
def calibrate(self, laser: Laser, calibration: Calibration) -> None:
    """Calibrate the phase section heater with the given laser and calibration.

    Args:
        laser: The laser instance to use for calibration.
        calibration: The calibration object containing calibration data.
    """
    self._anti_hyst = self.get_antihyst_method(
        laser=laser,
        voltage_steps=calibration.tune_settings.anti_hyst_voltages,
        time_steps=calibration.tune_settings.anti_hyst_times,
    )
get_antihyst_method(laser: Laser, voltage_steps: list[float] | None = None, time_steps: list[float] | None = None) -> Callable[[float | None], None] staticmethod

Construct an anti-hysteresis correction function for the laser.

This method takes a laser object and returns an appropriate anti-hyst func that can be used independently.

Parameters:

  • laser (Laser) –

    The laser instance to apply anti-hysteresis correction to.

  • voltage_steps (list[float] | None, default: None ) –

    Optional list of voltage step values for the anti-hysteresis procedure. Defaults will be used if None provided.

  • time_steps (list[float] | None, default: None ) –

    Optional list of time step durations (in ms) for each voltage step. Defaults will be used if None provided.

Returns:

  • Callable[[float | None], None]

    A callable that applies anti-hysteresis correction when invoked with an optional phase voltage.

Source code in src/pychilaslasers/laser_components/heaters/phase_section.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
@staticmethod
def get_antihyst_method(
    laser: Laser,
    voltage_steps: list[float] | None = None,
    time_steps: list[float] | None = None,
) -> Callable[[float | None], None]:
    """Construct an anti-hysteresis correction function for the laser.

    This method takes a laser object and returns an appropriate anti-hyst func
    that can be used independently.

    Args:
        laser: The laser instance to apply anti-hysteresis correction to.
        voltage_steps: Optional list of voltage step values for the
            anti-hysteresis procedure. Defaults will be used if None provided.
        time_steps: Optional list of time step durations (in ms) for
            each voltage step. Defaults will be used if None provided.

    Returns:
        A callable that applies anti-hysteresis correction when invoked with
          an optional phase voltage.
    """
    query: Callable[[str], str] = laser.comm.query

    phase_min: float
    phase_max: float

    try:
        phase_max = laser._manual_mode.phase_section.max_value
        phase_min = laser._manual_mode.phase_section.min_value
    except AttributeError as e:
        if laser.system_state:
            phase_max = float(
                laser.comm.query(f"DRV:LIM:MAX? {PhaseSection.channel}")
            )
            phase_min = float(
                laser.comm.query(f"DRV:LIM:MIN? {PhaseSection.channel}")
            )
        else:
            raise ModeError(
                "Phase section min-max values could not be obtained", laser.mode
            ) from e

    voltage_steps = (
        Defaults.TUNE_ANTI_HYST[0] if voltage_steps is None else voltage_steps
    )
    time_steps = Defaults.TUNE_ANTI_HYST[0] if time_steps is None else time_steps

    time_steps = (
        [time_steps[0]] * (len(voltage_steps) - 1) + [0]
        if len(time_steps) == 1
        else [*time_steps, 0]
    )

    def antihyst(v_phase: float | None = None) -> None:
        """Apply anti-hysteresis correction to the laser.

        Applies a voltage ramping procedure to the phase section heater to
        minimize hysteresis effects during wavelength changes. The specifics of
        this method are laser-dependent and are specified as part of the calibration
        data.
        """
        if v_phase is None:
            v_phase = float(query(f"DRV:D? {HeaterChannel.PHASE_SECTION.value:d}"))

        for i, voltage_step in enumerate(voltage_steps):
            if v_phase**2 + voltage_step < 0:
                value: float = 0
                logging.getLogger(__name__).warning(
                    "Anti-hysteresis "
                    f"value out of bounds: {value} (min: {phase_min}, max: "
                    f"{phase_max}). Approximating by 0"
                )
            else:
                value = sqrt(v_phase**2 + voltage_step)
            if value < phase_min or value > phase_max:
                logging.getLogger(__name__).error(
                    "Anti-hysteresis"
                    f"value out of bounds: {value} (min: {phase_min}, max: "
                    f"{phase_max}). Approximating with the closest limit."
                )
                value = min(value, phase_max)
                value = max(value, phase_min)
            query(f"DRV:D {HeaterChannel.PHASE_SECTION.value:d} {value:.4f}")
            sleep(time_steps[i] / 1000)

    return antihyst

pychilaslasers.laser_components.heaters.HeaterChannel

Bases: Enum


              flowchart TD
              pychilaslasers.laser_components.heaters.HeaterChannel[HeaterChannel]

              

              click pychilaslasers.laser_components.heaters.HeaterChannel href "" "pychilaslasers.laser_components.heaters.HeaterChannel"