| Total Complexity | 65 | 
| Total Lines | 480 | 
| Duplicated Lines | 2.08 % | 
| Changes | 3 | ||
| Bugs | 0 | Features | 0 | 
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 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 -*-  | 
            ||
| 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 seconds 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 | def get_current_runtime(self):  | 
            ||
| 298 | """  | 
            ||
| 299 | Returns the current runtime.  | 
            ||
| 300 | @return float runtime: in s  | 
            ||
| 301 | """  | 
            ||
| 302 | status = AcqStatus()  | 
            ||
| 303 | self.dll.GetStatusData(ctypes.byref(status), 0)  | 
            ||
| 304 | return status.runtime  | 
            ||
| 305 | |||
| 306 | def get_current_sweeps(self):  | 
            ||
| 307 | """  | 
            ||
| 308 | Returns the current runtime.  | 
            ||
| 309 | @return int sweeps: in sweeps  | 
            ||
| 310 | """  | 
            ||
| 311 | status = AcqStatus()  | 
            ||
| 312 | self.dll.GetStatusData(ctypes.byref(status), 0)  | 
            ||
| 313 | return status.sweeps  | 
            ||
| 314 | |||
| 315 | def start_measure(self):  | 
            ||
| 316 | """Start the measurement. """  | 
            ||
| 317 | status = self.dll.Start(0)  | 
            ||
| 318 | while self.get_status() != 2:  | 
            ||
| 319 | time.sleep(0.05)  | 
            ||
| 320 | return status  | 
            ||
| 321 | |||
| 322 | def pause_measure(self):  | 
            ||
| 323 | """Make a pause in the measurement, which can be continued. """  | 
            ||
| 324 | self.stopped_or_halt = "halt"  | 
            ||
| 325 | status = self.dll.Halt(0)  | 
            ||
| 326 | while self.get_status() != 3:  | 
            ||
| 327 | time.sleep(0.05)  | 
            ||
| 328 | |||
| 329 | if self.gated:  | 
            ||
| 330 | self.timetrace_tmp = self.get_data_trace()  | 
            ||
| 331 | return status  | 
            ||
| 332 | |||
| 333 | def stop_measure(self):  | 
            ||
| 334 | """Stop the measurement. """  | 
            ||
| 335 | self.stopped_or_halt = "stopped"  | 
            ||
| 336 | status = self.dll.Halt(0)  | 
            ||
| 337 | while self.get_status() != 1:  | 
            ||
| 338 | time.sleep(0.05)  | 
            ||
| 339 | |||
| 340 | if self.gated:  | 
            ||
| 341 | self.timetrace_tmp = []  | 
            ||
| 342 | return status  | 
            ||
| 343 | |||
| 344 | def continue_measure(self):  | 
            ||
| 345 | """Continue a paused measurement. """  | 
            ||
| 346 | if self.gated:  | 
            ||
| 347 | status = self.start_measure()  | 
            ||
| 348 | else:  | 
            ||
| 349 | status = self.dll.Continue(0)  | 
            ||
| 350 | while self.get_status() != 2:  | 
            ||
| 351 | time.sleep(0.05)  | 
            ||
| 352 | return status  | 
            ||
| 353 | |||
| 354 | def get_binwidth(self):  | 
            ||
| 355 | """ Returns the width of a single timebin in the timetrace in seconds.  | 
            ||
| 356 | |||
| 357 | @return float: current length of a single bin in seconds (seconds/bin)  | 
            ||
| 358 | |||
| 359 | The red out bitshift will be converted to binwidth. The binwidth is  | 
            ||
| 360 | defined as 2**bitshift*minimal_binwidth.  | 
            ||
| 361 | """  | 
            ||
| 362 | return self.minimal_binwidth*(2**int(self.get_bitshift()))  | 
            ||
| 363 | |||
| 364 | |||
| 365 | def is_gated(self):  | 
            ||
| 366 | """ Check the gated counting possibility.  | 
            ||
| 367 | |||
| 368 | @return bool: Boolean value indicates if the fast counter is a gated  | 
            ||
| 369 | counter (TRUE) or not (FALSE).  | 
            ||
| 370 | """  | 
            ||
| 371 | return self.gated  | 
            ||
| 372 | |||
| 373 | def get_data_trace(self):  | 
            ||
| 374 | """  | 
            ||
| 375 | Polls the current timetrace data from the fast counter and returns it as a numpy array (dtype = int64).  | 
            ||
| 376 | The binning specified by calling configure() must be taken care of in this hardware class.  | 
            ||
| 377 | A possible overflow of the histogram bins must be caught here and taken care of.  | 
            ||
| 378 | If the counter is UNgated it will return a 1D-numpy-array with returnarray[timebin_index]  | 
            ||
| 379 | If the counter is gated it will return a 2D-numpy-array with returnarray[gate_index, timebin_index]  | 
            ||
| 380 | |||
| 381 | @return arrray: Time trace.  | 
            ||
| 382 | """  | 
            ||
| 383 | setting = AcqSettings()  | 
            ||
| 384 | self.dll.GetSettingData(ctypes.byref(setting), 0)  | 
            ||
| 385 | N = setting.range  | 
            ||
| 386 | |||
| 387 | if self.gated:  | 
            ||
| 388 | bsetting=AcqSettings()  | 
            ||
| 389 | self.dll.GetSettingData(ctypes.byref(bsetting), 0)  | 
            ||
| 390 | H = bsetting.cycles  | 
            ||
| 391 | data = np.empty((H, int(N / H)), dtype=np.uint32)  | 
            ||
| 392 | |||
| 393 | else:  | 
            ||
| 394 | data = np.empty((N,), dtype=np.uint32)  | 
            ||
| 395 | |||
| 396 | p_type_ulong = ctypes.POINTER(ctypes.c_uint32)  | 
            ||
| 397 | ptr = data.ctypes.data_as(p_type_ulong)  | 
            ||
| 398 | self.dll.LVGetDat(ptr, 0)  | 
            ||
| 399 | time_trace = np.int64(data)  | 
            ||
| 400 | |||
| 401 | if self.gated and self.timetrace_tmp != []:  | 
            ||
| 402 | time_trace = time_trace + self.timetrace_tmp  | 
            ||
| 403 | |||
| 404 | return time_trace  | 
            ||
| 405 | |||
| 406 | |||
| 407 | def get_data_testfile(self):  | 
            ||
| 408 | ''' Load data test file '''  | 
            ||
| 409 | data = np.loadtxt(os.path.join(get_main_dir(), 'tools', 'FastComTec_demo_timetrace.asc'))  | 
            ||
| 410 | time.sleep(0.5)  | 
            ||
| 411 | return data  | 
            ||
| 412 | |||
| 413 | |||
| 414 | # =========================================================================  | 
            ||
| 415 | # Non Interface methods  | 
            ||
| 416 | # =========================================================================  | 
            ||
| 417 | |||
| 418 | def get_bitshift(self):  | 
            ||
| 419 | """Get bitshift from Fastcomtec.  | 
            ||
| 420 | |||
| 421 | @return int settings.bitshift: the red out bitshift  | 
            ||
| 422 | """  | 
            ||
| 423 | |||
| 424 | settings = AcqSettings()  | 
            ||
| 425 | self.dll.GetSettingData(ctypes.byref(settings), 0)  | 
            ||
| 426 | return int(settings.bitshift)  | 
            ||
| 427 | |||
| 428 | def set_bitshift(self, bitshift):  | 
            ||
| 429 | """ Sets the bitshift properly for this card.  | 
            ||
| 430 | |||
| 431 | @param int bitshift:  | 
            ||
| 432 | |||
| 433 | @return int: asks the actual bitshift and returns the red out value  | 
            ||
| 434 | """  | 
            ||
| 435 | |||
| 436 |         cmd = 'BITSHIFT={0}'.format(bitshift) | 
            ||
| 437 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 438 | return self.get_bitshift()  | 
            ||
| 439 | |||
| 440 | def set_binwidth(self, binwidth):  | 
            ||
| 441 | """ Set defined binwidth in Card.  | 
            ||
| 442 | |||
| 443 | @param float binwidth: the current binwidth in seconds  | 
            ||
| 444 | |||
| 445 | @return float: Red out bitshift converted to binwidth  | 
            ||
| 446 | |||
| 447 | The binwidth is converted into to an appropiate bitshift defined as  | 
            ||
| 448 | 2**bitshift*minimal_binwidth.  | 
            ||
| 449 | """  | 
            ||
| 450 | bitshift = int(np.log2(binwidth/self.minimal_binwidth))  | 
            ||
| 451 | new_bitshift=self.set_bitshift(bitshift)  | 
            ||
| 452 | |||
| 453 | return self.minimal_binwidth*(2**new_bitshift)  | 
            ||
| 454 | |||
| 455 | |||
| 456 | #TODO: Check such that only possible lengths are set.  | 
            ||
| 457 | def set_length(self, length_bins, preset=None, cycles=None, sequences=None):  | 
            ||
| 458 | """ Sets the length of the length of the actual measurement.  | 
            ||
| 459 | |||
| 460 | @param int length_bins: Length of the measurement in bins  | 
            ||
| 461 | |||
| 462 | @return float: Red out length of measurement  | 
            ||
| 463 | """  | 
            ||
| 464 | constraints = self.get_constraints()  | 
            ||
| 465 | if length_bins * self.get_binwidth() < constraints['max_sweep_len']:  | 
            ||
| 466 |             cmd = 'RANGE={0}'.format(int(length_bins)) | 
            ||
| 467 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 468 |             cmd = 'roimax={0}'.format(int(length_bins)) | 
            ||
| 469 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 470 | if preset != None:  | 
            ||
| 471 |                 cmd = 'swpreset={0}'.format(preset) | 
            ||
| 472 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 473 | if cycles != None and cycles != 0:  | 
            ||
| 474 |                 cmd = 'cycles={0}'.format(cycles) | 
            ||
| 475 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 476 | if sequences != None and sequences != 0:  | 
            ||
| 477 |                 cmd = 'sequences={0}'.format(sequences) | 
            ||
| 478 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 479 | return self.get_length()  | 
            ||
| 480 | else:  | 
            ||
| 481 | self.log.error(  | 
            ||
| 482 | 'Length of sequence is too high: %s' % (str(length_bins * self.get_binwidth())))  | 
            ||
| 483 | return -1  | 
            ||
| 484 | |||
| 485 | def set_preset(self, preset):  | 
            ||
| 486 |         cmd = 'swpreset={0}'.format(preset) | 
            ||
| 487 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 488 | return preset  | 
            ||
| 489 | |||
| 490 | def set_cycles(self, cycles):  | 
            ||
| 491 |         cmd = 'cycles={0}'.format(cycles) | 
            ||
| 492 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 493 | return cycles  | 
            ||
| 494 | |||
| 495 | def get_length(self):  | 
            ||
| 496 | """ Get the length of the current measurement.  | 
            ||
| 497 | |||
| 498 | @return int: length of the current measurement  | 
            ||
| 499 | """  | 
            ||
| 500 | setting = AcqSettings()  | 
            ||
| 501 | self.dll.GetSettingData(ctypes.byref(setting), 0)  | 
            ||
| 502 | return int(setting.range)  | 
            ||
| 503 | |||
| 504 | def _change_filename(self,name):  | 
            ||
| 505 | """ Changed the name in FCT"""  | 
            ||
| 506 | cmd = 'datname=%s'%name  | 
            ||
| 507 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 508 | return name  | 
            ||
| 509 | |||
| 510 | def change_sweep_mode(self, gated):  | 
            ||
| 511 | if gated:  | 
            ||
| 512 |             cmd = 'sweepmode={0}'.format(hex(1978500)) | 
            ||
| 513 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 514 |             cmd = 'prena={0}'.format(hex(16)) #To select starts preset | 
            ||
| 515 |             # cmd = 'prena={0}'.format(hex(4)) #To select sweeps preset | 
            ||
| 516 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 517 | self.gated = True  | 
            ||
| 518 | else:  | 
            ||
| 519 | View Code Duplication | # fastcomtch standard settings for ungated acquisition (check manual)  | 
            |
| 520 |             cmd = 'sweepmode={0}'.format(hex(1978496)) | 
            ||
| 521 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 522 |             cmd = 'prena={0}'.format(hex(0)) | 
            ||
| 523 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 524 | self.gated = False  | 
            ||
| 525 | return gated  | 
            ||
| 526 | |||
| 527 | |||
| 528 | def change_save_mode(self, mode):  | 
            ||
| 529 | """ Changes the save mode of p7887  | 
            ||
| 530 | |||
| 531 | @param int mode: Specifies the save mode (0: No Save at Halt, 1: Save at Halt,  | 
            ||
| 532 | 2: Write list file, No Save at Halt, 3: Write list file, Save at Halt  | 
            ||
| 533 | |||
| 534 | @return int mode: specified save mode  | 
            ||
| 535 | """  | 
            ||
| 536 |         cmd = 'savedata={0}'.format(mode) | 
            ||
| 537 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 538 | return mode  | 
            ||
| 539 | |||
| 540 | def set_delay_start(self, delay_s):  | 
            ||
| 541 | """ Sets the record delay length  | 
            ||
| 542 | |||
| 543 | @param int delay_s: Record delay after receiving a start trigger  | 
            ||
| 544 | |||
| 545 | @return int mode: specified save mode  | 
            ||
| 546 | """  | 
            ||
| 547 | |||
| 548 | # A delay can only be adjusted in steps of 6.4ns  | 
            ||
| 549 | delay_bins = np.rint(delay_s / 6.4e-9 /2.5)  | 
            ||
| 550 |         cmd = 'fstchan={0}'.format(int(delay_bins)) | 
            ||
| 551 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  | 
            ||
| 552 | return delay_bins  | 
            ||
| 553 | |||
| 554 | def get_delay_start(self):  | 
            ||
| 555 | """ Returns the current record delay length  | 
            ||
| 556 | |||
| 557 | @return float delay_s: current record delay length in seconds  | 
            ||
| 558 | """  | 
            ||
| 559 | bsetting = AcqSettings()  | 
            ||
| 560 | self.dll.GetSettingData(ctypes.byref(bsetting), 0)  | 
            ||
| 561 | delay_s = bsetting.fstchan * 6.4e-9 *2.5  | 
            ||
| 562 | #prena = bsetting.prena  | 
            ||
| 563 | return delay_s  | 
            ||
| 564 | |||
| 565 | # =========================================================================  | 
            ||
| 566 | # The following methods have to be carefully reviewed and integrated as  | 
            ||
| 567 | # internal methods/function, because they might be important one day.  | 
            ||
| 568 | # =========================================================================  | 
            ||
| 569 | |||
| 570 | def SetDelay(self, t):  | 
            ||
| 571 | #~ setting = AcqSettings()  | 
            ||
| 572 | #~ self.dll.GetSettingData(ctypes.byref(setting), 0)  | 
            ||
| 573 | #~ setting.fstchan = t/6.4  | 
            ||
| 574 | #~ self.dll.StoreSettingData(ctypes.byref(setting), 0)  | 
            ||
| 575 | #~ self.dll.NewSetting(0)  | 
            ||
| 576 |         self.dll.RunCmd(0, 'DELAY={0:f}'.format(t)) | 
            ||
| 577 | return self.GetDelay()  | 
            ||
| 578 | |||
| 579 | def GetDelay(self):  | 
            ||
| 580 | setting = AcqSettings()  | 
            ||
| 581 | self.dll.GetSettingData(ctypes.byref(setting), 0)  | 
            ||
| 582 | return setting.fstchan * 6.4  | 
            ||
| 583 | |||
| 584 | |||
| 585 | #former SaveData_fast  | 
            ||
| 586 | def SaveData_locally(self, filename, laser_index):  | 
            ||
| 587 | # os.chdir(r'D:\data\FastComTec')  | 
            ||
| 588 | data = self.get_data()  | 
            ||
| 589 | fil = open(filename + '.asc', 'w')  | 
            ||
| 590 | for i in laser_index:  | 
            ||
| 591 | for n in data[i:i+int(round(3000/(self.minimal_binwidth*2**self.GetBitshift())))  | 
            ||
| 592 | +int(round(1000/(self.minimal_binwidth*2**self.GetBitshift())))]:  | 
            ||
| 593 |                 fil.write('{0!s}\n'.format(n)) | 
            ||
| 594 | fil.close()  | 
            ||
| 595 | |||
| 596 | def SetLevel(self, start, stop):  | 
            ||
| 597 | setting = AcqSettings()  | 
            ||
| 598 | self.dll.GetSettingData(ctypes.byref(setting), 0)  | 
            ||
| 599 | def FloatToWord(r):  | 
            ||
| 600 |             return int((r+2.048)/4.096*int('ffff',16)) | 
            ||
| 601 |         setting.dac0 = ( setting.dac0 & int('ffff0000',16) ) | FloatToWord(start) | 
            ||
| 602 |         setting.dac1 = ( setting.dac1 & int('ffff0000',16) ) | FloatToWord(stop) | 
            ||
| 603 | self.dll.StoreSettingData(ctypes.byref(setting), 0)  | 
            ||
| 604 | self.dll.NewSetting(0)  | 
            ||
| 605 | return self.GetLevel()  | 
            ||
| 606 | |||
| 607 | def GetLevel(self):  | 
            ||
| 608 | setting = AcqSettings()  | 
            ||
| 609 | self.dll.GetSettingData(ctypes.byref(setting), 0)  | 
            ||
| 610 | def WordToFloat(word):  | 
            ||
| 611 |             return (word & int('ffff',16)) * 4.096 / int('ffff',16) - 2.048 | 
            ||
| 612 | return WordToFloat(setting.dac0), WordToFloat(setting.dac1)  | 
            ||
| 613 | |||
| 614 | #used in one script for SSR  | 
            ||
| 615 | #Todo: Remove  | 
            ||
| 616 | def Running(self):  | 
            ||
| 617 | s = self.GetStatus()  | 
            ||
| 618 | return s.started  | 
            ||
| 619 | |||
| 620 | def GetStatus(self):  | 
            ||
| 621 | status = AcqStatus()  | 
            ||
| 622 | self.dll.GetStatusData(ctypes.byref(status), 0)  | 
            ||
| 623 | return status  | 
            ||
| 624 | |||
| 625 | |||
| 626 | def load_setup(self, configname):  | 
            ||
| 627 |         cmd = 'loadcnf={0}'.format(configname) | 
            ||
| 628 | self.dll.RunCmd(0, bytes(cmd, 'ascii'))  |