def red_laser_channels(): ''' ## Intensity Controls `red_cavity_power` Controls the trap light power going into the cavity axis via error offset into a (PI) power lockbox. This RF signal is switched via `red_cavity_power_switch`. `red_cavity_power_switch` has some crosstalk with Channel 8 on Dev 6. `red_transverse_power` Controls the light power for the transverse trapping beam, which is oriented along the y-axis (lab frame). ''' AnalogOut( name = 'red_cavity_power', parent_device = ni_pci_6723_dev3, connection = 'ao0', limits = None ) AnalogOut( name = 'red_transverse_power', parent_device = ni_pci_6723_dev3, connection = 'ao5' ) DigitalOut( name = 'red_cavity_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line9' )
def add_device(self, device): if not device.connection == 'trigger': raise LabscriptError('The \'connection\' string of device %s ' % device.name + 'to %s must be \'trigger\', not \'%s\'' % (self.name, repr(device.connection))) AnalogOut.add_device(self, device)
def __init__(self, name, parent_device, connection, voltage, trigger_edge_type='rising', **kwargs): self.voltage = voltage AnalogOut.__init__(self, name, parent_device, connection, **kwargs) self.trigger_edge_type = trigger_edge_type if self.trigger_edge_type == 'rising': self.enable = self.go_high_analog self.disable = self.go_low_analog self.allowed_states = {1: 'enabled', 0: 'disabled'} elif self.trigger_edge_type == 'falling': self.enable = self.go_low_analog self.disable = self.go_high_analog self.allowed_states = {1: 'disabled', 0: 'enabled'} else: raise ValueError( 'trigger_edge_type must be \'rising\' or \'falling\', not \'%s\'.' % trigger_edge_type) # A list of the times this trigger has been asked to trigger: self.triggerings = []
def __init__(self,name,parent_device,com_port='COM1',FMSignal=None,RFOnOff=None,freq_limits = None,freq_conv_class = None,freq_conv_params = {},amp_limits=None,amp_conv_class = None,amp_conv_params = {},phase_limits=None,phase_conv_class = None,phase_conv_params = {}): #self.clock_type = parent_device.clock_type # Don't see that this is needed anymore IntermediateDevice.__init__(self,name,parent_device) self.BLACS_connection = com_port self.sweep_dt = 2e-6 self.RFSettings = { 'freq': 0, 'amp': 0, 'phase': 0, 'freq_dev':0 ##EE } self.sweep_params = { # 'type': None, 'low': 0, 'high': 1, 'duration': 0, # 'falltime': 0, 'sample_rate': self.sweep_dt } self.sweep = False self.ext_in = False self.frequency = StaticAnalogQuantity(self.name+'_freq',self,'freq',freq_limits,freq_conv_class,freq_conv_params) self.amplitude = StaticAnalogQuantity(self.name+'_amp',self,'amp',amp_limits,amp_conv_class,amp_conv_params) self.phase = StaticAnalogQuantity(self.name+'_phase',self,'phase',phase_limits,phase_conv_class,phase_conv_params) self.FMSignal = {} self.RFOnOff = {} if FMSignal: if 'device' in FMSignal and 'connection' in FMSignal: self.FMSignal = AnalogOut(self.name+'_FMSignal', FMSignal['device'], FMSignal['connection']) else: raise LabscriptError('You must specify the "device" and "connection" for the analog output FMSignal of '+self.name) else: raise LabscriptError('Expected analog output for "FMSignal" control') if RFOnOff: if 'device' in RFOnOff and 'connection' in RFOnOff: self.RFOnOff = DigitalOut(self.name+'_RFOnOff', RFOnOff['device'], RFOnOff['connection']) else: raise LabscriptError('You must specify the "device" and "connection" for the digital output RFOnOff of '+self.name) else: raise LabscriptError('Expected digital output for "RFOnOff" control')
def undocumented_channels(): # DigitalOut( # name = 'UNDOCUMENTED_switch_for_phase_reference', # parent_device = ni_pci_6284_dev6, # connection = 'port0/line14' # ) AnalogOut( name = 'UNDOCUMENTED_unused_1', parent_device = ni_pci_6723_dev3, connection = 'ao6' )
def blue_laser_channels(): ''' ###`blue_mot_power` This controls the power to our 399nm laser. It currently needs no distinction, as we only have one blue laser beam path: the MOT beampath. ###`blue_mot_shutter` This controls the shutter for the MOT beampath. ###`imaging_power_switch` Controls the RF switch for the 399nm Imaging Light beampath. ###`imaging_power_shutter` Controls the shutter for the 399nm Imaging Light beampath. ''' AnalogOut( name = 'blue_mot_power', parent_device = ni_pci_6713_dev4, connection = 'ao0', limits = None ) DigitalOut( name = 'blue_mot_shutter', parent_device = ni_pci_6284_dev6, connection = 'port0/line1' ) DigitalOut( name = 'imaging_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line6' ) DigitalOut( name = 'imaging_power_shutter', parent_device = ni_pci_6284_dev6, connection = 'port0/line7' )
def magnetic_field_channels(): ''' ## Bias Fields These are the magnetic fields that are intended to be uniform across the atoms. `x_bias_field` `y_bias_field` `z_bias_field` ## MOT Coil This creates the large quadrupole field for trapping and cooling the atoms. `mot_coil_current` & `mot_coil_voltage` control the voltage and current setpoint to a power supply. Just like small benchtop supplies, setting one too large places it in either constant voltage mode or constant current mode. ## Rabi Coil This drives AC fields along the x-direction (lab frame). This is for driving nuclear spin flips. The Rabi Coil was designed in a idiosyncratic manner. Given our difficulties in creating bipolar current controllers, we came up with a method for driving AC fields with unipolar current controllers. We have two coils wound together, and we drive currents in opposite directions. This causes zero magnetic field. We then modulate each current in opposite amounts causing a net AC field. `rabi_coil_dc_offset` controls that DC offset. `rabi_coil_field` controls that differential offset, and thus magnetic field that the atoms do see. ''' AnalogOut( name = 'x_bias_field', parent_device = ni_pci_6713_dev4, connection = 'ao1', limits = None ) AnalogOut( name = 'y_bias_field', parent_device = ni_pci_6713_dev4, connection = 'ao2', limits = None ) AnalogOut( name = 'z_bias_field', parent_device = ni_pci_6713_dev4, connection = 'ao3', limits = None ) #sets the voltage on the mot coil current controller. #for constant current mode, voltage needs to be larger than actual, #for constant voltage mode, current needs to be larger than actual. AnalogOut( name = 'mot_coil_current', parent_device = ni_pci_6713_dev4, connection = 'ao5', limits = None ) AnalogOut( name = 'mot_coil_voltage', parent_device = ni_pci_6723_dev3, connection = 'ao3', limits = None ) # # Rabi Coil # AnalogOut( name = 'rabi_coil_dc_offset', parent_device = ni_pci_6713_dev5, connection = 'ao4' ) AnalogOut( name = 'rabi_coil_field', parent_device = ni_pci_6713_dev4, connection = 'ao7' )
def green_laser_channels(): ''' Control the power and shutters of the various green beams as well as the frequency. ##Beampaths Polarizations are defined with respect to the magnetic field bias. This is currently pointing up. ### Probe Beampath This is beampath for the light going into the cavity **for measurement**. It's \\(\\sigma+\\) polarized. #### Probe Sideband The Probe carrier frequency is actually a little far off from the atom+cavity resonance. The Probe Sideband is what actually interacts with the atoms+cavity. One can say the 'Probe Sideband' is the actual probing beam. Unfortunately, 'Probe' is more of a name for the ultimate use of the beam path rather than it's initial spectral content. This makes things confusing. We can try and help by saying that the naming convention in the lab is labeled by its final state. This makes it difficult to understand its evolution through the system but that's the way things are. #### Two Color Probe Sidebands (of the Probe Sideband) We have a **phase** measurement technique where we center the probe sideband frequency at the center of the atom + cavity resonances, then we apply modulation \\(f_m\\) to split this sideband in two. This allows us to drive two colors of light into the two modes of the atom + cavity system. Since these two beams share the same spatial mode, they interfere at the photodetector giving us a signal that, at least somewhat, looks like \\(\\cos(f_m t + \\phi) \\) where \\(\\phi\\) is the phase shift imparted by one of the atom + cavity transmission peaks. ### Pump Beampath This goes into the cavity axis. It's used polarizing the atoms in the up state. It's \\(\\sigma+\\) polarized. ### Cooling Beampath This is greenlight coming perpendicular to the cavity axis. It's \\(\\pi\\) polarized. ### Green MOT Beampath It has a complicated beam path. Green comes in from all directions. .. figure:: ./imgs/mot_path.png ##Analog Intensity Controls ###`probe_sideband_power` This controls the **sideband light** power via Mixer + Amplifier into an **EOM**. ###`two_color_probe_sideband_power` The probe sideband is split in two via EOM modulation. See the above section. **We think** that this controls the modulation strength and thus the ratio of the probe sideband and these two color sidebands, but are not sure. ###`probe_power_lock_error_offset` This controls an error offset to the `probe_sideband_power` lock. Typically, this constant across a whole experimental run. ###`pump_power` This controls the power via Mixer + Amplifier into an **AOM**. ###`cooling_pi_power` Currently not connected. ###`cooling_sigma_plus_power` Controls the power of the \\(\\sigma +\\) light feeding into the cavity axis for cooling purposes via **EOM**. ###`green_mot_power` Controls the power of the Green MOT via **AOM**. ##Digital Intensity Controls All the channels in this section turn off all the RF power to the AOM/EOM via an RF switch. ###`green_mot_power_switch` Controlled via MOT AOM. ###`probe_power_switch` Controlled via AOM. ###`probe_sideband_power_switch` Controlled via EOM. ###`pump_power_switch` Controlled via AOM. ###`cooling_pi_power_switch` Controlled via AOM. ###`probe_sideband_cooling_rf_switch` Is the TTL for an RF switch for changing the frequency fed into the eom for the probe/cooling path. ##Shutter Controls Aren't these just intensity controls? Yes, but they block the light better than turning off the EOM/AOM can. So a shutter helps ensure the light is really off. Ofcourse, they are slower so they are used in conjunction with an AOM/EOM RF control. ###`green_mot_shutter` ###`cooling_pi_shutter` ###`probe_shutter` Located almost just before entering the cavity mirror. It's beneath the optics table. ###`probe_sideband_cooling_shutters` This output actually controls two shutters. For `go_high`, the cooling path is open. For `go_low`, the probe sideband path is open. ## Frequency Control ###`probe_sideband_frequency` Controls the frequency of the EOM modulation, thus letting us control the detuning from the atom + cavity system. ###`two_color_chirp` Triggers the SRS to begin the frequency sweep for the phase measurement. ###`cooling_sideband_frequency` (SRS FM input) An analog input feeding into an SRS to control the Frequency Modulation. Thus, it's effectively a VCO. This VCO is driving the same EOM as the `probe_sideband_frequency` channel controls. We need a TTL to switch between the probe and cooling settings. One for the shutter, and one for the RF switch. ## FPGA Trigger There is an FPGA (Opal Kelly) that controls the frequencies of a Double Pass AOM early in the beampath. So it controls all the frequencies of all the beampaths. This FPGA controls the PTS synthesizer on top of the canopy of the lab. The frequencies are defined in an external program "FrontPanel.exe". There's a short cut to it on the desktop. ''' # # Intensity Controls # AnalogOut( name = 'probe_sideband_power', parent_device = ni_pci_6713_dev5, connection = 'ao0' ) AnalogOut( name = 'probe_power_lock_error_offset', parent_device = ni_pci_6713_dev5, connection = 'ao5' ) DigitalOut( name = 'probe_sideband_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line23' ) DigitalOut( name = 'probe_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line10', inverted = True ) AnalogOut( name = 'two_color_probe_sideband_power', parent_device = ni_pci_6713_dev5, connection = 'ao1' ) DigitalOut( name = 'probe_shutter', parent_device = ni_pci_6284_dev6, connection = 'port0/line12' ) AnalogOut( name = 'pump_power', parent_device = ni_pci_6713_dev5, connection = 'ao7', ) DigitalOut( name = 'pump_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line8' ) AnalogOut( name = 'cooling_pi_power', parent_device = ni_pci_6713_dev5, connection = 'ao6', ) DigitalOut( name = 'cooling_pi_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line24' ) AnalogOut( name = 'cooling_sigma_plus_power', parent_device = ni_pci_6723_dev3, connection = 'ao4' ) AnalogOut( name = 'green_mot_power', parent_device = ni_pci_6713_dev4, connection = 'ao4', limits = None ) DigitalOut( name = 'green_mot_power_switch', parent_device = ni_pci_6284_dev6, connection = 'port0/line2' ) DigitalOut( name = 'probe_sideband_cooling_rf_switch', #Old name: ProbeEOMPowerSelect (0=VCO 1=SRS) parent_device = ni_pci_6284_dev6, connection = 'port0/line29' ) # # Shutters # DigitalOut( name = 'cooling_pi_shutter', parent_device = ni_pci_6284_dev6, connection = 'port0/line25' ) DigitalOut( name = 'green_mot_shutter', parent_device = ni_pci_6284_dev6, connection = 'port0/line4' ) DigitalOut( name = 'green_frequency_fpga_trigger', parent_device = ni_pci_6284_dev6, connection = 'port0/line3' ) DigitalOut( name = 'probe_sideband_cooling_shutters', parent_device = ni_pci_6284_dev6, connection = 'port0/line16' ) # # Frequency Controls # AnalogOut( name = 'probe_sideband_frequency', parent_device = ni_pci_6713_dev4, connection = 'ao6', unit_conversion_class = GreenFrequencyVCOCalibration, unit_conversion_parameters = { 'raw_voltage' : vco_raw_voltage_data, 'raw_frequency' : vco_raw_frequency_data } ) AnalogOut( name = 'cooling_sideband_frequency', parent_device = ni_pci_6723_dev3, connection = 'ao2' ) DigitalOut( name = 'two_color_chirp', parent_device = ni_pci_6284_dev6, connection = 'port0/line5' )
trigger_device=ni_card_0, trigger_connection="port0/line15", usbport="COM7", ) NI_PCI_6733( name="ni_card_1", parent_device=pineblaster_0.clockline, clock_terminal="ni_pcie_6733_0/PFI0", MAX_name="ni_pci_6733_0", ) # Create the output/input channels on the above devices use the example1 conversion # class located in pythonlib/unitconversions/example.py with default paremeters AnalogOut( name="analog0", parent_device=ni_card_1, connection="ao0", unit_conversion_class=example1, ) # same as above, but we are changing some parameters used in the conversion and # specifying a prefix to be used with units. You can now program in mA, uA, mGauss, # uGauss AnalogOut( name="analog1", parent_device=ni_card_1, connection="ao1", unit_conversion_class=example1, unit_conversion_parameters={"a": 5, "b": 1, "magnitudes": ["m", "u"]}, ) AnalogOut(name="analog2", parent_device=ni_card_0, connection="ao2") AnalogOut(name="analog3", parent_device=ni_card_0, connection="ao3")
from labscript import start, stop, add_time_marker, AnalogOut, DigitalOut from labscript_devices.DummyPseudoclock.labscript_devices import DummyPseudoclock from labscript_devices.DummyIntermediateDevice import DummyIntermediateDevice # Use a virtual, or 'dummy', device for the psuedoclock DummyPseudoclock(name='pseudoclock') # An output of this DummyPseudoclock is its 'clockline' attribute, which we use # to trigger children devices DummyIntermediateDevice(name='intermediate_device', parent_device=pseudoclock.clockline) # Create an AnalogOut child of the DummyIntermediateDevice AnalogOut(name='analog_out', parent_device=intermediate_device, connection='ao0') # Create a DigitalOut child of the DummyIntermediateDevice DigitalOut(name='digital_out', parent_device=intermediate_device, connection='port0/line0') # Begin issuing labscript primitives # A timing variable t is used for convenience # start() elicits the commencement of the shot t = 0 add_time_marker(t, "Start", verbose=True) start() # Wait for 1 second with all devices in their default state t += 1
) import sys sys.excepthook = sys.__excepthook__ # labscript_init('test.h5', new=True, overwrite=True) PulseBlasterUSB('pulseblaster') ClockLine('output_clock', pulseblaster.pseudoclock, 'flag 0') ClockLine('acq_trigger', pulseblaster.pseudoclock, 'flag 1') NI_PCI_6733('Dev1', output_clock, clock_terminal='PFI0') NI_USB_6008('Dev3', acq_trigger, 'PFI0', acquisition_rate=5000) AnalogOut('ao0', Dev1, 'ao0') AnalogOut('ao1', Dev1, 'ao1') # DigitalOut('do0', Dev1, 'port0/line0') # DigitalOut('do1', Dev1, 'port0/line1') StaticAnalogOut('static_ao0', Dev3, 'ao0') StaticAnalogOut('static_ao1', Dev3, 'ao1') StaticDigitalOut('static_do0', Dev3, 'port0/line0') StaticDigitalOut('static_do1', Dev3, 'port1/line1') AnalogIn('ai0', Dev3, 'ai0') AnalogIn('ai1', Dev3, 'ai1') WaitMonitor(
class AgilentE4422B(IntermediateDevice): description = 'Agilent RF Signal Generator' allowed_children = [StaticAnalogQuantity] generation = 2 @set_passed_properties(property_names = { "connection_table_properties": ["com_port"]} ) def __init__(self,name,parent_device,com_port='COM1',FMSignal=None,RFOnOff=None,freq_limits = None,freq_conv_class = None,freq_conv_params = {},amp_limits=None,amp_conv_class = None,amp_conv_params = {},phase_limits=None,phase_conv_class = None,phase_conv_params = {}): #self.clock_type = parent_device.clock_type # Don't see that this is needed anymore IntermediateDevice.__init__(self,name,parent_device) self.BLACS_connection = com_port self.sweep_dt = 2e-6 self.RFSettings = { 'freq': 0, 'amp': 0, 'phase': 0, 'freq_dev':0 ##EE } self.sweep_params = { # 'type': None, 'low': 0, 'high': 1, 'duration': 0, # 'falltime': 0, 'sample_rate': self.sweep_dt } self.sweep = False self.ext_in = False self.frequency = StaticAnalogQuantity(self.name+'_freq',self,'freq',freq_limits,freq_conv_class,freq_conv_params) self.amplitude = StaticAnalogQuantity(self.name+'_amp',self,'amp',amp_limits,amp_conv_class,amp_conv_params) self.phase = StaticAnalogQuantity(self.name+'_phase',self,'phase',phase_limits,phase_conv_class,phase_conv_params) self.FMSignal = {} self.RFOnOff = {} if FMSignal: if 'device' in FMSignal and 'connection' in FMSignal: self.FMSignal = AnalogOut(self.name+'_FMSignal', FMSignal['device'], FMSignal['connection']) else: raise LabscriptError('You must specify the "device" and "connection" for the analog output FMSignal of '+self.name) else: raise LabscriptError('Expected analog output for "FMSignal" control') if RFOnOff: if 'device' in RFOnOff and 'connection' in RFOnOff: self.RFOnOff = DigitalOut(self.name+'_RFOnOff', RFOnOff['device'], RFOnOff['connection']) else: raise LabscriptError('You must specify the "device" and "connection" for the digital output RFOnOff of '+self.name) else: raise LabscriptError('Expected digital output for "RFOnOff" control') def reset(self, t): self.FMSignal.constant(t,-1) return t def synthesizeRF(self, t, freq, amp, ph, freqUnits=None, ampUnits=None, phaseUnits=None): self.RFSettings['freq'] = freq self.RFSettings['amp'] = amp self.RFSettings['phase'] = ph self.sweep = False self.ext_in = False self.FMSignal.constant(t,0) self.RFOnOff.go_high(t) return t def synthesizeRF_ext(self, t, freq, amp, ph, freq_dev, freqUnits=None, ampUnits=None, phaseUnits=None): self.RFSettings['freq'] = freq self.RFSettings['amp'] = amp self.RFSettings['phase'] = ph self.RFSettings['freq_dev'] = freq_dev ##EE self.sweep = False self.ext_in = True self.FMSignal.constant(t,0) #when plugged into the feedforward, needs to be set to 0.017 to account for some offset self.RFOnOff.go_high(t) return t def sweepRF(self, t, duration, low_freq, high_freq, sample_rate, amp): center_freq = np.mean([low_freq,high_freq]) for dev_freq_range in max_deviations: if center_freq > dev_freq_range['low'] and center_freq <= dev_freq_range['high']: deviation = high_freq - center_freq if deviation > dev_freq_range['dev']: raise LabscriptError('Frequency deviation is too high. For a center frequency of '+str(center_freq)+' MHz, the maximum deviation is '+str(dev_freq_range['dev'])+' MHz ('+str(deviation)+' MHz requested)') self.sweep_params['duration'] = duration self.sweep_params['low'] = low_freq self.sweep_params['high'] = high_freq self.sweep_params['sample_rate'] = sample_rate self.RFSettings['freq'] = center_freq self.RFSettings['amp'] = amp self.RFSettings['phase'] = 0 self.sweep = True self.RFOnOff.go_high(t) self.FMSignal.ramp(t,duration=duration,initial=-1.03,final=1.08,samplerate=sample_rate) #To account for the gain of the feedforward box: initial=-0.085 and +final=+1 self.RFOnOff.go_low(t+duration) return t+duration def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) if len(self.child_devices) != 3: raise LabscriptError("Wrong number of child_devices. This device expects exactly 3 children") grp = hdf5_file.create_group('/devices/'+self.name) profile_dtypes = [('freq',np.float), ('phase',np.float), ('amp',np.float), ('ext_in',bool), #EE ('freq_dev',np.float)] #EE profile_table = np.zeros(1, dtype=profile_dtypes) profile_table['freq'] = self.RFSettings['freq'] profile_table['amp'] = self.RFSettings['amp'] profile_table['phase'] = self.RFSettings['phase'] profile_table['ext_in'] = 0 ##EE profile_table['freq_dev'] = 0 #EE ## Emily edit if self.ext_in: profile_table['ext_in'] = 1 profile_table['freq_dev'] = self.RFSettings['freq_dev'] grp.create_dataset('RF_DATA',compression=config.compression,data=profile_table) if self.sweep: sweep_dtypes = [('sweep_low',np.float), ('sweep_high',np.float), ('sweep_duration',np.float), ('sweep_samplerate',np.float)] sweep_table = np.empty(1, dtype=sweep_dtypes) # sweep_table['sweep_type'] = sweep_types[output.sweep_params['type']] sweep_table['sweep_low'] = self.sweep_params['low'] sweep_table['sweep_high'] = self.sweep_params['high'] sweep_table['sweep_duration'] = self.sweep_params['duration'] # sweep_table['sweep_falltime'] = output.sweep_params['falltime'] sweep_table['sweep_samplerate'] = self.sweep_params['sample_rate'] grp.create_dataset('SWEEP_DATA',compression=config.compression,data=sweep_table)