| Total Complexity | 65 |
| Total Lines | 480 |
| Duplicated Lines | 2.08 % |
| Changes | 2 | ||
| 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 int 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')) |