def set_voltage(voltage, base_atten=self.pspl_base_attenuation): # Calculate the voltage controller attenuator setting amplitude = 7.5 * np.power(10, -base_atten / 20.0) vc_atten = abs(20.0 * np.log10( abs(voltage) / 7.5)) - base_atten - self.circuit_attenuation if vc_atten <= self.atten.minimum_atten(): base_atten -= 1 if base_atten < 0: logger.error( "Voltage controlled attenuation {} under range, PSPL at Max. Decrease circuit attenuation." .format(vc_atten)) raise ValueError( "Voltage controlled attenuation {} under range, PSPL at Max. Decrease circuit attenuation." .format(vc_atten)) set_voltage(voltage, base_atten=base_atten) return if self.atten.maximum_atten() < vc_atten: base_atten += 1 if base_atten > 80: logger.error( "Voltage controlled attenuation {} over range, PSPL at Min. Increase circuit attenuation." .format(vc_atten)) raise ValueError( "Voltage controlled attenuation {} over range, PSPL at Min. Increase circuit attenuation." .format(vc_atten)) set_voltage(voltage, base_atten=base_atten) return #print("PSPL Amplitude: {}, Attenuator: {}".format(amplitude,vc_atten)) self.atten.set_attenuation(vc_atten) self.pspl.amplitude = self.pulse_polarity * amplitude time.sleep(0.04)
def connect(self, resource_name=None, interface_type="VISA"): """Connect to the RF source via a specified physical interface. Defaults to the IP address given at instatiation and the VISA interface if these arguments are not given. Args: resource_name: IP address of BNC. Defaults to None. interface_type: Physical interface for communication. Default is None, indicating use of PyVISA. Returns: None. """ if resource_name is not None: if is_valid_ipv4(resource_name): resource_name = resource_name + "::inst0::INSTR" else: logger.error("Invalid IP address for BNC845: {}.".format(resource_name)) super(BNC845, self).connect(resource_name, interface_type) self.interface._resource.read_termination = '\n' self.interface._resource.write_termination = '\n' # Setup the reference every time # Output 10MHz for daisy-chaining and lock to 10MHz external # reference self.output = True self.interface.write('SOURCE:ROSC:EXT:FREQ 10E6') self.interface.write('SOUR:ROSC:SOUR EXT') # Check that it locked -- it does not lock. for ct in range(10): locked = self.interface.query('SOURCE:ROSC:LOCKED?') logger.debug("Lock attempt {}: {}".format(ct, locked)) if locked == '1': break time.sleep(0.5) if locked != '1': logger.warning('BNC845 at %s is unlocked.', self.resource_name.split("::")[1]);
def set_voltage(voltage): # Calculate the voltage controller attenuator setting self.pspl.amplitude = self.polarity * 7.5 * np.power( 10, -self.pspl_base_attenuation / 20.0) vc_atten = abs( 20.0 * np.log10(abs(voltage) / 7.5) ) - self.pspl_base_attenuation - self.circuit_attenuation if vc_atten <= self.atten.minimum_atten(): logger.error( "Voltage controlled attenuation {} under range.".format( vc_atten)) raise ValueError( "Voltage controlled attenuation {} under range.".format( vc_atten)) if self.atten.maximum_atten() < vc_atten: logger.error( "Voltage controlled attenuation {} over range.".format( vc_atten)) raise ValueError( "Voltage controlled attenuation {} over range.".format( vc_atten)) self.atten.set_attenuation(vc_atten) time.sleep(0.02)
async def run(self): """This is run for each step in a sweep.""" for dig in self.digitizers: dig.acquire() await asyncio.sleep(0.75) if not self.cw_mode: for awg in self.awgs: awg.run() # Wait for all of the acquisitions to complete timeout = 10 try: await asyncio.gather( * [dig.wait_for_acquisition(timeout) for dig in self.digitizers]) except Exception as e: logger.error("Received exception %s in run loop. Bailing", repr(e)) self.shutdown() sys.exit(0) for dig in self.digitizers: dig.stop() if not self.cw_mode: for awg in self.awgs: awg.stop()
def query(self, command, nbytes=64): self.write(command) response = self.read(nbytes=nbytes) if response == "Invalid Command": logger.error("Invalid command {} to Holzworth {}.".format( command, self.serial)) return response
def set_all(self, params, digit=4): """ Set the connections of all channels params: number, string or dictionary defining which channel to be set to which terminal digit: number of digits per channel. Default 4 (channels, bits) Examples: set_all({'A':2}) or set_all(2) or set_all('10') sets channel A to 2, disconnects channel B """ logger.debug("Set all connections for %s" % self.name) if isinstance(params, int): val = params elif isinstance(params, str): val = int(params, 2) elif isinstance(params, dict): val = 0 for k, v in params.items(): shift = (ord(k.upper()) - 65) * digit shift += v - 1 val += 1 << shift else: logger.error( "Function set_all is not yet implemented for this type of argument: %s" % type(params)) return None res = self.write("SETP=" + str(val)) return res
async def wait_for_acquisition(self, timeout=5): while not self.done(): if (datetime.datetime.now() - self.last_timestamp).seconds > timeout: logger.error("Digitizer %s timed out.", self.name) break await asyncio.sleep(0.2)
def write(self, command): try: wlen = self._e_out.write(command.encode(), timeout=self.TIMEOUT) assert wlen == len(command.encode()) except usb.core.USBError: logger.error("Command {} to Holzworth {} timed out!".format( command, self.serial))
def channel_setup(self, channel): a, b, c = channel.channel_tuple self._lib.enable_stream(a, b, c) if channel.stream_type == "Raw": return elif channel.stream_type == "Demodulated": self._lib.set_nco_frequency(a, b, channel.if_freq) elif channel.stream_type == "Integrated": if channel.kernel is None: logger.error("Integrated streams must specify a kernel") return # convert to complex128 channel.kernel = channel.kernel.astype(complex) self._lib.write_kernel(a, b, c, channel.kernel) self._lib.set_kernel_bias(a, b, c, channel.kernel_bias) self._lib.set_threshold(a, c, channel.threshold) self._lib.set_threshold_invert(a, c, channel.threshold_invert) self._lib.set_threshold_input_sel(a, c, channel.threshold_input_sel) elif channel.stream_type == "State": return elif channel.stream_type == "Correlated": return else: logger.error("Unrecognized stream type %s" % channel.stream_type)
def enumerate(cls): try: lib = ctypes.CDLL("HolzworthMulti.dll") except: logger.error("Could not find the Holzworth driver.") return lib.getAttachedDevices.restype = ctypes.c_char_p devices = lib.getAttachedDevices() return devices.decode('ascii').split(',')
async def wait_for_acquisition(self, timeout=5): while not self.done(): if (datetime.datetime.now() - self.last_timestamp).seconds > timeout: logger.error("Digitizer %s timed out.", self.name) raise Exception("Alazar timed out.") await asyncio.sleep(0.2) logger.debug("Digitizer %s finished getting data.", self.name)
def read(self, nbytes=64): data = None try: data = self._e_in.read(nbytes, timeout=self.TIMEOUT) except usb.core.USBError: logger.error("Read from Holzworth {} timed out!".format( self.serial)) #Strip NULLs from reply and decode return bytes(data).partition(b'\0')[0].decode()
def set_voltage(voltage): # Calculate the voltage controller attenuator setting self.pspl.amplitude = np.sign(voltage)*7.5*np.power(10, -self.pspl_base_attenuation/20.0) vc_atten = abs(20.0 * np.log10(abs(voltage)/7.5)) - self.pspl_base_attenuation - self.circuit_attenuation if vc_atten <= 6.0: logger.error("Voltage controlled attenuation under range (6dB).") raise ValueError("Voltage controlled attenuation under range (6dB).") self.atten.set_attenuation(vc_atten) time.sleep(0.02)
def wait_for_acquisition(self, dig_run, timeout=5, ocs=None, progressbars=None): progress_updaters = {} if ocs and progressbars: for oc in ocs: if hasattr(progressbars[oc], 'goto'): progress_updaters[oc] = lambda x: progressbars[oc].goto(x) else: progress_updaters[oc] = lambda x: setattr(progressbars[oc], 'value', x) if self.gen_fake_data: total_spewed = 0 counter = {chan: 0 for chan in self._chan_to_wsocket.keys()} initial_points = {oc: oc.points_taken.value for oc in ocs} # print(self.number_averages, self.number_segments) for j in range(self.number_averages): # for i in range(self.number_segments): if self.ideal_data is not None: #add ideal data for testing if hasattr(self, 'exp_step') and self.increment_ideal_data: raise Exception("Cannot use both exp_step and increment_ideal_data") elif hasattr(self, 'exp_step'): total_spewed += self.spew_fake_data( counter, self.ideal_data[self.exp_step]) elif self.increment_ideal_data: total_spewed += self.spew_fake_data( counter, self.ideal_data[self.ideal_counter]) else: total_spewed += self.spew_fake_data( counter, self.ideal_data) else: total_spewed += self.spew_fake_data(counter, [0.0 for i in range(self.number_segments)]) time.sleep(0.0001) self.ideal_counter += 1 while not self.done(): if not dig_run.is_set(): self.last_timestamp.value = datetime.datetime.now().timestamp() if (datetime.datetime.now().timestamp() - self.last_timestamp.value) > timeout: logger.info(f"timeout when recv={self.total_received.value}, exp={self.number_segments*self.record_length*self.number_averages*len(self.channels)}") logger.error("Digitizer %s timed out. Timeout was %f, time was %f", self.name, timeout, (datetime.datetime.now().timestamp() - self.last_timestamp.value)) raise Exception("Alazar timed out.") if progressbars: for oc in ocs: progress_updaters[oc](oc.points_taken.value) #time.sleep(0.2) Does this need to be here at all? if progressbars: try: progressbars[oc].next() progressbars[oc].finish() except AttributeError: pass logger.info(f"Digitizer %s finished getting data when recv={self.total_received.value}, exp={self.number_segments*self.record_length*self.number_averages*len(self.channels)}.", self.name)
def __init__(self, resource_name=None, *args, **kwargs): """Berkely Nucleonics BNC845-M RF Signal Generator Args: resource_name: The IP address of the source to conenct to, as string. """ if resource_name is not None: if is_valid_ipv4(resource_name): resource_name = resource_name + "::inst0::INSTR" else: logger.error("Invalid IP address for BNC845: {}.".format(resource_name)) super(BNC845, self).__init__(resource_name, *args, **kwargs)
def receive_data(self, channel, oc, exit, ready, run): try: sock = self._chan_to_rsocket[channel] sock.settimeout(2) self.last_timestamp.value = datetime.datetime.now().timestamp() total = 0 ready.value += 1 logger.debug( f"{self} receiver launched with pid {os.getpid()}. ppid {os.getppid()}" ) while not exit.is_set(): # push data from a socket into an OutputConnector (oc) # wire format is just: [size, buffer...] # TODO receive 4 or 8 bytes depending on sizeof(size_t) run.wait() # Block until we are running again try: msg = sock.recv(8) self.last_timestamp.value = datetime.datetime.now( ).timestamp() except: continue # reinterpret as int (size_t) msg_size = struct.unpack('n', msg)[0] buf = sock_recvall(sock, msg_size) if len(buf) != msg_size: logger.error( "Channel %s socket msg shorter than expected" % channel.channel) logger.error("Expected %s bytes, received %s bytes" % (msg_size, len(buf))) return data = np.frombuffer(buf, dtype=channel.dtype) # logger.info(f"X6 {msg_size} got {len(data)}") total += len(data) oc.push(data) # logger.info('RECEIVED %d %d', total, oc.points_taken.value) # TODO: this is suspeicious for stream in oc.output_streams: abc = 0 while True: try: dat = stream.queue.get(False) abc += 1 time.sleep(0.005) except queue.Empty as e: # logger.info(f"All my data {oc} has been consumed {abc}") break # logger.info("X6 receive data exiting") except Exception as e: logger.warning(f"{self} receiver raised exception {e}. Bailing.")
async def process_data(self, data): """Fill the ground and excited data bins""" if data.shape[0] == self.ground_data.size * 2: dsplit = np.array(np.split(data, self.num_segments)) gd = dsplit[::2] ed = dsplit[1::2] self.ground_data = gd.T self.excited_data = ed.T self.counter = self.num_segments + 1 else: if self.counter % 2 != 0: N = (self.counter + 1) // 2 - 1 self.ground_data[:, N] = data else: N = self.counter // 2 - 1 self.excited_data[:, N] = data self.counter += 1 if self.counter > self.num_segments: self.counter = 1 filter_success = False filter_tries = 0 ORIG_TOL = self.TOLERANCE while not filter_success: try: filter_tries += 1 self.compute_filter() filter_success = True except np.linalg.linalg.LinAlgError as e: self.TOLERANCE *= 1.5 logger.warning( "Single shot filter failed with error: {}. Increasing kernel tolerance to {}." .format(e, self.TOLERANCE)) logger.warning( "Single shot filter retrying {} out of {} times.". format(filter_tries, self.MAX_TRIES)) if filter_tries > self.MAX_TRIES: logger.error( "Could not find a non-singluar single-shot filter after {} tries with tolerance {}." .format(filter_tries, self.TOLERANCE)) self.fidelity_result = np.complex128(0) break self.TOLERANCE = ORIG_TOL if self.logistic_regression.value: self.logistic_fidelity() if self.save_kernel.value: self._save_kernel() for os in self.fidelity.output_streams: await os.push(self.fidelity_result)
def connect(self, resource_name=None, interface_type=None): """Either connect to the resource name specified during initialization, or specify a new resource name here.""" self._unfreeze() if resource_name is None and self.resource_name is None: raise Exception( "Must supply a resource name to 'connect' if the instrument was initialized without one." ) elif resource_name is not None: self.resource_name = resource_name self.full_resource_name = self.resource_name if interface_type is None: # Load the dummy interface, unless we see that GPIB is in the resource string if any([ x in self.resource_name for x in [ "GPIB", "USB", "SOCKET", "hislip", "inst0", "COM", "ASRL", "TCPIP" ] ]): interface_type = "VISA" try: if interface_type is None: logger.debug( "Instrument {} is using a generic instrument " + "interface as none was provided.".format(self.name)) self.interface = Interface() elif interface_type == "VISA": if "GPIB" in self.full_resource_name: pass elif any( is_valid_ipv4(substr) for substr in self.full_resource_name.split( "::")) and "TCPIP" not in self.full_resource_name: # assume single NIC for now self.full_resource_name = "TCPIP0::" + self.full_resource_name self.interface = VisaInterface(self.full_resource_name) logger.debug( "A pyVISA interface {} was created for instrument {}.". format(str(self.interface._resource), self.name)) elif interface_type == "Prologix": self.interface = PrologixInterface(self.full_resource_name) else: raise ValueError("That interface type is not yet recognized.") except: logger.error("Could not initialize interface for %s.", self.full_resource_name) self.interface = MagicMock() self._freeze()
def upload_waveform(self, data, channel=1, name="mywaveform", dac=True): """ Load string-converted data into a waveform memory dac: True if values are converted to integer already """ # Check number of data points N = len(data) if N < 8 or N > 65536: log.error( "Data has invalid length = %d. Must be between 8 and 65536. Cannot upload waveform." % N) return False # Check length of waveform length, must be <=12 if len(name) > 12: logger.warning("Waveform length is larger than the limit of 12. Will be clipped off: %s --> %s" \ %(name,name[:12])) name = name[:12] # Arb waveform name at most 12 characters if dac: # Data points are integer dac_str = ":DAC" # Values must be within -32767 and 32767 if abs(np.max(data)) > 32767: logger.warning( "Some points out of range [-32767,32767] will be clipped off." ) data = [int(max(min(datum, 32767), -32767)) for datum in data] else: # Data points are float dac_str = "" # Values must be within -1 and 1 if abs(np.max(data)) > 1: logger.warning( "Some points out of range [-1,1] will be clipped off.") data = [max(min(datum, 1), -1) for datum in data] # convert array into string data_str = ','.join([str(item) for item in data]) logger.debug("Upload waveform %s to instrument %s, channel %d: %s" % (name, self.name, channel, data)) self.interface.write("SOURce%s:DATA:ARBitrary1%s %s,%s" % (channel, dac_str, name, data_str)) # Check if successfully uploaded or not data_pts = int( self.interface.query("SOURce%s:DATA:ATTR:POIN? %s" % (channel, name))) if data_pts == N: logger.debug( "Successfully uploaded waveform %s to instrument %s, channel %d" % (name, self.name, channel)) return True else: logger.error( "Failed uploading waveform %s to instrument %s, channel %d" % (name, self.name, channel)) return False
def connect(self, resource_name=None, interface_type="VISA"): if resource_name is not None: self.resource_name = resource_name if is_valid_ipv4(self.resource_name): self.resource_name += "::hpib7,16::INSTR" else: logger.error( "The resource name for the Agilent E8363C: {} is " + "not a valid IPv4 address.".format(self.resource_name)) super(AgilentE8363C, self).connect(resource_name=None, interface_type=interface_type) self.interface._resource._read_termination = u"\n" self.interface._resource.write_termination = u"\n"
def self_check(self): N = len(self.data) if N < 8: logger.error("Waveform %s must have at least 8 points" % self.name) return False else: if self.mkr_pts < 4: self.mkr_pts = 4 logger.warning( "Marker points of waveform %s is less than 4. Set to 4." % self.name) if self.mkr_pts > N - 3: self.mkr_pts = N - 3 logger.warning( "Marker points of waveform %s is longer than lenght-3 = %d. Set to lenght-3." % (self.name, N - 3)) return True
def channel_setup(self, channel): a, b, c = channel.channel_tuple self._lib.enable_stream(a, b, c) if channel.stream_type == "raw": return elif channel.stream_type == "demodulated": self._lib.set_nco_frequency(a, b, channel.if_freq) elif channel.stream_type == "integrated": if channel.kernel is None: logger.error("Integrated streams must specify a kernel") return self._lib.write_kernel(a, b, c, channel.kernel) self._lib.set_kernel_bias(a, b, c, channel.kernel_bias) self._lib.set_threshold(a, c, channel.threshold) self._lib.set_threshold_invert(a, c, channel.threshold_invert) else: logger.error("Unrecognized stream type %s" % channel.stream_type)
def request(self, method, command): """ Send a request via HTTP and retrieve response """ if self._resource is None: logger.error( "No connection established for %s. Query returns None." % self.name) return None logger.debug("Send request to %s: %s" % (self.name, command)) self._resource.request(method, command) res = self._resource.getresponse() if res.status == 200: logger.debug("Successfully made request to %s. Status: %s - %s" % (self.name, res.status, res.reason)) else: logger.warning("Issue making request to %s. Status: %s - %s" % (self.name, res.status, res.reason)) data = res.read() logger.debug("Response from %s: %s" % (self.name, data)) return data
async def wait_for_acquisition(self, timeout=5): if self.gen_fake_data: for j in range(self._lib.nbr_round_robins): for i in range(self._lib.nbr_segments): if self.ideal_data is not None: #add ideal data for testing if hasattr(self, 'exp_step'): self.spew_fake_data(self.ideal_data[self.exp_step][i]) else: self.spew_fake_data(self.ideal_data[i]) else: self.spew_fake_data() await asyncio.sleep(0.005) else: while not self.done(): if (datetime.datetime.now() - self.last_timestamp).seconds > timeout: logger.error("Digitizer %s timed out.", self.name) break await asyncio.sleep(0.1)
def receive_data(self, channel, oc): # push data from a socket into an OutputConnector (oc) self.last_timestamp = datetime.datetime.now() # wire format is just: [size, buffer...] sock = self._chan_to_rsocket[channel] # TODO receive 4 or 8 bytes depending on sizeof(size_t) msg = sock.recv(8) # reinterpret as int (size_t) msg_size = struct.unpack('n', msg)[0] buf = sock.recv(msg_size, socket.MSG_WAITALL) if len(buf) != msg_size: logger.error("Channel %s socket msg shorter than expected" % channel.channel) logger.error("Expected %s bytes, received %s bytes" % (msg_size, len(buf))) # assume that we cannot recover, so stop listening. loop = asyncio.get_event_loop() loop.remove_reader(sock) return data = np.frombuffer(buf, dtype=channel.dtype) asyncio.ensure_future(oc.push(data))
def __new__(cls, name, set_all=True, meas_file=None): settings = auspex.config.load_meas_file(meas_file) modules = ( importlib.import_module('auspex.instruments.' + name) for loader, name, is_pkg in pkgutil.iter_modules(auspex.instruments.__path__) ) module_map = {} for mod in modules: instrs = (_ for _ in inspect.getmembers(mod) if inspect.isclass(_[1]) and issubclass(_[1], Instrument) and _[1] != Instrument and _[1] != SCPIInstrument and _[1] != CLibInstrument) module_map.update(dict(instrs)) try: instr_par = settings['instruments'][name] except KeyError as e: e.args = ('Could not find instrument {} in measurement file: {}'.format(e.args[0], auspex.config.find_meas_file())) raise instr_type = instr_par['type'] instr_par['name'] = name if instr_type in module_map: logger.debug("Found instrument class %s for '%s' at loc %s when loading experiment settings.", instr_type, name, instr_par['address']) try: inst = module_map[instr_type](correct_resource_name(str(instr_par['address'])), name=name) except Exception as e: logger.error("Initialization of caused exception:", name, str(e)) inst = None if inst: inst.connect() if set_all: inst.set_all(instr_par) return inst
def new_file(self): """ Open a new data file to write """ # Close the current file, if any if self.file is not None: try: self.file.close() except Exception as e: logger.error("Encounter exception: {}".format(e)) logger.error( "Cannot close file '{}'. File may be damaged.".format( self.file.filename)) # Get new file name self.filename.value = self.new_filename() head = os.path.dirname(self.filename.value) head = os.path.normpath(head) dirs = head.split(os.sep) # Check if path exists. If not, create new one(s). os.makedirs(head, exist_ok=True) logger.debug("Create new data file: %s." % self.filename.value) # Copy current settings to a folder with the file name if self.save_settings: self.save_json() return h5py.File(self.filename.value, 'w', libver='latest')
def load_instruments(experiment): # Inspect all vendor modules in auspex instruments and construct # a map to the instrument names. modules = ( importlib.import_module('auspex.instruments.' + name) for loader, name, is_pkg in pkgutil.iter_modules(auspex.instruments.__path__) ) module_map = {} for mod in modules: instrs = (_ for _ in inspect.getmembers(mod) if inspect.isclass(_[1]) and issubclass(_[1], Instrument) and _[1] != Instrument and _[1] != SCPIInstrument and _[1] != CLibInstrument) module_map.update(dict(instrs)) logger.debug("Found instruments %s.", module_map) # Loop through instruments, and add them to the experiment if they are enabled. for instr_name, instr_par in experiment.instrument_settings['instrDict'].items(): if instr_par['enabled']: # This should go away as auspex and pyqlab converge on naming schemes instr_type = instr_par['x__class__'] # Instantiate the desired instrument if instr_type in module_map: logger.debug("Found instrument class %s for '%s' at loc %s when loading experiment settings.", instr_type, instr_name, instr_par['address']) try: inst = module_map[instr_type](correct_resource_name(instr_par['address']), name=instr_name) except Exception as e: import ipdb; ipdb.set_trace() logger.error("Initialization caused exception:", str(e)) inst = None # Add to class dictionary for convenience setattr(experiment, 'instr_name', inst) # Add to _instruments dictionary experiment._instruments[instr_name] = inst else: logger.error("Could not find instrument class %s for '%s' when loading experiment settings.", instr_type, instr_name)
def shutdown_instruments(self): # remove socket listeners logger.debug("Shutting down instruments") try: for awg in self.awgs: awg.stop() for dig in self.digitizers: dig.stop() for gen_proxy in self.generators: gen_proxy.instr.output = False except: logger.error('Could Not Stop AWGs or Digitizers; Reset Experiment') for instr in self.instruments: instr.disconnect() self.dig_exit.set() for listener in self.dig_listeners: listener.join(2) if listener.is_alive(): logger.debug(f"Terminating listener {listener} aggressively") listener.terminate() del listener import gc gc.collect()
def connect(self, ipaddr=None, gpib=None): """Connect to a GPIB device through a Prologix GPIB-ETHERNET controller. box. Args: ipaddr: The IP address of the Prologix GPIB-ETHERNET. gpib: The GPIB address of the instrument to be controlled. Returns: None. """ if ipaddr is not None: self.ipaddr = ipaddr if gpib is not None: self.gpib = gpib try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) self.sock.settimeout(self._timeout) self.sock.connect( (self.ipaddr, 1234)) #Prologix communicates on port 1234 except socket.error as err: logger.error("Cannot open socket to Prologix at {0}: {1}".format( self.ipaddr, err.msg)) raise PrologixError(self.ipaddr) from err self.sock.send(b"++ver\r\n") whoami = self.sock.recv(128).decode() if "Prologix" not in whoami: logger.error( "The device at {0} does not appear to be a Prologix; got {1}.". format(self.ipaddr, whoami)) raise PrologixError(whoami) self.sock.send(b"++mode 1\r\n") #set to controller mode self.sock.send(b"++auto 1\r\n") #enable read-after-write self._addr() self.sock.send(b"++clr\r\n") idn = self.query(self.idn_string) if idn is '': logger.error(("Did not receive response to GPIB command {0} " + "from GPIB device {1} on Prologix at {2}.").format( self.idn_string, self.gpib, self.ipaddr)) raise PrologixError(idn) else: logger.debug( ("Succesfully connected to device {0} at GPIB port {1} on" + " Prologix controller at {2}.").format( idn, self.gpib, self.ipaddr))