Exemple #1
0
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
Exemple #2
0
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()
Exemple #3
0
    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)
Exemple #4
0
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
Exemple #5
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)
Exemple #7
0
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,
Exemple #9
0
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()
Exemple #10
0
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()
Exemple #11
0
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')