def go(): if len(sys.argv) <= 1: print "You must enter a test mode!" printUsage() sys.exit() funcs = { 'radio' : audioTest, 'status' : testDeviceStatusQueries, 'raw-pipe' : testRawPipeMode, 'callback' : testCallback, 'traces' : testSweeps, 'int-traces' : interruptedSweeping, 'gps' : testGpsSweeps, 'reset' : resetDevice, 'iq' : testIqStreaming } if sys.argv[1] in funcs: logSetup.initLogging() sh = SignalHound() # sh.preset() # testDeviceStatusQueries(sh) # testRawPipeMode(sh) if len(sys.argv) == 2: funcs[sys.argv[1]](sh) if len(sys.argv) == 3: funcs[sys.argv[1]](sh, float(sys.argv[2])) # testCallback(sh) sh.closeDevice() else: print "Error! You must enter a valid test-mode!" printUsage()
def callbackTestFunc(bufPtr, bufLen): global START_TIME #hacking about for determining callback interval times. I shouldn't be using global, but fukkit. now = time.time() print "Callback!", bufPtr, bufLen print bufPtr[0] arr = SignalHound.decodeRawSweep(bufPtr, bufLen) print "NP Array = ", arr.shape, arr print "Elapsed Time = ", now-START_TIME START_TIME = now
def callbackTestFunc(bufPtr, bufLen): global START_TIME #hacking about for determining callback interval times. I shouldn't be using global, but fukkit. now = time.time() print "Callback!", bufPtr, bufLen print bufPtr[0] arr = SignalHound.decodeRawSweep(bufPtr, bufLen) print "NP Array = ", arr.shape, arr print "Elapsed Time = ", now - START_TIME START_TIME = now
def process(self): ret = self.rawDataRingBuf.getOldest() if ret != False: rawDataBuf, retreiveLock = ret # this immediate lock release is *probably* a bad idea, but as long as the buffer doesn't get almost entirely full, it should be OK. # It will also prevent blockages in the output buffer from propigating back to the input buffer. retreiveLock.release() # seqNum, dataDict = tmp["data"] # samples, triggers = dataDict["data"], dataDict["triggers"] # print(len(samples)) # samples = fft.fft(samples) # print "Doing FFT", seqNum samples = SignalHound.fastDecodeArray(rawDataBuf, SignalHound.rawSweepArrSize, np.short) for x in range(self.chunksPerAcq * self.overlap - 1): # Create byte-aligned array for efficent FFT, and copy the data we're interested into it. rets = pyfftw.n_byte_align_empty(self.outputSize, 16, dtype=np.complex64) dat = samples[x * (self.fftChunkSize / self.overlap): (x * (self.fftChunkSize / self.overlap)) + self.fftChunkSize] * self.window self.fftFunc(dat, rets) fftArr = self.fftFunc.get_output_array() # # log.warning("Buf = %s, arrSize = %s, dtype=%s, as floats = %s", processedDataBuf, fftArr.shape, fftArr.dtype, fftArr.view(dtype=np.float32).shape) # try: # processedDataBuf, addLock = self.fftDataRingBuf.getAddArray() # processedDataBuf[:] = fftArr.view(dtype=np.float32) # finally: # addLock.release() x += 1 return 1 return 0
def process(self): ret = self.rawDataRingBuf.getOldest() if ret != False: rawDataBuf, retreiveLock = ret # this immediate lock release is *probably* a bad idea, but as long as the buffer doesn't get almost entirely full, it should be OK. # It will also prevent blockages in the output buffer from propigating back to the input buffer. retreiveLock.release() # seqNum, dataDict = tmp["data"] # samples, triggers = dataDict["data"], dataDict["triggers"] # print(len(samples)) # samples = fft.fft(samples) # print "Doing FFT", seqNum samples = SignalHound.fastDecodeArray(rawDataBuf, SignalHound.rawSweepArrSize, np.short) for x in range(self.chunksPerAcq*self.overlap-1): # Create byte-aligned array for efficent FFT, and copy the data we're interested into it. rets = pyfftw.n_byte_align_empty(self.outputSize, 16, dtype=np.complex64) dat = samples[x*(self.fftChunkSize/self.overlap):(x*(self.fftChunkSize/self.overlap))+self.fftChunkSize] * self.window self.fftFunc(dat, rets) fftArr = self.fftFunc.get_output_array() # # log.warning("Buf = %s, arrSize = %s, dtype=%s, as floats = %s", processedDataBuf, fftArr.shape, fftArr.dtype, fftArr.view(dtype=np.float32).shape) # try: # processedDataBuf, addLock = self.fftDataRingBuf.getAddArray() # processedDataBuf[:] = fftArr.view(dtype=np.float32) # finally: # addLock.release() x += 1 return 1 return 0
def sweepSource(statusMessageQueue, ctrlNs, printQueue, ringBuf): from SignalHound import SignalHound logSetup.initLogging(printQ = printQueue) loop_timer = time.time() print "Starting sweep-logger!" log = logging.getLogger("Main.AcqProcess") loop_timer = time.time() seq_num = 0 sh = SignalHound() startAcquisition(sh, statusMessageQueue) temperature = sh.getDeviceDiagnostics()["temperature"] while ctrlNs.run: bufPtr, lock = ringBuf.getAddPointer() try: sh.fetchRaw_s(ctDataBufPtr=bufPtr) except Exception: log.error("IOError in Acquisition Thread!") log.error(traceback.format_exc()) statusMessageQueue.put({"status" : (time.time(), "Error: Device interface crashed. Reinitializing")}) log.error("Resetting hardware!") # sh.preset() sh.forceClose() try: while 1: log.warning("Freeing python device handle") del(sh) except UnboundLocalError: pass log.error("Hardware shut down, completely re-initializing device interface!") # sys.exit() sh = SignalHound() startAcquisition(sh, statusMessageQueue) finally: lock.release() if seq_num % PRINT_LOOP_CNT == 0: now = time.time() delta = now-loop_timer updateInterval = delta / PRINT_LOOP_CNT freq = 1 / updateInterval log.info("Elapsed Time = %0.5f, Frequency = %s. Items in buffer = %s", delta, freq, ringBuf.getItemsNum()) loop_timer = now # print if seq_num % CAL_CHK_LOOP_CNT == 0: diags = sh.getDeviceDiagnostics() statusMessageQueue.put({"status" : (time.time(), diags)}) temptmp = diags["temperature"] if abs(temperature - temptmp) > 2.0: # Temperature deviations of > 2° cause IF shifts. Therefore, we do a re-cal if they're detected statusMessageQueue.put({"status" : (time.time(), "Recalibrating IF due to temperature change")}) sh.selfCal() startAcquisition(sh, statusMessageQueue) log.warning("Temperature changed > 2.0 C. Delta is %f. Recalibrated!", abs(temperature - temptmp)) temperature = temptmp else: log.info("Temperature deviation = %f. Not doing recal, since drift < 2C", abs(temperature - temptmp)) seq_num += 1 sh.abort() sh.closeDevice() del(sh) ctrlNs.acqRunning = False log.info("Acquisition-thread exiting!")
def sweepSource(dataQueues, ctrlNs, printQueue): dataQueue, plotQueue = dataQueues from SignalHound import SignalHound logSetup.initLogging(printQ = printQueue) loop_timer = time.time() print "Starting sweep-logger!" log = logging.getLogger("Main.AcqProcess") loop_timer = time.time() loops = 0 sh = SignalHound() startAcquisition(sh, dataQueue, plotQueue) # Send the trace size to the acq thread so I can properly set up the data-log file numPoints = sh.queryTraceInfo()["arr-size"] dataQueue.put({"arrSize" : numPoints}) temperature = sh.getDeviceDiagnostics()["temperature"] runningSum = np.array(()) runningSumItems = 0 startFreq = 0 while 1: try: trace = sh.fetchTrace() traceInfo = sh.queryTraceInfo() dataDict = { "info": traceInfo, "data": trace } acqInfo = dataDict["info"] if runningSum.shape != dataDict["data"]["max"].shape: runningSum = np.zeros_like(dataDict["data"]["max"]) runningSumItems = 0 startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] log.info("Running average array size changed! Either the system just started, or something is seriously wrong!") changed = False if startFreq != acqInfo["ret-start-freq"]: changed = True else: runningSum += dataDict["data"]["max"] runningSumItems += 1 # if we've reached the number of average items per output array, or the frequency has changed, requiring an early dump of the specra data. if runningSumItems == NUM_AVERAGE or changed: # Divide down to the average arr = runningSum / runningSumItems # Build array to write out. saveTime = time.time() # log.info("Saving data record with timestamp %f", saveTime) # Only write out to the file if we actually have data if runningSumItems != 0: dataQueue.put({"row" : (saveTime, startFreq, binSize, runningSumItems, arr)}) if plotQueue: plotQueue.put({"row" : (saveTime, startFreq, binSize, runningSumItems, arr)}) del(trace) runningSum = np.zeros_like(runningSum) log.info("Estimated items in processing queue %s", dataQueue.qsize()) log.info("Running sum shape = %s, items = %s", runningSum.shape, runningSumItems) runningSumItems = 0 # now = time.time() # delta = now-loop_timer # freq = 1 / (delta) # log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) # loop_timer = now # If we wrote the output because the current spectra has changed, we need to update the running acq info variables with the new frequencies. if changed: log.info("Retuned! Old freq = %s, new freq = %s", startFreq, acqInfo["ret-start-freq"]) runningSum += dataDict["data"]["max"] startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] runningSumItems = 1 except Exception: log.error("IOError in Acquisition Thread!") log.error(traceback.format_exc()) dataQueue.put({"status" : "Error: Device interface crashed. Reinitializing"}) log.error("Resetting hardware!") # sh.preset() sh.forceClose() try: while 1: log.warning("Freeing python device handle") del(sh) except UnboundLocalError: pass log.error("Hardware shut down, completely re-initializing device interface!") # sys.exit() sh = SignalHound() startAcquisition(sh, dataQueue, plotQueue) if loops % PRINT_LOOP_CNT == 0: now = time.time() delta = now-loop_timer freq = 1 / (delta / PRINT_LOOP_CNT) # log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) loop_timer = now if loops % CAL_CHK_LOOP_CNT == 0: diags = sh.getDeviceDiagnostics() dataQueue.put({"status" : diags}) temptmp = diags["temperature"] if abs(temperature - temptmp) > 2.0: # Temperature deviations of > 2° cause IF shifts. Therefore, we do a re-cal if they're detected dataQueue.put({"status" : "Recalibrating IF"}) sh.selfCal() startAcquisition(sh, dataQueue, plotQueue) log.warning("Temperature changed > 2.0 C. Delta is %f. Recalibrated!", abs(temperature - temptmp)) temperature = temptmp else: log.info("Temperature deviation = %f. Not doing recal, since drift < 2C", abs(temperature - temptmp)) loops += 1 if ctrlNs.run == False: log.info("Stopping Acq-thread!") break sh.abort() sh.closeDevice() del(sh) log.info("Acq-thread closing dataQueue!") dataQueue.close() dataQueue.join_thread() if plotQueue: plotQueue.close() plotQueue.cancel_join_thread() ctrlNs.acqRunning = False log.info("Acq-thread exiting!") printQueue.close() printQueue.join_thread()
def go(): print("startup") statusMessageQueue = mp.Queue() fftDataQueue = mp.Queue() printQueue = mp.Queue() ctrlManager = mp.Manager() logSetup.initLogging(printQ = printQueue) log = logging.getLogger("Main.Main") ctrlNs = ctrlManager.Namespace() ctrlNs.run = True ctrlNs.acqRunning = True ctrlNs.procRunning = True ctrlNs.logRunning = True ctrlNs.printerRun = True ctrlNs.stopped = False # A separate process for printing, which allows nice easy non-blocking printing. printProc = mp.Process(target=printThread.printer, name="PrintFormatterThread", args=(printQueue, ctrlNs)) printProc.daemon = True printProc.start() rawDataRingBuf = sharedMemRingBuf.SharedMemRingBuf(2000, *SignalHound.getRawSweep_s_size()) # 32769 =fftChunkSize//2 + 1 (fftChunkSize = 2**16). Values are a complex64, which is really 2 32 bit floats fftDataRingBuf = sharedMemRingBuf.SharedMemRingBuf(1000, ct.c_float, 32769*2) print(rawDataRingBuf) fftWorkerPool = mp.Pool(processes=s.NUM_FFT_PROESSES, initializer=fftWorker.FFTWorker, initargs=(ctrlNs, printQueue, rawDataRingBuf, fftDataRingBuf)) acqProc = mp.Process(target=spectraAcqThread.sweepSource, name="SweepThread", args=(statusMessageQueue, ctrlNs, printQueue, rawDataRingBuf)) logProc = mp.Process(target=spectraLogThread.logSweeps, name="LogThread", args=(statusMessageQueue, fftDataRingBuf, ctrlNs, printQueue)) log.info("Waiting while worker-processes perform initialization") time.sleep(5) acqProc.start() logProc.start() try: while 1: inStr = raw_input() print inStr if inStr == "q": break except KeyboardInterrupt: pass log.info("Stopping Processes!") ctrlNs.run = False # fftWorkerPool.terminate() fftWorkerPool.close() # Sometimes the last few queue items take a little while to trickle in. # therefore, we both poll the queue for items, and try to join() the thread. That way # as soon as the queue is *actually* empty, we exit immediately # - - - # this was a f*****g nightmare to track down. log.info("Waiting for acquisition thread to halt.") acqProc.join() log.info("Acquisition thread halted.") log.info("Stopping worker thread pool.") ctrlNs.procRunning = False fftWorkerPool.join() log.info("Threadpool Halted.") log.info("Waiting for log-thread to halt.") while logProc.is_alive(): if not fftDataQueue.empty(): fftDataQueue.get() logProc.join() log.info("Logging thread halted.") log.info("stopping printing service") ctrlNs.printerRun = False if not printQueue.empty(): printQueue.get() printProc.join() print("Threads stopped.") print("Stopping Shared Memory Manager!") ctrlManager.shutdown() print("Shutdown complete. Exiting.") sys.exit()
class InternalSweepAcqThread(object): log = logging.getLogger("Main.AcqProcess") def __init__(self, printQueue): self.printQueue = printQueue logSetup.initLogging(printQ=printQueue) self.calcScanBands() if ACQ_TYPE != "real-time-sweeping": raise ValueError("internalSweep module only supports 'real-time-sweeping' mode! Configured mode = {mode}".format(mode=ACQ_TYPE)) def calcScanBands(self): if ACQ_SPAN < IF_WIDTH: raise ValueError("Scan width is smaller then the IF bandwidth!") if ACQ_SPAN == IF_WIDTH: raise ValueError("Scan width is exactly the IF bandwith. Maybe use the real-time mode instead?") sweepWidth = IF_WIDTH * (1-ACQ_OVERLAP) bins = ACQ_SPAN/sweepWidth sweepSteps = int(bins+0.5) effectiveScanWidth = sweepWidth*sweepSteps self.binFreqs = [] baseFreq = ACQ_FREQ - (effectiveScanWidth/2 + sweepWidth/2) for x in xrange(1, sweepSteps+1): self.binFreqs.append(baseFreq+x*sweepWidth) self.binFreqIndice = 0 def retune(self): self.sh.configureCenterSpan(center = self.binFreqs[self.binFreqIndice], span = IF_WIDTH) self.binFreqIndice = (self.binFreqIndice + 1) % len(self.binFreqs) def startAcquisition(self, dataQueue, plotQueue): self.sh.configureAcquisition(ACQ_MODE, ACQ_Y_SCALE) self.retune() self.sh.configureLevel(ref = ACQ_REF_LEVEL_DB, atten = ACQ_ATTENUATION_DB) self.sh.configureGain(gain = ACQ_GAIN_SETTING) self.sh.configureSweepCoupling(rbw = ACQ_RBW, vbw = ACQ_VBW, sweepTime = ACQ_SWEEP_TIME_SECONDS, rbwType = "native", rejection = "no-spur-reject") self.sh.configureWindow(window = ACQ_WINDOW_TYPE) self.sh.configureProcUnits(units = ACQ_UNITS) self.sh.configureTrigger(trigType = "none", edge = "rising-edge", level = 0, timeout = 5) self.sh.initiate(mode = "real-time", flag = "ignored") dataQueue.put({"settings" : self.sh.getCurrentAcquisitionSettings()}) plotQueue.put({"settings" : self.sh.getCurrentAcquisitionSettings()}) def sweepSource(self, dataQueues, ctrlNs): dataQueue, plotQueue = dataQueues from SignalHound import SignalHound loop_timer = time.time() print "Starting sweep-logger!" loop_timer = time.time() loops = 0 self.sh = SignalHound() self.startAcquisition(dataQueue, plotQueue) # Send the trace size to the acq thread so I can properly set up the data-log file numPoints = self.sh.queryTraceInfo()["arr-size"] dataQueue.put({"arrSize" : numPoints}) temperature = self.sh.getDeviceDiagnostics()["temperature"] runningSum = np.array(()) runningSumItems = 0 startFreq = 0 while 1: try: trace = self.sh.fetchTrace() traceInfo = self.sh.queryTraceInfo() dataDict = { "info": traceInfo, "data": trace } acqInfo = dataDict["info"] if runningSum.shape != dataDict["data"]["max"].shape: runningSum = np.zeros_like(dataDict["data"]["max"]) runningSumItems = 0 startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] self.log.info("Running average array size changed! Either the system just started, or something is seriously wrong!") changed = False if startFreq != acqInfo["ret-start-freq"]: changed = True else: runningSum += dataDict["data"]["max"] runningSumItems += 1 # if we've reached the number of average items per output array, or the frequency has changed, requiring an early dump of the specra data. if runningSumItems == NUM_AVERAGE or changed: self.log.info("Running sum shape = %s, items = %s", runningSum.shape, runningSumItems) # Divide down to the average arr = runningSum / runningSumItems # Build array to write out. saveTime = time.time() # self.log.info("Saving data record with timestamp %f", saveTime) # Only write out to the file if we actually have data if runningSumItems != 0: dataQueue.put({"row" : (saveTime, startFreq, binSize, runningSumItems, arr)}) if plotQueue: plotQueue.put({"row" : (saveTime, startFreq, binSize, runningSumItems, arr)}) runningSum = np.zeros_like(runningSum) self.log.info("Estimated items in processing queue %s", dataQueue.qsize()) self.log.info("Running sum shape = %s, items = %s", runningSum.shape, runningSumItems) runningSumItems = 0 # now = time.time() # delta = now-loop_timer # freq = 1 / (delta) # self.log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) # loop_timer = now # If we wrote the output because the current spectra has changed, we need to update the running acq info variables with the new frequencies. if changed: self.log.info("Retuned! Old freq = %s, new freq = %s", startFreq, acqInfo["ret-start-freq"]) runningSum += dataDict["data"]["max"] startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] runningSumItems = 1 del(trace) except Exception: self.log.error("IOError in Acquisition Thread!") self.log.error(traceback.format_exc()) dataQueue.put({"status" : "Error: Device interface craself.shed. Reinitializing"}) self.log.error("Resetting hardware!") # self.sh.preset() self.sh.forceClose() try: while 1: self.log.warning("Trying to free python device handle") del(self.sh) except UnboundLocalError: self.log.info("Handle freed?") except AttributeError: self.log.info("Handle freed?") self.log.error("Hardware shut down, completely re-initializing device interface!") # sys.exit() self.log.info("Preparing to reset device.") self.sh = SignalHound() self.log.info("Performing hardware reset") self.sh.preset() self.log.info("Reset triggered. Waiting 5 seconds for device to restart.") time.sleep(5) self.log.info("Hardware reset. Reopening device.") self.sh = SignalHound() self.startAcquisition(dataQueue, dataQueue) loops += 1 if loops % ACQ_BIN_SAMPLES == 0: print("Should retune frontend!") self.sh.abort() self.startAcquisition(dataQueue, dataQueue) # print("Current acq mode = ", self.sh.queryTraceInfo()) if loops % PRINT_LOOP_CNT == 0: now = time.time() delta = now-loop_timer freq = 1 / (delta / PRINT_LOOP_CNT) # self.log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) loop_timer = now if loops % CAL_CHK_LOOP_CNT == 0: diags = self.sh.getDeviceDiagnostics() dataQueue.put({"status" : diags}) temptmp = diags["temperature"] if abs(temperature - temptmp) > 2.0: # Temperature deviations of > 2° cause IF self.shifts. Therefore, we do a re-cal if they're detected dataQueue.put({"status" : "Recalibrating IF"}) self.sh.selfCal() self.startAcquisition(dataQueue, dataQueue) self.log.warning("Temperature changed > 2.0 C. Delta is %f. Recalibrated!", abs(temperature - temptmp)) temperature = temptmp else: self.log.info("Temperature deviation = %f. Not doing recal, since drift < 2C", abs(temperature - temptmp)) if ctrlNs.run == False: self.log.info("Stopping Acq-thread!") break self.sh.abort() self.sh.closeDevice() del(self.sh) self.log.info("Acq-thread closing dataQueue!") dataQueue.close() dataQueue.join_thread() plotQueue.close() plotQueue.cancel_join_thread() ctrlNs.acqRunning = False self.log.info("Acq-thread exiting!") self.printQueue.close() self.printQueue.join_thread()
def sweepSource(dataQueues, ctrlNs, printQueue): dataQueue, plotQueue = dataQueues from SignalHound import SignalHound logSetup.initLogging(printQ=printQueue) loop_timer = time.time() print "Starting sweep-logger!" log = logging.getLogger("Main.AcqProcess") loop_timer = time.time() loops = 0 sh = SignalHound() startAcquisition(sh, dataQueue, plotQueue) # Send the trace size to the acq thread so I can properly set up the data-log file numPoints = sh.queryTraceInfo()["arr-size"] dataQueue.put({"arrSize": numPoints}) temperature = sh.getDeviceDiagnostics()["temperature"] runningSum = np.array(()) runningSumItems = 0 startFreq = 0 while 1: try: trace = sh.fetchTrace() traceInfo = sh.queryTraceInfo() dataDict = {"info": traceInfo, "data": trace} acqInfo = dataDict["info"] if runningSum.shape != dataDict["data"]["max"].shape: runningSum = np.zeros_like(dataDict["data"]["max"]) runningSumItems = 0 startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] log.info( "Running average array size changed! Either the system just started, or something is seriously wrong!" ) changed = False if startFreq != acqInfo["ret-start-freq"]: changed = True else: runningSum += dataDict["data"]["max"] runningSumItems += 1 # if we've reached the number of average items per output array, or the frequency has changed, requiring an early dump of the specra data. if runningSumItems == NUM_AVERAGE or changed: # Divide down to the average arr = runningSum / runningSumItems # Build array to write out. saveTime = time.time() # log.info("Saving data record with timestamp %f", saveTime) # Only write out to the file if we actually have data if runningSumItems != 0: dataQueue.put({ "row": (saveTime, startFreq, binSize, runningSumItems, arr) }) if plotQueue: plotQueue.put({ "row": (saveTime, startFreq, binSize, runningSumItems, arr) }) del (trace) runningSum = np.zeros_like(runningSum) log.info("Estimated items in processing queue %s", dataQueue.qsize()) log.info("Running sum shape = %s, items = %s", runningSum.shape, runningSumItems) runningSumItems = 0 # now = time.time() # delta = now-loop_timer # freq = 1 / (delta) # log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) # loop_timer = now # If we wrote the output because the current spectra has changed, we need to update the running acq info variables with the new frequencies. if changed: log.info("Retuned! Old freq = %s, new freq = %s", startFreq, acqInfo["ret-start-freq"]) runningSum += dataDict["data"]["max"] startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] runningSumItems = 1 except Exception: log.error("IOError in Acquisition Thread!") log.error(traceback.format_exc()) dataQueue.put( {"status": "Error: Device interface crashed. Reinitializing"}) log.error("Resetting hardware!") # sh.preset() sh.forceClose() try: while 1: log.warning("Freeing python device handle") del (sh) except UnboundLocalError: pass log.error( "Hardware shut down, completely re-initializing device interface!" ) # sys.exit() sh = SignalHound() startAcquisition(sh, dataQueue, plotQueue) if loops % PRINT_LOOP_CNT == 0: now = time.time() delta = now - loop_timer freq = 1 / (delta / PRINT_LOOP_CNT) # log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) loop_timer = now if loops % CAL_CHK_LOOP_CNT == 0: diags = sh.getDeviceDiagnostics() dataQueue.put({"status": diags}) temptmp = diags["temperature"] if abs( temperature - temptmp ) > 2.0: # Temperature deviations of > 2° cause IF shifts. Therefore, we do a re-cal if they're detected dataQueue.put({"status": "Recalibrating IF"}) sh.selfCal() startAcquisition(sh, dataQueue, plotQueue) log.warning( "Temperature changed > 2.0 C. Delta is %f. Recalibrated!", abs(temperature - temptmp)) temperature = temptmp else: log.info( "Temperature deviation = %f. Not doing recal, since drift < 2C", abs(temperature - temptmp)) loops += 1 if ctrlNs.run == False: log.info("Stopping Acq-thread!") break sh.abort() sh.closeDevice() del (sh) log.info("Acq-thread closing dataQueue!") dataQueue.close() dataQueue.join_thread() if plotQueue: plotQueue.close() plotQueue.cancel_join_thread() ctrlNs.acqRunning = False log.info("Acq-thread exiting!") printQueue.close() printQueue.join_thread()
class InternalSweepAcqThread(object): log = logging.getLogger("Main.AcqProcess") def __init__(self, printQueue): self.printQueue = printQueue logSetup.initLogging(printQ=printQueue) self.calcScanBands() if ACQ_TYPE != "real-time-sweeping": raise ValueError( "internalSweep module only supports 'real-time-sweeping' mode! Configured mode = {mode}" .format(mode=ACQ_TYPE)) def calcScanBands(self): if ACQ_SPAN < IF_WIDTH: raise ValueError("Scan width is smaller then the IF bandwidth!") if ACQ_SPAN == IF_WIDTH: raise ValueError( "Scan width is exactly the IF bandwith. Maybe use the real-time mode instead?" ) sweepWidth = IF_WIDTH * (1 - ACQ_OVERLAP) bins = ACQ_SPAN / sweepWidth sweepSteps = int(bins + 0.5) effectiveScanWidth = sweepWidth * sweepSteps self.binFreqs = [] baseFreq = ACQ_FREQ - (effectiveScanWidth / 2 + sweepWidth / 2) for x in xrange(1, sweepSteps + 1): self.binFreqs.append(baseFreq + x * sweepWidth) self.binFreqIndice = 0 def retune(self): self.sh.configureCenterSpan(center=self.binFreqs[self.binFreqIndice], span=IF_WIDTH) self.binFreqIndice = (self.binFreqIndice + 1) % len(self.binFreqs) def startAcquisition(self, dataQueue, plotQueue): self.sh.configureAcquisition(ACQ_MODE, ACQ_Y_SCALE) self.retune() self.sh.configureLevel(ref=ACQ_REF_LEVEL_DB, atten=ACQ_ATTENUATION_DB) self.sh.configureGain(gain=ACQ_GAIN_SETTING) self.sh.configureSweepCoupling(rbw=ACQ_RBW, vbw=ACQ_VBW, sweepTime=ACQ_SWEEP_TIME_SECONDS, rbwType="native", rejection="no-spur-reject") self.sh.configureWindow(window=ACQ_WINDOW_TYPE) self.sh.configureProcUnits(units=ACQ_UNITS) self.sh.configureTrigger(trigType="none", edge="rising-edge", level=0, timeout=5) self.sh.initiate(mode="real-time", flag="ignored") dataQueue.put({"settings": self.sh.getCurrentAcquisitionSettings()}) plotQueue.put({"settings": self.sh.getCurrentAcquisitionSettings()}) def sweepSource(self, dataQueues, ctrlNs): dataQueue, plotQueue = dataQueues from SignalHound import SignalHound loop_timer = time.time() print "Starting sweep-logger!" loop_timer = time.time() loops = 0 self.sh = SignalHound() self.startAcquisition(dataQueue, plotQueue) # Send the trace size to the acq thread so I can properly set up the data-log file numPoints = self.sh.queryTraceInfo()["arr-size"] dataQueue.put({"arrSize": numPoints}) temperature = self.sh.getDeviceDiagnostics()["temperature"] runningSum = np.array(()) runningSumItems = 0 startFreq = 0 while 1: try: trace = self.sh.fetchTrace() traceInfo = self.sh.queryTraceInfo() dataDict = {"info": traceInfo, "data": trace} acqInfo = dataDict["info"] if runningSum.shape != dataDict["data"]["max"].shape: runningSum = np.zeros_like(dataDict["data"]["max"]) runningSumItems = 0 startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] self.log.info( "Running average array size changed! Either the system just started, or something is seriously wrong!" ) changed = False if startFreq != acqInfo["ret-start-freq"]: changed = True else: runningSum += dataDict["data"]["max"] runningSumItems += 1 # if we've reached the number of average items per output array, or the frequency has changed, requiring an early dump of the specra data. if runningSumItems == NUM_AVERAGE or changed: self.log.info("Running sum shape = %s, items = %s", runningSum.shape, runningSumItems) # Divide down to the average arr = runningSum / runningSumItems # Build array to write out. saveTime = time.time() # self.log.info("Saving data record with timestamp %f", saveTime) # Only write out to the file if we actually have data if runningSumItems != 0: dataQueue.put({ "row": (saveTime, startFreq, binSize, runningSumItems, arr) }) if plotQueue: plotQueue.put({ "row": (saveTime, startFreq, binSize, runningSumItems, arr) }) runningSum = np.zeros_like(runningSum) self.log.info("Estimated items in processing queue %s", dataQueue.qsize()) self.log.info("Running sum shape = %s, items = %s", runningSum.shape, runningSumItems) runningSumItems = 0 # now = time.time() # delta = now-loop_timer # freq = 1 / (delta) # self.log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) # loop_timer = now # If we wrote the output because the current spectra has changed, we need to update the running acq info variables with the new frequencies. if changed: self.log.info("Retuned! Old freq = %s, new freq = %s", startFreq, acqInfo["ret-start-freq"]) runningSum += dataDict["data"]["max"] startFreq = acqInfo["ret-start-freq"] binSize = acqInfo["arr-bin-size"] runningSumItems = 1 del (trace) except Exception: self.log.error("IOError in Acquisition Thread!") self.log.error(traceback.format_exc()) dataQueue.put({ "status": "Error: Device interface craself.shed. Reinitializing" }) self.log.error("Resetting hardware!") # self.sh.preset() self.sh.forceClose() try: while 1: self.log.warning("Trying to free python device handle") del (self.sh) except UnboundLocalError: self.log.info("Handle freed?") except AttributeError: self.log.info("Handle freed?") self.log.error( "Hardware shut down, completely re-initializing device interface!" ) # sys.exit() self.log.info("Preparing to reset device.") self.sh = SignalHound() self.log.info("Performing hardware reset") self.sh.preset() self.log.info( "Reset triggered. Waiting 5 seconds for device to restart." ) time.sleep(5) self.log.info("Hardware reset. Reopening device.") self.sh = SignalHound() self.startAcquisition(dataQueue, dataQueue) loops += 1 if loops % ACQ_BIN_SAMPLES == 0: print("Should retune frontend!") self.sh.abort() self.startAcquisition(dataQueue, dataQueue) # print("Current acq mode = ", self.sh.queryTraceInfo()) if loops % PRINT_LOOP_CNT == 0: now = time.time() delta = now - loop_timer freq = 1 / (delta / PRINT_LOOP_CNT) # self.log.info("Elapsed Time = %0.5f, Frequency = %s", delta, freq) loop_timer = now if loops % CAL_CHK_LOOP_CNT == 0: diags = self.sh.getDeviceDiagnostics() dataQueue.put({"status": diags}) temptmp = diags["temperature"] if abs( temperature - temptmp ) > 2.0: # Temperature deviations of > 2° cause IF self.shifts. Therefore, we do a re-cal if they're detected dataQueue.put({"status": "Recalibrating IF"}) self.sh.selfCal() self.startAcquisition(dataQueue, dataQueue) self.log.warning( "Temperature changed > 2.0 C. Delta is %f. Recalibrated!", abs(temperature - temptmp)) temperature = temptmp else: self.log.info( "Temperature deviation = %f. Not doing recal, since drift < 2C", abs(temperature - temptmp)) if ctrlNs.run == False: self.log.info("Stopping Acq-thread!") break self.sh.abort() self.sh.closeDevice() del (self.sh) self.log.info("Acq-thread closing dataQueue!") dataQueue.close() dataQueue.join_thread() plotQueue.close() plotQueue.cancel_join_thread() ctrlNs.acqRunning = False self.log.info("Acq-thread exiting!") self.printQueue.close() self.printQueue.join_thread()