Source code for hardware_interfaces.polarizer

# Helper modules
from typing import List, Tuple
import logging

# Import relevant modules
import nidaqmx as ni
from nidaqmx import task as ni_task
import time

# Set up logger
logger = logging.getLogger(__name__)


[docs]class Polarizer: """ This class can be used to change polarization of a polarizer from parallel to perpendicular by applying 5V or 0V to their inputs. It is assumed that a National Instruments nidaqmx capable device is used to provide the output voltage. For this a digital output port is used. By default, applying 5V means parallel polarization, while perpendicular polarization implies 0 V. The time it takes for a polarizer to rotate is around 10 ms. Waiting 500 ms should be enough to ensure that the process of rotating finishes. Args: device_name (str): Name of device on which the appropriate voltage-out port is located. The name can be found and configured in the National Instruments Software: 'Measurement and Automation Explorer' (MAX). The device name should also be displayed in a pop-up when plugging in the device. * E.g.: "Dev0", "Dev1" etc. channel (str): Name of channel, that is used to send signal. * E.g.: "do0", "do1", "PFI0", "PFI1" etc. waiting_time (float, optional): Time in milliseconds to wait for the polarizer to turn. Defaults to 50 ms. default_position (bool, optional): Set to True if default state is parallel. Set to False if default state is perpendicular. Defaults to False. parallel_electrical_state (bool, optional): Set to True if to set parallel polarization a digital high signal (5V) needs to be sent. Set to False if to set parallel polarization polarizer a digital low (0V) needs to be applied. Defaults to True. name (str, optional): Name / Identifier to give to this polarizer. This is relevant for log statements, especially when there is more than one polarizer in the setup. Defaults to "XYZ polarizer". Attributes: task (object): Represents a DAQmx Task object, through which all communication with device is managed. current_position (bool): True when polarizer is parallel. False when polarizer is perpendicular. channel (object): DAQmx channel object representing the output channel. References: | https://nidaqmx-python.readthedocs.io/en/latest/index.html | https://nidaqmx-python.readthedocs.io/en/latest/task.html """ def __init__( self, device_name: str, channel: str, waiting_time: float = 500, default_position: bool = False, parallel_electrical_state: bool = True, name: str = "XYZ Polarizer", ) -> "Polarizer": # Set attributes self.name = name self.default_position = default_position self.parallel_electrical_state = parallel_electrical_state self.waiting_time = waiting_time self.current_position = None # Initialise nidaqmx task object self.task = ni_task.Task(self.name) logger.info("Initialized nidaqmx task for {}.".format(self.name)) # Connect to appropriate digital out channel self.channel = self.task.do_channels.add_do_chan( r"/{}/{}".format(device_name, channel) ) # See nidaqmx.task.do_channel documentation logger.info( "Set {} as digital output channel for {}.".format(self.channel, self.name) ) # Set polarisator to default state self.set_to_default_polarization() def __wait(self): """ Puts thread to sleep for specified waiting time in milliseconds using the time module. """ logger.info( "Waiting {} ms for {} to complete movement.".format( self.waiting_time, self.name ) ) time.sleep(self.waiting_time / 1000) # Put thread to sleep logger.info("Waiting time for {} completed.".format(self.name))
[docs] def set_parallel(self): """ Sets polarizer to parallel polarization. Then waits for specified waiting time. """ # Check whether if polarizer is already set to parallel polarization if self.current_position == True: logger.info( "{} is already set to parallel polarization. Doing nothing.".format( self.name ) ) return # Exit function / Skip rest of code if ( self.parallel_electrical_state == True ): # Decide whether high or low needs to be sent. self.task.write(True) logger.info( "{} is set to parallel polarization by sending 5V signal.".format( self.name ) ) elif self.parallel_electrical_state == False: self.task.write(False) logger.info( "{} is set to parallel polarization by sending 0V signal.".format( self.name ) ) self.__wait() self.current_position = True
[docs] def set_perpendicular(self): """ Sets polarizer to perpendicular polarization. Then waits for specified waiting time. """ # Check whether if polarizer is already at perpendicular polarization if self.current_position == False: logger.info( "{} is already at perpendicular polarization. Doing nothing.".format( self.name ) ) return # Exit function / Skip rest of code if ( self.parallel_electrical_state == True ): # Decide whether high or low needs to be sent. self.task.write(False) logger.info( "{} is set to perpendicular polarization by sending 0V signal.".format( self.name ) ) elif self.parallel_electrical_state == False: self.task.write(True) logger.info( "{} is set to perpendicular polarization by sending 5V signal.".format( self.name ) ) self.__wait() self.current_position = False
[docs] def set_to_default_polarization(self): """ Set polarizer to its default position/ polarization. """ logger.info("Setting {} to default position/ polarization.".format(self.name)) # Manage initialization by setting current position/ # polarization to opposite of default position/ polarization. if self.current_position == None: self.current_position = not self.default_position # Set polarizer to default postion/ polarization if self.default_position == True: self.set_parallel() elif self.default_position == False: self.set_perpendicular()
[docs] def end(self): """ Set polarizer to default position/ polarization and ends nidaqmx task. """ logger.info("Setting {} to default polarization to end task.".format(self.name)) self.set_to_default_polarization() self.task.close() logger.info("Connection to {} terminated.".format(self.name))
def __enter__(self): return self def __exit__(self, type, value, traceback): self.end()