Completed
Pull Request — master (#376)
by
unknown
02:06
created

FastComtec   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 463
Duplicated Lines 2.16 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 10
loc 463
rs 3.6585
wmc 63

36 Methods

Rating   Name   Duplication   Size   Complexity  
A GetStatus() 0 4 1
A on_activate() 0 9 2
A _change_filename() 0 5 1
A get_binwidth() 0 9 1
A __init__() 0 12 2
A on_deactivate() 0 4 1
A set_bitshift() 0 11 1
A get_delay_start() 0 10 1
A set_preset() 0 4 1
A set_cycles() 0 4 1
A set_binwidth() 0 14 1
A pause_measure() 0 10 3
A GetLevel() 0 6 2
A FloatToWord() 0 2 1
B get_constraints() 0 42 1
A get_bitshift() 0 9 1
A get_data_testfile() 0 5 1
B get_data_trace() 0 32 4
A stop_measure() 0 10 3
A set_delay_start() 6 13 1
B get_status() 0 26 5
C set_length() 0 27 7
A change_sweep_mode() 0 16 2
A is_gated() 0 7 1
A change_save_mode() 3 11 1
A WordToFloat() 0 2 1
A start_measure() 0 6 2
A SetLevel() 0 10 2
B configure() 0 33 3
A continue_measure() 0 9 3
A get_length() 0 8 1
A GetDelay() 0 4 1
A load_setup() 0 3 1
A SaveData_locally() 0 9 3
A SetDelay() 0 8 1
A Running() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like FastComtec often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
3
"""
4
This file contains the Qudi hardware file implementation for FastComtec p7887 .
5
6
Qudi is free software: you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation, either version 3 of the License, or
9
(at your option) any later version.
10
11
Qudi is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
16
You should have received a copy of the GNU General Public License
17
along with Qudi. If not, see <http://www.gnu.org/licenses/>.
18
19
Copyright (c) the Qudi Developers. See the COPYRIGHT.txt file at the
20
top-level directory of this distribution and at <https://github.com/Ulm-IQO/qudi/>
21
"""
22
23
#TODO: start stop works but pause does not work, i guess gui/logic problem
24
#TODO: What does get status do or need as return?
25
#TODO: Check if there are more modules which are missing, and more settings for FastComtec which need to be put, should we include voltage threshold?
26
27
from core.module import Base, ConfigOption
28
from core.util.modules import get_main_dir
29
from interface.fast_counter_interface import FastCounterInterface
30
import time
31
import os
32
import numpy as np
33
import ctypes
34
35
36
37
"""
38
Remark to the usage of ctypes:
39
All Python types except integers (int), strings (str), and bytes (byte) objects
40
have to be wrapped in their corresponding ctypes type, so that they can be
41
converted to the required C data type.
42
43
ctypes type     C type                  Python type
44
----------------------------------------------------------------
45
c_bool          _Bool                   bool (1)
46
c_char          char                    1-character bytes object
47
c_wchar         wchar_t                 1-character string
48
c_byte          char                    int
49
c_ubyte         unsigned char           int
50
c_short         short                   int
51
c_ushort        unsigned short          int
52
c_int           int                     int
53
c_uint          unsigned int            int
54
c_long          long                    int
55
c_ulong         unsigned long           int
56
c_longlong      __int64 or
57
                long long               int
58
c_ulonglong     unsigned __int64 or
59
                unsigned long long      int
60
c_size_t        size_t                  int
61
c_ssize_t       ssize_t or
62
                Py_ssize_t              int
63
c_float         float                   float
64
c_double        double                  float
65
c_longdouble    long double             float
66
c_char_p        char *
67
                (NUL terminated)        bytes object or None
68
c_wchar_p       wchar_t *
69
                (NUL terminated)        string or None
70
c_void_p        void *                  int or None
71
72
"""
73
# Reconstruct the proper structure of the variables, which can be extracted
74
# from the header file 'struct.h'.
75
76
class AcqStatus(ctypes.Structure):
77
    """ Create a structured Data type with ctypes where the dll can write into.
78
79
    This object handles and retrieves the acquisition status data from the
80
    Fastcomtec.
81
82
    int started;                // acquisition status: 1 if running, 0 else
83
    double runtime;             // running time in seconds
84
    double totalsum;            // total events
85
    double roisum;              // events within ROI
86
    double roirate;             // acquired ROI-events per second
87
    double nettosum;            // ROI sum with background subtracted
88
    double sweeps;              // Number of sweeps
89
    double stevents;            // Start Events
90
    unsigned long maxval;       // Maximum value in spectrum
91
    """
92
    _fields_ = [('started', ctypes.c_int),
93
                ('runtime', ctypes.c_double),
94
                ('totalsum', ctypes.c_double),
95
                ('roisum', ctypes.c_double),
96
                ('roirate', ctypes.c_double),
97
                ('ofls', ctypes.c_double),
98
                ('sweeps', ctypes.c_double),
99
                ('stevents', ctypes.c_double),
100 View Code Duplication
                ('maxval', ctypes.c_ulong), ]
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
101
102
class AcqSettings(ctypes.Structure):
103
    """ Create a structured Data type with ctypes where the dll can write into.
104
105
    This object handles and retrieves the acquisition settings of the Fastcomtec.
106
    """
107
108
    _fields_ = [('range',       ctypes.c_ulong),
109
                ('prena',       ctypes.c_long),
110
                ('cftfak',      ctypes.c_long),
111
                ('roimin',      ctypes.c_ulong),
112
                ('roimax',      ctypes.c_ulong),
113
                ('eventpreset', ctypes.c_double),
114
                ('timepreset',  ctypes.c_double),
115
                ('savedata',    ctypes.c_long),
116
                ('fmt',         ctypes.c_long),
117
                ('autoinc',     ctypes.c_long),
118
                ('cycles',      ctypes.c_long),
119
                ('sweepmode',   ctypes.c_long),
120
                ('syncout',     ctypes.c_long),
121
                ('bitshift',    ctypes.c_long),
122
                ('digval',      ctypes.c_long),
123
                ('digio',       ctypes.c_long),
124
                ('dac0',        ctypes.c_long),
125
                ('dac1',        ctypes.c_long),
126
                ('swpreset',    ctypes.c_double),
127
                ('nregions',    ctypes.c_long),
128
                ('caluse',      ctypes.c_long),
129
                ('fstchan',     ctypes.c_double),
130
                ('active',      ctypes.c_long),
131
                ('calpoints',   ctypes.c_long), ]
132
133
class ACQDATA(ctypes.Structure):
134
    """ Create a structured Data type with ctypes where the dll can write into.
135
136
    This object handles and retrieves the acquisition data of the Fastcomtec.
137
    """
138
    _fields_ = [('s0', ctypes.POINTER(ctypes.c_ulong)),
139
                ('region', ctypes.POINTER(ctypes.c_ulong)),
140
                ('comment', ctypes.c_char_p),
141
                ('cnt', ctypes.POINTER(ctypes.c_double)),
142
                ('hs0', ctypes.c_int),
143
                ('hrg', ctypes.c_int),
144
                ('hcm', ctypes.c_int),
145
                ('hct', ctypes.c_int), ]
146
147
148
149
class FastComtec(Base, FastCounterInterface):
150
    """
151
    unstable: Jochen Scheuer, Simon Schmitt
152
153
    Hardware Class for the FastComtec Card.
154
    """
155
    _modclass = 'FastComtec'
156
    _modtype = 'hardware'
157
    gated = ConfigOption('gated', False, missing='warn')
158
    trigger_safety = ConfigOption('trigger_safety', 200e-9, missing='warn')
159
    aom_delay = ConfigOption('aom_delay', 400e-9, missing='warn')
160
    minimal_binwidth = ConfigOption('minimal_binwidth', 0.25e-9, missing='warn')
161
162
    def __init__(self, config, **kwargs):
163
        super().__init__(config=config, **kwargs)
164
165
        self.log.debug('The following configuration was found.')
166
167
        # checking for the right configuration
168
        for key in config.keys():
169
            self.log.info('{0}: {1}'.format(key,config[key]))
170
        #this variable has to be added because there is no difference
171
        #in the fastcomtec it can be on "stopped" or "halt"
172
        self.stopped_or_halt = "stopped"
173
        self.timetrace_tmp = []
174
175
    def on_activate(self):
176
        """ Initialisation performed during activation of the module.
177
        """
178
        self.dll = ctypes.windll.LoadLibrary('dp7887.dll')
179
        if self.gated:
180
            self.change_sweep_mode(gated=True)
181
        else:
182
            self.change_sweep_mode(gated=False)
183
        return
184
185
186
    def on_deactivate(self):
187
        """ Deinitialisation performed during deactivation of the module.
188
        """
189
        return
190
191
    def get_constraints(self):
192
        """ Retrieve the hardware constrains from the Fast counting device.
193
194
        @return dict: dict with keys being the constraint names as string and
195
                      items are the definition for the constaints.
196
197
         The keys of the returned dictionary are the str name for the constraints
198
        (which are set in this method).
199
200
                    NO OTHER KEYS SHOULD BE INVENTED!
201
202
        If you are not sure about the meaning, look in other hardware files to
203
        get an impression. If still additional constraints are needed, then they
204
        have to be added to all files containing this interface.
205
206
        The items of the keys are again dictionaries which have the generic
207
        dictionary form:
208
            {'min': <value>,
209
             'max': <value>,
210
             'step': <value>,
211
             'unit': '<value>'}
212
213
        Only the key 'hardware_binwidth_list' differs, since they
214
        contain the list of possible binwidths.
215
216
        If the constraints cannot be set in the fast counting hardware then
217
        write just zero to each key of the generic dicts.
218
        Note that there is a difference between float input (0.0) and
219
        integer input (0), because some logic modules might rely on that
220
        distinction.
221
222
        ALL THE PRESENT KEYS OF THE CONSTRAINTS DICT MUST BE ASSIGNED!
223
        """
224
225
        constraints = dict()
226
227
        # the unit of those entries are seconds per bin. In order to get the
228
        # current binwidth in seonds use the get_binwidth method.
229
        constraints['hardware_binwidth_list'] = list(self.minimal_binwidth * (2 ** np.array(
230
                                                     np.linspace(0,24,25))))
231
        constraints['max_sweep_len'] = 6.8
232
        return constraints
233
234
    def configure(self, bin_width_s, record_length_s, number_of_gates=0, filename=None):
235
        """ Configuration of the fast counter.
236
237
        @param float bin_width_s: Length of a single time bin in the time trace
238
                                  histogram in seconds.
239
        @param float record_length_s: Total length of the timetrace/each single
240
                                      gate in seconds.
241
        @param int number_of_gates: optional, number of gates in the pulse
242
                                    sequence. Ignore for not gated counter.
243
244
        @return tuple(binwidth_s, record_length_s, number_of_gates):
245
                    binwidth_s: float the actual set binwidth in seconds
246
                    gate_length_s: the actual record length in seconds
247
                    number_of_gates: the number of gated, which are accepted,
248
                    None if not-gated
249
        """
250
251
        # when not gated, record length = total sequence length, when gated, record length = laser length.
252
        # subtract 200 ns to make sure no sequence trigger is missed
253
        record_length_FastComTech_s = record_length_s
254
        if self.gated:
255
            # add time to account for AOM delay
256
            no_of_bins = int((record_length_FastComTech_s + self.aom_delay) / self.set_binwidth(bin_width_s))
257
        else:
258
            # subtract time to make sure no sequence trigger is missed
259
            no_of_bins = int((record_length_FastComTech_s - self.trigger_safety) / self.set_binwidth(bin_width_s))
260
261
        self.set_length(no_of_bins, preset=1, cycles=number_of_gates)
262
263
        if filename is not None:
264
            self._change_filename(filename)
265
266
        return (self.get_binwidth(), record_length_FastComTech_s, number_of_gates)
267
268
269
270
    def get_status(self):
271
        """
272
        Receives the current status of the Fast Counter and outputs it as return value.
273
        0 = unconfigured
274
        1 = idle
275
        2 = running
276
        3 = paused
277
        -1 = error state
278
        """
279
        status = AcqStatus()
280
        self.dll.GetStatusData(ctypes.byref(status), 0)
281
        if status.started == 1:
282
            return 2
283
        elif status.started == 0:
284
            if self.stopped_or_halt == "stopped":
285
                return 1
286
            elif self.stopped_or_halt == "halt":
287
                return 3
288
            else:
289
                self.log.error('FastComTec neither stopped nor halt')
290
291
                return -1
292
        else:
293
            self.log.error(
294
                'There is an unknown status from FastComtec. The status message was %s' % (str(status.started)))
295
            return -1
296
297
298
    def start_measure(self):
299
        """Start the measurement. """
300
        status = self.dll.Start(0)
301
        while self.get_status() != 2:
302
            time.sleep(0.05)
303
        return status
304
305
    def pause_measure(self):
306
        """Make a pause in the measurement, which can be continued. """
307
        self.stopped_or_halt = "halt"
308
        status = self.dll.Halt(0)
309
        while self.get_status() != 3:
310
            time.sleep(0.05)
311
312
        if self.gated:
313
            self.timetrace_tmp = self.get_data_trace()
314
        return status
315
316
    def stop_measure(self):
317
        """Stop the measurement. """
318
        self.stopped_or_halt = "stopped"
319
        status = self.dll.Halt(0)
320
        while self.get_status() != 1:
321
            time.sleep(0.05)
322
323
        if self.gated:
324
            self.timetrace_tmp = []
325
        return status
326
327
    def continue_measure(self):
328
        """Continue a paused measurement. """
329
        if self.gated:
330
            status = self.start_measure()
331
        else:
332
            status = self.dll.Continue(0)
333
            while self.get_status() != 2:
334
                time.sleep(0.05)
335
        return status
336
337
    def get_binwidth(self):
338
        """ Returns the width of a single timebin in the timetrace in seconds.
339
340
        @return float: current length of a single bin in seconds (seconds/bin)
341
342
        The red out bitshift will be converted to binwidth. The binwidth is
343
        defined as 2**bitshift*minimal_binwidth.
344
        """
345
        return self.minimal_binwidth*(2**int(self.get_bitshift()))
346
347
348
    def is_gated(self):
349
        """ Check the gated counting possibility.
350
351
        @return bool: Boolean value indicates if the fast counter is a gated
352
                      counter (TRUE) or not (FALSE).
353
        """
354
        return self.gated
355
356
    def get_data_trace(self):
357
        """
358
        Polls the current timetrace data from the fast counter and returns it as a numpy array (dtype = int64).
359
        The binning specified by calling configure() must be taken care of in this hardware class.
360
        A possible overflow of the histogram bins must be caught here and taken care of.
361
        If the counter is UNgated it will return a 1D-numpy-array with returnarray[timebin_index]
362
        If the counter is gated it will return a 2D-numpy-array with returnarray[gate_index, timebin_index]
363
364
          @return arrray: Time trace.
365
        """
366
        setting = AcqSettings()
367
        self.dll.GetSettingData(ctypes.byref(setting), 0)
368
        N = setting.range
369
370
        if self.gated:
371
            bsetting=AcqSettings()
372
            self.dll.GetSettingData(ctypes.byref(bsetting), 0)
373
            H = bsetting.cycles
374
            data = np.empty((H, int(N / H)), dtype=np.uint32)
375
376
        else:
377
            data = np.empty((N,), dtype=np.uint32)
378
379
        p_type_ulong = ctypes.POINTER(ctypes.c_uint32)
380
        ptr = data.ctypes.data_as(p_type_ulong)
381
        self.dll.LVGetDat(ptr, 0)
382
        time_trace = np.int64(data)
383
384
        if self.gated and self.timetrace_tmp != []:
385
            time_trace = time_trace + self.timetrace_tmp
386
387
        return time_trace
388
389
390
    def get_data_testfile(self):
391
        ''' Load data test file '''
392
        data = np.loadtxt(os.path.join(get_main_dir(), 'tools', 'FastComTec_demo_timetrace.asc'))
393
        time.sleep(0.5)
394
        return data
395
396
397
    # =========================================================================
398
    #                           Non Interface methods
399
    # =========================================================================
400
401
    def get_bitshift(self):
402
        """Get bitshift from Fastcomtec.
403
404
        @return int settings.bitshift: the red out bitshift
405
        """
406
407
        settings = AcqSettings()
408
        self.dll.GetSettingData(ctypes.byref(settings), 0)
409
        return int(settings.bitshift)
410
411
    def set_bitshift(self, bitshift):
412
        """ Sets the bitshift properly for this card.
413
414
        @param int bitshift:
415
416
        @return int: asks the actual bitshift and returns the red out value
417
        """
418
419
        cmd = 'BITSHIFT={0}'.format(bitshift)
420
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))
421
        return self.get_bitshift()
422
423
    def set_binwidth(self, binwidth):
424
        """ Set defined binwidth in Card.
425
426
        @param float binwidth: the current binwidth in seconds
427
428
        @return float: Red out bitshift converted to binwidth
429
430
        The binwidth is converted into to an appropiate bitshift defined as
431
        2**bitshift*minimal_binwidth.
432
        """
433
        bitshift = int(np.log2(binwidth/self.minimal_binwidth))
434
        new_bitshift=self.set_bitshift(bitshift)
435
436
        return self.minimal_binwidth*(2**new_bitshift)
437
438
439
    #TODO: Check such that only possible lengths are set.
440
    def set_length(self, length_bins, preset=None, cycles=None, sequences=None):
441
        """ Sets the length of the length of the actual measurement.
442
443
        @param int length_bins: Length of the measurement in bins
444
445
        @return float: Red out length of measurement
446
        """
447
        constraints = self.get_constraints()
448
        if length_bins * self.get_binwidth() < constraints['max_sweep_len']:
449
            cmd = 'RANGE={0}'.format(int(length_bins))
450
            self.dll.RunCmd(0, bytes(cmd, 'ascii'))
451
            cmd = 'roimax={0}'.format(int(length_bins))
452
            self.dll.RunCmd(0, bytes(cmd, 'ascii'))
453
            if preset != None:
454
                cmd = 'swpreset={0}'.format(preset)
455
                self.dll.RunCmd(0, bytes(cmd, 'ascii'))
456
            if cycles != None and cycles != 0:
457
                cmd = 'cycles={0}'.format(cycles)
458
                self.dll.RunCmd(0, bytes(cmd, 'ascii'))
459
            if sequences != None and sequences != 0:
460
                cmd = 'sequences={0}'.format(sequences)
461
                self.dll.RunCmd(0, bytes(cmd, 'ascii'))
462
            return self.get_length()
463
        else:
464
            self.log.error(
465
                'Length of sequence is too high: %s' % (str(length_bins * self.get_binwidth())))
466
            return -1
467
468
    def set_preset(self, preset):
469
        cmd = 'swpreset={0}'.format(preset)
470
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))
471
        return preset
472
473
    def set_cycles(self, cycles):
474
        cmd = 'cycles={0}'.format(cycles)
475
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))
476
        return cycles
477
478
    def get_length(self):
479
        """ Get the length of the current measurement.
480
481
          @return int: length of the current measurement
482
        """
483
        setting = AcqSettings()
484
        self.dll.GetSettingData(ctypes.byref(setting), 0)
485
        return int(setting.range)
486
487
    def _change_filename(self,name):
488
        """ Changed the name in FCT"""
489
        cmd = 'datname=%s'%name
490
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))
491
        return name
492
493
    def change_sweep_mode(self, gated):
494
        if gated:
495
            cmd = 'sweepmode={0}'.format(hex(1978500))
496
            self.dll.RunCmd(0, bytes(cmd, 'ascii'))
497
            cmd = 'prena={0}'.format(hex(16)) #To select starts preset
498
            # cmd = 'prena={0}'.format(hex(4)) #To select sweeps preset
499
            self.dll.RunCmd(0, bytes(cmd, 'ascii'))
500
            self.gated = True
501
        else:
502
            # fastcomtch standard settings for ungated acquisition (check manual)
503
            cmd = 'sweepmode={0}'.format(hex(1978496))
504
            self.dll.RunCmd(0, bytes(cmd, 'ascii'))
505
            cmd = 'prena={0}'.format(hex(0))
506
            self.dll.RunCmd(0, bytes(cmd, 'ascii'))
507
            self.gated = False
508
        return gated
509
510
511
    def change_save_mode(self, mode):
512
        """ Changes the save mode of p7887
513
514
        @param int mode: Specifies the save mode (0: No Save at Halt, 1: Save at Halt,
515
                        2: Write list file, No Save at Halt, 3: Write list file, Save at Halt
516
517
        @return int mode: specified save mode
518
        """
519 View Code Duplication
        cmd = 'savedata={0}'.format(mode)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
520
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))
521
        return mode
522
523
    def set_delay_start(self, delay_s):
524
        """ Sets the record delay length
525
526
        @param int delay_s: Record delay after receiving a start trigger
527
528
        @return int mode: specified save mode
529
        """
530
531
        # A delay can only be adjusted in steps of 6.4ns
532
        delay_bins = np.rint(delay_s / 6.4e-9 /2.5)
533
        cmd = 'fstchan={0}'.format(int(delay_bins))
534
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))
535
        return delay_bins
536
537
    def get_delay_start(self):
538
        """ Returns the current record delay length
539
540
        @return float delay_s: current record delay length in seconds
541
        """
542
        bsetting = AcqSettings()
543
        self.dll.GetSettingData(ctypes.byref(bsetting), 0)
544
        delay_s = bsetting.fstchan * 6.4e-9 *2.5
545
        #prena = bsetting.prena
546
        return delay_s
547
548
    # =========================================================================
549
    #   The following methods have to be carefully reviewed and integrated as
550
    #   internal methods/function, because they might be important one day.
551
    # =========================================================================
552
553
    def SetDelay(self, t):
554
        #~ setting = AcqSettings()
555
        #~ self.dll.GetSettingData(ctypes.byref(setting), 0)
556
        #~ setting.fstchan = t/6.4
557
        #~ self.dll.StoreSettingData(ctypes.byref(setting), 0)
558
        #~ self.dll.NewSetting(0)
559
        self.dll.RunCmd(0, 'DELAY={0:f}'.format(t))
560
        return self.GetDelay()
561
562
    def GetDelay(self):
563
        setting = AcqSettings()
564
        self.dll.GetSettingData(ctypes.byref(setting), 0)
565
        return setting.fstchan * 6.4
566
567
568
    #former SaveData_fast
569
    def SaveData_locally(self, filename, laser_index):
570
        # os.chdir(r'D:\data\FastComTec')
571
        data = self.get_data()
572
        fil = open(filename + '.asc', 'w')
573
        for i in laser_index:
574
            for n in data[i:i+int(round(3000/(self.minimal_binwidth*2**self.GetBitshift())))
575
                    +int(round(1000/(self.minimal_binwidth*2**self.GetBitshift())))]:
576
                fil.write('{0!s}\n'.format(n))
577
        fil.close()
578
579
    def SetLevel(self, start, stop):
580
        setting = AcqSettings()
581
        self.dll.GetSettingData(ctypes.byref(setting), 0)
582
        def FloatToWord(r):
583
            return int((r+2.048)/4.096*int('ffff',16))
584
        setting.dac0 = ( setting.dac0 & int('ffff0000',16) ) | FloatToWord(start)
585
        setting.dac1 = ( setting.dac1 & int('ffff0000',16) ) | FloatToWord(stop)
586
        self.dll.StoreSettingData(ctypes.byref(setting), 0)
587
        self.dll.NewSetting(0)
588
        return self.GetLevel()
589
590
    def GetLevel(self):
591
        setting = AcqSettings()
592
        self.dll.GetSettingData(ctypes.byref(setting), 0)
593
        def WordToFloat(word):
594
            return (word & int('ffff',16)) * 4.096 / int('ffff',16) - 2.048
595
        return WordToFloat(setting.dac0), WordToFloat(setting.dac1)
596
597
    #used in one script for SSR
598
    #Todo: Remove
599
    def Running(self):
600
        s = self.GetStatus()
601
        return s.started
602
603
    def GetStatus(self):
604
        status = AcqStatus()
605
        self.dll.GetStatusData(ctypes.byref(status), 0)
606
        return status
607
608
609
    def load_setup(self, configname):
610
        cmd = 'loadcnf={0}'.format(configname)
611
        self.dll.RunCmd(0, bytes(cmd, 'ascii'))