Example #1
0
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()
Example #2
0
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
Example #3
0
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
Example #4
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
Example #5
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
Example #6
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()
Example #8
0
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()
Example #10
0
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()
Example #11
0
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()