class TestSetContextManager(TestCase): def setUp(self): self.instrument = DummyInstrument('dummy_holder') self.instrument.add_parameter( "a", set_cmd=None, get_cmd=None ) def tearDown(self): self.instrument.close() del self.instrument def test_none_value(self): with self.instrument.a.set_to(3): assert self.instrument.a.get() == 3 assert self.instrument.a.get() is None def test_context(self): self.instrument.a.set(2) with self.instrument.a.set_to(3): assert self.instrument.a.get() == 3 assert self.instrument.a.get() == 2
def SpectrumAnalyzer(): """ Yields a DummyInstrument that holds an ArrayParameter """ class Spectrum(ArrayParameter): def __init__(self, name, instrument): super().__init__( name=name, shape=(1, ), # this attribute should be removed label='Flower Power Spectrum', unit='V/sqrt(Hz)', setpoint_names=('Frequency', ), setpoint_units=('Hz', )) self.npts = 100 self.start = 0 self.stop = 2e6 self._instrument = instrument def get_raw(self): # This is how it should be: the setpoints are generated at the # time we get. But that will of course not work with the old Loop self.setpoints = (tuple( np.linspace(self.start, self.stop, self.npts)), ) # not the best SA on the market; it just returns noise... return np.random.randn(self.npts) SA = DummyInstrument('dummy_SA') SA.add_parameter('spectrum', parameter_class=Spectrum) yield SA SA.close()
def test_get_instr(self): a = DummyInstrument('dummy_holder') d = DummyInstrument('dummy') a.add_parameter('test', parameter_class=InstrumentRefParameter) a.test.set(d.name) self.assertEqual(a.test.get(), d.name) self.assertEqual(a.test.get_instr(), d)
class TestManualParameterValMapping(TestCase): def setUp(self): self.instrument = DummyInstrument('dummy_holder') def tearDown(self): self.instrument.close() del self.instrument def test_val_mapping(self): self.instrument.add_parameter('myparameter', set_cmd=None, get_cmd=None, val_mapping={'A': 0, 'B': 1}) self.instrument.myparameter('A') assert self.instrument.myparameter() == 'A' assert self.instrument.myparameter() == 'A' assert self.instrument.myparameter.raw_value == 0
class TestInstrumentRefParameter(TestCase): def setUp(self): self.a = DummyInstrument('dummy_holder') self.d = DummyInstrument('dummy') def test_get_instr(self): self.a.add_parameter('test', parameter_class=InstrumentRefParameter) self.a.test.set(self.d.name) self.assertEqual(self.a.test.get(), self.d.name) self.assertEqual(self.a.test.get_instr(), self.d) def tearDown(self): self.a.close() self.d.close() del self.a del self.d
class One_tone: def __init__(self, database="./OneTone.db", exp_name="One_Tone"): #sets the defaults values self.__database = database self.__exp_name = exp_name self.__amp = 5 self.__range = [0, 60] self.__samples = 120 self.__freq_time = 0.001 self.__amplitude_range = [6, 12] self.__amplitude_samples = 12 self.__colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] self.__colorN = 0 self.__ax1 = None #to share the graph screen through the class self.__set_qcodes() #print defaults print("database", self.__database) self.print_setup() def help(): print( "To print the variables for the setup use the method print_setup()\ In this function output you can see the methods that change each setup variable and their current values.\ Call each of these methods in order to change their corresponding values. \n\ Methods:\n\ print_setup() prints the current setup of the experiment\n\ \n\ For variables:\n\ freq_range=interval the range of the sweep frequency from beggining to end in the form interval =[beggining, end]\n\ amp_range=interval the range of the sweep amplitude for the double sweep method from beggining to end in the form interval =[beggining, end]\n\ freq_samples=number the number of samples in the for the frequency with number=integer \n\ amp_samples=number the number of samples in the double sweep for the amplitude with number=integer \n\ ampl(voltage) the amplitude for a single sweep in the run() method \n\ freq_time=interval the time duration at which each frequency stays during the sweep step \n\ \ graph_window() opens a window to graph one or more runs. You can open more than one window and the runs will always graph on the last window\n\ \ run(graph=True, amp=-1, legend=True) runs the experiment saving the data to the qcodes database and if graph is True(default) and there is a window open graphs the output too. amp if positive will change the amplitude for the run and legend turns on off the legend in the graph useful for multiple plots in the same window.\n\ \ double_sweep(graph=True) same as run but sweeps both frequency and amplitude and if graph is True and there is a window graphs a pcolor with the data collected. \n\ ") ###### methods to change the experiment setup values ################# #the max and min frequency sweeped by the experiment #getter of the function exp.freq_range returns output @property def freq_range(self): return self.__range #setter of the function use exp.freq_range=value @freq_range.setter def freq_range(self, interval): self.__range = interval self.print_setup() #the max and min frequency sweeped by the experiment @property def amp_range(self): return self.__amplitude_range @amp_range.setter def amp_range(self, interval): self.__amplitude_range = interval self.print_setup() #amp of the input signal of the experiment @property def amp_samples(self): return self.__amplitude_samples @amp_samples.setter def amp_samples(self, number): self.__amplitude_samples = number self.print_setup() #amp of the input signal of the experiment @property def freq_samples(self): return self.__samples @freq_samples.setter def freq_samples(self, number): self.__samples = number self.print_setup() #amp of the input signal of the experiment @property def ampl(self): return self.__amp @ampl.setter def ampl(self, voltage): self.__amp = voltage self.print_setup() #the time that the sweep stays at each frequency @property def freq_time(self): return self.__freq_time @freq_time.setter def freq_time(self, interval): self.__freq_time = interval self.print_setup() ######################################################## #sets up/resets the graph window to display as many graphs as wished on it def graph_window(self): #plot axis to make the points appear in the same graph plt.ion() self.__fig = plt.figure() self.__ax1 = self.__fig.add_subplot() #plt.show(block=False) print("Window set up, run experiments to draw graphs") def list_exps(self): exps = experiments() #loads a database to add the data to it instead of the one opened at the beggining def load_database(self): print("database loaded") #starts experiment def run(self, graph=True, amp=-1, legend=True): dac = self.dac dmm = self.dmm exp = self.exp station = self.station #selects between amp set previously or set in the run call if (amp == -1): dac.amp(self.__amp) amp = self.__amp else: dac.amp(amp) meas = Measurement(exp=exp, station=station) meas.register_parameter( dac.freq) # register the first independent parameter meas.register_parameter(dac.amp) meas.register_parameter( dmm.v1, setpoints=(dac.freq, )) # now register the dependent oone meas.write_period = 2 #plot lables if (self.__ax1 != None and graph): self.__ax1.set_xlabel("Frequency") self.__ax1.set_ylabel("Amplitude measured") title = 'One Tone Spectroscopy sweeping the frequency' self.__ax1.set_title(title) #sets legend with amplitude for each plot to appear first = legend #vectors for plotting Y = [] X = [] with meas.run() as datasaver: #np.linspace is the interval and number of points in the osciloscope for set_v in np.linspace(self.__range[0], self.__range[1], self.__samples): #sets dac ch1 with the set_v value and gets value from v1 dac.freq.set(set_v) get_v = dmm.v1.get() #adds to the datasaver the result datasaver.add_result((dac.freq, set_v), (dmm.v1, get_v)) #stays in one freq so that the osciloscope can measure the necessary sleep(self.__freq_time / 10) #plots graph in real time #checks if there is a canvas to plot in if (self.__ax1 != None and graph): #gets data from dataset to plot X.append(set_v) Y.append(get_v) #plots data with color from array picked by number self.__ax1.plot(X, Y, c=self.__colors[self.__colorN]) #plots once with a label and the legend for it if (first): self.__ax1.plot(X, Y, c=self.__colors[self.__colorN], label='Amplitude ' + str(self.__amp) + 'V') plt.legend(loc='lower right') first = False plt.pause(0.01) #changes color of plot for next time self.__colorN = (self.__colorN + 1) % 7 #adds the amplitude to the dataset as well datasaver.add_result((dac.amp, dac.amp())) self.dataset = datasaver.dataset # convenient to have for plotting print("experiment was run") #starts experiment def double_sweep(self, graph=True): dac = self.dac dmm = self.dmm exp = self.exp station = self.station meas = Measurement(exp=exp, station=station) meas.register_parameter( dac.freq) # register the first independent parameter meas.register_parameter(dac.amp) meas.register_parameter(dmm.v1, setpoints=( dac.freq, dac.amp, )) # now register the dependent oone meas.write_period = 2 if (self.__ax1 != None and graph): self.__ax1.set_xlabel("Frequency of input (Hz)") self.__ax1.set_ylabel("Amplitude of input (V)") self.__ax1.set_title('One Tone Spectroscopy with double sweep') colorbar = False #vectors for plotting Y = [] X = [] C = [] column = -1 with meas.run() as datasaver: for set_v in np.linspace(self.__amplitude_range[0], self.__amplitude_range[1], self.__amplitude_samples): if (self.__ax1 != None and graph): C.append([]) column += 1 Y.append(set_v) dac.amp(set_v) for set_f in np.linspace(self.__range[0], self.__range[1], self.__samples): #sets dac ch1 with the set_v value and gets value from v1 dac.freq.set(set_f) get_v = dmm.v1.get() #adds to the datasaver the result datasaver.add_result((dac.freq, set_f), (dac.amp, set_v), (dmm.v1, get_v)) #stays in one freq so that the osciloscope can measure the necessary sleep(self.__freq_time) #plots graph in real time #checks if there is a canvas to plot in if (self.__ax1 != None and graph): #gets data from dataset to plot X.append(set_f) C[column].append(get_v) #plots data with color from array picked by number #the pcolor doesn't do well with imcomplete lines/columns alongside imcomplete ones so it' at the end of the main loop if (self.__ax1 != None and graph): #removes repeated colorbars if (colorbar): colorbar.remove() graph_colors = self.__ax1.pcolor(X, Y, C) colorbar = self.__fig.colorbar(graph_colors, ax=self.__ax1) colorbar.set_label('Amplitude of output (V)', rotation=270, labelpad=15) plt.pause(0.01) X = [] #changes color of plot for next time self.__colorN = (self.__colorN + 1) % 7 #adds the amplitude to the dataset as well datasaver.add_result((dac.amp, dac.amp())) self.dataset = datasaver.dataset # convenient to have for plotting print("experiment was run") #prints the experiment setup values def print_setup(self): print("freq_range", self.__range, "Hz | freq_samples", self.__samples, "|freq_time", self.__freq_time, "|ampl", self.__amp, "V") print("amp_range", self.__amplitude_range, "V | amp_samples", self.__amplitude_samples) #sets up the qcodes code to run the experiment def __set_qcodes(self): initialise_or_create_database_at(self.__database) self.station = Station() #### instruments needs change # A dummy instrument dac with two parameters ch1 and ch2 self.dac = DummyInstrument('dac', gates=['amp']) # A dummy instrument dmm with two parameters ch1 and Ch2 self.dmm = DummyInstrument('dmm', gates=['v1']) #These are the parameters which come ready to use from the intruments drivers #dac.add_parameter('amp',label='Amplitude', unit="V", get_cmd=None, set_cmd=None) self.dac.add_parameter('freq', label='Frequency', unit="Hz", get_cmd=None, set_cmd=None) #puts current time in a string to facilitate control of the samples #makes the sample name now = datetime.now() now = now.strftime("%Y-%m-%d_%H-%M-%S") print(now) #the experiment is a unit of data inside the database it's made #out self.exp = load_or_create_experiment(experiment_name=self.__exp_name, sample_name=now) self.dmm.v1 = dmm_parameter('dmm_v1', self.dac)
class TestSetContextManager(TestCase): def setUp(self): self.instrument = DummyInstrument('dummy_holder') self.instrument.add_parameter("a", set_cmd=None, get_cmd=None) # These two parameters mock actual instrument parameters; when first # connecting to the instrument, they have the _latest["value"] None. # We must call get() on them to get a valid value that we can set # them to in the __exit__ method of the context manager self.instrument.add_parameter("validated_param", set_cmd=self._vp_setter, get_cmd=self._vp_getter, vals=vals.Enum("foo", "bar")) self.instrument.add_parameter("parsed_param", set_cmd=self._pp_setter, get_cmd=self._pp_getter, set_parser=int) # A parameter that counts the number of times it has been set self.instrument.add_parameter("counting_parameter", set_cmd=self._cp_setter, get_cmd=self._cp_getter) # the mocked instrument state values of validated_param and # parsed_param self._vp_value = "foo" self._pp_value = 42 # the counter value for counting_parameter self._cp_counter = 0 self._cp_get_counter = 0 def _vp_getter(self): return self._vp_value def _vp_setter(self, value): self._vp_value = value def _pp_getter(self): return self._pp_value def _pp_setter(self, value): self._pp_value = value def _cp_setter(self, value): self._cp_counter += 1 def _cp_getter(self): self._cp_get_counter += 1 return self.instrument['counting_parameter'].cache._value def tearDown(self): self.instrument.close() del self.instrument def test_set_to_none_when_parameter_is_not_captured_yet(self): counting_parameter = self.instrument.counting_parameter # Pre-conditions: assert self._cp_counter == 0 assert self._cp_get_counter == 0 assert counting_parameter.cache._value is None assert counting_parameter.get_latest.get_timestamp() is None with counting_parameter.set_to(None): # The value should not change assert counting_parameter.cache._value is None # The timestamp of the latest value should not be None anymore assert counting_parameter.get_latest.get_timestamp() is not None # Set method is not called assert self._cp_counter == 0 # Get method is called once assert self._cp_get_counter == 1 # The value should not change assert counting_parameter.cache._value is None # The timestamp of the latest value should still not be None assert counting_parameter.get_latest.get_timestamp() is not None # Set method is still not called assert self._cp_counter == 0 # Get method is still called once assert self._cp_get_counter == 1 def test_set_to_none_for_not_captured_parameter_but_instrument_has_value(self): # representing instrument here instr_value = 'something' set_counter = 0 def set_instr_value(value): nonlocal instr_value, set_counter instr_value = value set_counter += 1 # make a parameter that is linked to an instrument p = Parameter('p', set_cmd=set_instr_value, get_cmd=lambda: instr_value, val_mapping={'foo': 'something', None: 'nothing'}) # pre-conditions assert p.cache._value is None assert p.cache._raw_value is None assert p.cache.timestamp is None assert set_counter == 0 with p.set_to(None): # assertions after entering the context assert set_counter == 1 assert instr_value == 'nothing' assert p.cache._value is None assert p.cache._raw_value == 'nothing' assert p.cache.timestamp is not None # assertions after exiting the context assert set_counter == 2 assert instr_value == 'something' assert p.cache._value == 'foo' assert p.cache._raw_value == 'something' assert p.cache.timestamp is not None def test_none_value(self): with self.instrument.a.set_to(3): assert self.instrument.a.get_latest.get_timestamp() is not None assert self.instrument.a.get() == 3 assert self.instrument.a.get() is None assert self.instrument.a.get_latest.get_timestamp() is not None def test_context(self): self.instrument.a.set(2) with self.instrument.a.set_to(3): assert self.instrument.a.get() == 3 assert self.instrument.a.get() == 2 def test_validated_param(self): assert self.instrument.parsed_param.cache._value is None assert self.instrument.validated_param.get_latest() == "foo" with self.instrument.validated_param.set_to("bar"): assert self.instrument.validated_param.get() == "bar" assert self.instrument.validated_param.get_latest() == "foo" assert self.instrument.validated_param.get() == "foo" def test_parsed_param(self): assert self.instrument.parsed_param.cache._value is None assert self.instrument.parsed_param.get_latest() == 42 with self.instrument.parsed_param.set_to(1): assert self.instrument.parsed_param.get() == 1 assert self.instrument.parsed_param.get_latest() == 42 assert self.instrument.parsed_param.get() == 42 def test_number_of_set_calls(self): """ Test that with param.set_to(X) does not perform any calls to set if the parameter already had the value X """ assert self._cp_counter == 0 self.instrument.counting_parameter(1) assert self._cp_counter == 1 with self.instrument.counting_parameter.set_to(2): pass assert self._cp_counter == 3 with self.instrument.counting_parameter.set_to(1): pass assert self._cp_counter == 3
# We add a parameter that loudly prints what it is being set to # (It is used below) chX = 0 def myget(): return chX def myset(x): global chX chX = x print('Setting to {}'.format(x)) return None dac.add_parameter('verbose_channel', label='Verbose Channel', unit='V', get_cmd=myget, set_cmd=myset) # # # # Next, the instruments should be bound to a Station. # # Only instruments bound to the Station get recorded in the # # measurement metadata, so your metadata is blind to # # any instrument not in the Station. # # station = qc.Station(dac, dmm, dc) # # Set up folders, settings and logging for the experiment # my_init("MT_LEc03_SE_sw", STATION, # pdf_folder=True, png_folder=True, analysis_folder=True,
def SpectrumAnalyzer(): """ Yields a DummyInstrument that holds ArrayParameters returning different types """ class Spectrum(ArrayParameter): def __init__(self, name, instrument): super().__init__( name=name, shape=(1, ), # this attribute should be removed label='Flower Power Spectrum', unit='V/sqrt(Hz)', setpoint_names=('Frequency', ), setpoint_units=('Hz', )) self.npts = 100 self.start = 0 self.stop = 2e6 self._instrument = instrument def get_raw(self): # This is how it should be: the setpoints are generated at the # time we get. But that will of course not work with the old Loop self.setpoints = (tuple( np.linspace(self.start, self.stop, self.npts)), ) # not the best SA on the market; it just returns noise... return np.random.randn(self.npts) class MultiDimSpectrum(ArrayParameter): def __init__(self, name, instrument): self.start = 0 self.stop = 2e6 self.npts = (100, 50, 20) sp1 = np.linspace(self.start, self.stop, self.npts[0]) sp2 = np.linspace(self.start, self.stop, self.npts[1]) sp3 = np.linspace(self.start, self.stop, self.npts[2]) setpoints = setpoint_generator(sp1, sp2, sp3) super().__init__(name=name, instrument=instrument, setpoints=setpoints, shape=(100, 50, 20), label='Flower Power Spectrum in 3D', unit='V/sqrt(Hz)', setpoint_names=('Frequency0', 'Frequency1', 'Frequency2'), setpoint_units=('Hz', 'Other Hz', "Third Hz")) def get_raw(self): return np.random.randn(*self.npts) class ListSpectrum(Spectrum): def get_raw(self): output = super().get_raw() return list(output) class TupleSpectrum(Spectrum): def get_raw(self): output = super().get_raw() return tuple(output) SA = DummyInstrument('dummy_SA') SA.add_parameter('spectrum', parameter_class=Spectrum) SA.add_parameter('listspectrum', parameter_class=ListSpectrum) SA.add_parameter('tuplespectrum', parameter_class=TupleSpectrum) SA.add_parameter('multidimspectrum', parameter_class=MultiDimSpectrum) yield SA SA.close()
def complex_num_instrument(): class MyParam(Parameter): def get_raw(self): return self.instrument.setpoint() + 1j * self.instrument.setpoint() class RealPartParam(Parameter): def get_raw(self): return self.instrument.complex_setpoint().real dummyinst = DummyInstrument('dummy_channel_inst', gates=()) dummyinst.add_parameter('setpoint', parameter_class=Parameter, initial_value=0, label='Some Setpoint', unit="Some Unit", vals=Numbers(), get_cmd=None, set_cmd=None) dummyinst.add_parameter('complex_num', parameter_class=MyParam, initial_value=0 + 0j, label='Complex Num', unit="complex unit", vals=ComplexNumbers(), get_cmd=None, set_cmd=None) dummyinst.add_parameter('complex_setpoint', initial_value=0 + 0j, label='Complex Setpoint', unit="complex unit", vals=ComplexNumbers(), get_cmd=None, set_cmd=None) dummyinst.add_parameter('real_part', parameter_class=RealPartParam, label='Real Part', unit="real unit", vals=Numbers(), set_cmd=None) dummyinst.add_parameter('some_array_setpoints', label='Some Array Setpoints', unit='some other unit', vals=Arrays(shape=(5, )), set_cmd=False, get_cmd=lambda: np.arange(5)) dummyinst.add_parameter('some_array', parameter_class=ParameterWithSetpoints, setpoints=(dummyinst.some_array_setpoints, ), label='Some Array', unit='some_array_unit', vals=Arrays(shape=(5, )), get_cmd=lambda: np.ones(5), set_cmd=False) dummyinst.add_parameter('some_complex_array_setpoints', label='Some complex array setpoints', unit='some_array_unit', get_cmd=lambda: np.arange(5), set_cmd=False) dummyinst.add_parameter('some_complex_array', label='Some Array', unit='some_array_unit', get_cmd=lambda: np.ones(5) + 1j * np.ones(5), set_cmd=False) yield dummyinst dummyinst.close()
mdac = scfg.load_instrument('mdac') #lockin = scfg.load_instrument('sr860') #ithaco = scfg.load_instrument('ithaco') multimeter = scfg.load_instrument('Keysight') dummy_time = DummyInstrument(name="dummy_time") time_zero = time.time() def getTime(): return time.time() - time_zero dummy_time.add_parameter('seconds', label='time', unit='s', get_cmd=getTime, set_cmd=lambda x: x) dummy_time.add_parameter('dummy_set', label='count', set_cmd=lambda x: x) dummy_time.seconds() def veryfirst(): print('Starting the measurement') global time_zero time_zero = time.time() def thelast(): print('End of measurement')