def showAxisDialog(self): # todo : converting to double ... check b dialog = pyVacGraphAxesDialog(self) if type(self.axisScaleEngine(Qwt.QwtPlot.yLeft)) == type( Qwt.QwtLog10ScaleEngine()): dialog.ui.LogRadioButton_1.setChecked(True) else: dialog.ui.LinRadioButton_1.setChecked(True) if type(self.axisScaleEngine(Qwt.QwtPlot.yRight)) == type( Qwt.QwtLog10ScaleEngine()): dialog.ui.LogRadioButton_2.setChecked(True) else: dialog.ui.LinRadioButton_2.setChecked(True) if self.axisAutoScale(Qwt.QwtPlot.yLeft): dialog.ui.AutoRangeCheckBox_1.setChecked(True) if self.axisAutoScale(Qwt.QwtPlot.yRight): dialog.ui.AutoRangeCheckBox_2.setChecked(True) if dialog.exec_() == QDialog.Accepted: # Set the axes if dialog.ui.LogRadioButton_1.isChecked(): self.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) else: self.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) if dialog.ui.LogRadioButton_2.isChecked(): self.setAxisScaleEngine(Qwt.QwtPlot.yRight, Qwt.QwtLog10ScaleEngine()) else: self.setAxisScaleEngine(Qwt.QwtPlot.yRight, Qwt.QwtLinearScaleEngine()) if dialog.ui.AutoRangeCheckBox_1.isChecked(): self.setAxisAutoScale(Qwt.QwtPlot.yLeft) else: min, b = dialog.ui.MinLineEdit_1.text().toDouble() max, b = dialog.ui.MaxLineEdit_1.text().toDouble() self.setAxisScale(Qwt.QwtPlot.yLeft, min, max) if dialog.ui.AutoRangeCheckBox_2.isChecked(): self.setAxisAutoScale(Qwt.QwtPlot.yRight) else: min, b = dialog.ui.MinLineEdit_2.text().toDouble() max, b = dialog.ui.MaxLineEdit_2.text().toDouble() self.setAxisScale(Qwt.QwtPlot.yRight, min, max) self.replot()
def __init__(self, parent, logger): ClassPlot.__init__(self) # store the logger instance self.logger = logger # we do not need caching self.canvas().setPaintAttribute(Qwt.QwtPlotCanvas.PaintCached, False) self.canvas().setPaintAttribute(Qwt.QwtPlotCanvas.PaintPacked, False) # attach a grid grid = Qwt.QwtPlotGrid() grid.setMajPen(Qt.QPen(Qt.Qt.lightGray)) grid.attach(self) xtitle = Qwt.QwtText('Time (ms)') xtitle.setFont(QtGui.QFont(8)) self.setAxisTitle(Qwt.QwtPlot.xBottom, xtitle) self.setAxisScale(Qwt.QwtPlot.yLeft, -1., 1.) # self.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time (ms)') self.xmin = 0. self.xmax = 1. ytitle = Qwt.QwtText('Signal') ytitle.setFont(QtGui.QFont(8)) self.setAxisTitle(Qwt.QwtPlot.yLeft, ytitle) # self.setAxisTitle(Qwt.QwtPlot.yLeft, 'Signal') self.setAxisScale(Qwt.QwtPlot.yLeft, -1., 1.) self.setAxisScaleEngine(Qwt.QwtPlot.xBottom, Qwt.QwtLinearScaleEngine()) self.paint_time = 0. self.canvas_width = 0 self.dual_channel = False # insert an additional curve for the second channel # (ClassPlot already has one by default) self.curve2 = Qwt.QwtPlotCurve("Ch2") self.curve2.setPen(QtGui.QPen(Qt.Qt.blue)) #self.curve.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) #self.curve2.attach(self) # gives an appropriate title to the first curve # (for the legend) self.curve.setTitle("Ch1") # picker used to display coordinates when clicking on the canvas self.picker = picker(Qwt.QwtPlot.xBottom, Qwt.QwtPlot.yLeft, Qwt.QwtPicker.PointSelection, Qwt.QwtPlotPicker.CrossRubberBand, Qwt.QwtPicker.ActiveOnly, self.canvas()) self.cached_canvas = self.canvas() #need to replot here for the size Hints to be computed correctly (depending on axis scales...) self.replot()
def setlinfreqscale(self): self.logx = False self.horizontalScaleEngine = Qwt.QwtLinearScaleEngine() self.horizontalScale.setScaleDiv( self.horizontalScaleEngine.transformation(), self.horizontalScaleEngine.divideScale(self.xmin, self.xmax, 8, 5)) self.needtransform = True self.draw()
def toggleLogScale(self): """Change the scale to base 10 or log scale.""" if self.logScaleAct.isChecked(): self.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.replot() else: self.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.replot()
def checkbox_log_change(self, state): if state == QtCore.Qt.Checked: # Set plot to logarithmic self.qwtPlotFullScan.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.qwtPlotFullScan.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) else: # Set plot to linear #self.qwtPlotFullScan.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.qwtPlotFullScan.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.qwtPlotFullScan.replot()
def log_check(self, log, replot=True): self.log = log min_intes = self.data.intes_array.min() max_intes = math.ceil(self.data.intes_array.max()) + 1.0 if log: # most of this is changing color scaling for logarithimc colorMap = Qwt.QwtLinearColorMap(Qt.Qt.darkCyan, Qt.Qt.red) if min_intes <= 0: logmin = 0.01 else: logmin = min_intes self.setAxisScale(Qwt.QwtPlot.yRight, logmin, max_intes) oom = int( math.log10(max_intes) ) # for log scale we will add in colours depnding on order of magnatiude (oom) map = [[1.0 / (10**oom), Qt.Qt.cyan], [0.1, Qt.Qt.yellow], [0.01, Qt.Qt.darkGreen], [1.0 / (10**(oom - 1)), Qt.Qt.blue], [1.0 / (10**(oom - 2)), Qt.Qt.darkBlue], [1.0 / (10**(oom - 3)), Qt.Qt.green]] for i in range(oom): colorMap.addColorStop(map[i][0], map[i][1]) self.__spectrogram.setColorMap(colorMap) self.setAxisScaleEngine(Qwt.QwtPlot.yRight, Qwt.QwtLog10ScaleEngine()) else: colorMap = Qwt.QwtLinearColorMap(Qt.Qt.darkCyan, Qt.Qt.red) self.setAxisScale(Qwt.QwtPlot.yRight, math.floor(min_intes), math.ceil(max_intes)) colorMap.addColorStop(0.25, Qt.Qt.cyan) colorMap.addColorStop(0.5, Qt.Qt.darkGreen) colorMap.addColorStop(0.75, Qt.Qt.yellow) self.setAxisScaleEngine(Qwt.QwtPlot.yRight, Qwt.QwtLinearScaleEngine()) self.__spectrogram.setColorMap(colorMap) self.__spectrogram.attach(self) rightAxis = self.axisWidget(Qwt.QwtPlot.yRight) rightAxis.setTitle("Intensity") rightAxis.setColorBarEnabled(True) rightAxis.setColorMap(self.__spectrogram.data().range(), self.__spectrogram.colorMap()) self.enableAxis(Qwt.QwtPlot.yRight) if replot: self.replot()
def disableInAxis(plot, axis, scaleDraw=None, scaleEngine=None): '''convenience method that will disable this engine in the given axis. Note that it changes the ScaleDraw as well. :param plot: (Qwt5.QwtPlot) the plot to change :param axis: (Qwt5.QwtPlot.Axis) the id of the axis :param scaleDraw: (Qwt5.QwtScaleDraw) Scale draw to use. If None given, a :class:`FancyScaleDraw` will be set :param scaleEngine: (Qwt5.QwtScaleEngine) Scale draw to use. If None given, a :class:`Qwt5.QwtLinearScaleEngine` will be set ''' if scaleDraw is None: scaleDraw = FancyScaleDraw() if scaleEngine is None: scaleEngine = Qwt5.QwtLinearScaleEngine() plot.setAxisScaleEngine(axis, scaleEngine) plot.setAxisScaleDraw(axis, scaleDraw)
def divideScale(self, x1, x2, maxMajSteps, maxMinSteps, stepSize): interval = Qwt.QwtDoubleInterval(x1, x2).normalized() interval = interval.limited(LOG2_MIN, LOG2_MAX) if interval.width() <= 0: return Qwt.QwtScaleDiv() base = 2. if interval.maxValue() / interval.minValue() < base: # scale width is less than one octave -> build linear scale linearScaler = Qwt.QwtLinearScaleEngine() linearScaler.setAttributes(self.attributes()) linearScaler.setReference(self.reference()) linearScaler.setMargins(self.lowerMargin(), self.upperMargin()) return linearScaler.divideScale(x1, x2, maxMajSteps, maxMinSteps, stepSize) stepSize = abs(stepSize) if stepSize == 0.: if maxMajSteps < 1: maxMajSteps = 1 stepSize = self.divideInterval( self.log2(interval).width(), maxMajSteps) if stepSize < 1.: stepSize = 1. # major step must be >= 1 decade scaleDiv = Qwt.QwtScaleDiv() if stepSize <> 0.: ticks = self.buildTicks(interval, stepSize, maxMinSteps) scaleDiv = Qwt.QwtScaleDiv(interval, ticks[0], ticks[1], ticks[2]) if x1 > x2: scaleDiv.invert() return scaleDiv
def __init__(self, *args): Qwt.QwtPlot.__init__(self, *args) self.setCanvasBackground(QColor("LightGrey")) self.colors = itertools.cycle([ Qt.red, Qt.green, Qt.blue, Qt.cyan, Qt.magenta, Qt.yellow, Qt.darkRed, Qt.darkGreen, Qt.darkBlue, Qt.darkCyan, Qt.darkMagenta, Qt.darkYellow ]) # legend self.legend = Qwt.QwtLegend() self.legend.setItemMode(Qwt.QwtLegend.ClickableItem) self.legend.setFrameStyle(QFrame.Box | QFrame.Sunken) self.insertLegend(self.legend, Qwt.QwtPlot.RightLegend) self.connect(self, SIGNAL("legendClicked(QwtPlotItem *)"), self.legendClicked) # Axes self.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.setAxisScaleEngine(Qwt.QwtPlot.yRight, Qwt.QwtLinearScaleEngine()) self.axisScaleEngine(Qwt.QwtPlot.yLeft).setAttribute( Qwt.QwtScaleEngine.Floating) self.setAxisTitle(Qwt.QwtPlot.xBottom, "Time [h:m:s]") sd = TimeScaleDraw() self.setAxisScaleDraw(Qwt.QwtPlot.xBottom, sd) self.enableAxis(Qwt.QwtPlot.yRight) # Setup list of plots to hold self.curve = {}
def setlinfreqscale(self): self.plotImage.erase() self.logfreqscale = 0 self.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.replot()
def __init__(self, *args): apply(Qwt.QwtPlot.__init__, (self, ) + args) self.setTitle('Scope') self.setCanvasBackground(Qt.Qt.white) # grid self.grid = Qwt.QwtPlotGrid() self.grid.enableXMin(True) self.grid.setMajPen(Qt.QPen(Qt.Qt.gray, 0, Qt.Qt.SolidLine)) self.grid.attach(self) # axes self.enableAxis(Qwt.QwtPlot.yRight) self.setAxisTitle(Qwt.QwtPlot.xBottom, 'Time [s]') self.setAxisTitle(Qwt.QwtPlot.yLeft, 'Amplitude []') self.setAxisMaxMajor(Qwt.QwtPlot.xBottom, 10) self.setAxisMaxMinor(Qwt.QwtPlot.xBottom, 0) self.setAxisScaleEngine(Qwt.QwtPlot.yRight, Qwt.QwtLinearScaleEngine()) self.setAxisMaxMajor(Qwt.QwtPlot.yLeft, 10) self.setAxisMaxMinor(Qwt.QwtPlot.yLeft, 0) self.setAxisMaxMajor(Qwt.QwtPlot.yRight, 10) self.setAxisMaxMinor(Qwt.QwtPlot.yRight, 0) # curves for scope traces: 2 first so 1 is on top self.curve2 = Qwt.QwtPlotCurve('Trace2') self.curve2.setSymbol( Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, Qt.QBrush(2), Qt.QPen(Qt.Qt.darkMagenta), Qt.QSize(3, 3))) self.curve2.setPen(Qt.QPen(Qt.Qt.magenta, TIMEPENWIDTH)) self.curve2.setYAxis(Qwt.QwtPlot.yRight) self.curve2.attach(self) self.curve1 = Qwt.QwtPlotCurve('Trace1') self.curve1.setSymbol( Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, Qt.QBrush(2), Qt.QPen(Qt.Qt.darkBlue), Qt.QSize(3, 3))) self.curve1.setPen(Qt.QPen(Qt.Qt.blue, TIMEPENWIDTH)) self.curve1.setYAxis(Qwt.QwtPlot.yLeft) self.curve1.attach(self) # default settings self.triggerval = 0.10 self.triggerCH = None self.triggerslope = 0 self.maxamp = 100.0 self.maxamp2 = 100.0 self.freeze = 0 self.average = 0 self.autocorrelation = 0 self.avcount = 0 self.datastream = None self.offset1 = 0.0 self.offset2 = 0.0 self.maxtime = 0.1 # set data # NumPy: f, g, a and p are arrays! self.dt = 1.0 / samplerate self.f = np.arange(0.0, 10.0, self.dt) self.a1 = 0.0 * self.f self.a2 = 0.0 * self.f self.curve1.setData(self.f, self.a1) self.curve2.setData(self.f, self.a2) # start self.timerEvent() callbacks running self.timer_id = self.startTimer(self.maxtime * 100 + 50) # plot self.replot()
def setlinfreqscale(self): self.logfreqscale = False self.setAxisScaleEngine(Qwt.QwtPlot.xBottom, Qwt.QwtLinearScaleEngine()) self.update_xscale() self.needfullreplot = True
def updateTransferFunctionDisplay(self): if hasattr(self, 'transfer_function_dictionary') == False: return # Get which curve we should be displaying: (input_select, output_select, first_modulation_frequency_in_hz, last_modulation_frequency_in_hz, number_of_frequencies, System_settling_time, output_amplitude) = self.readSystemIdentificationSettings() try: H_measured_openloop = -self.transfer_function_dictionary[ (input_select, output_select, 0)] freq_axis_openloop = self.transfer_freq_axis_dictionary[( input_select, output_select, 0)] except: H_measured_openloop = np.array((1, 1)) freq_axis_openloop = np.array((1, 1)) try: H_measured_fll = -self.transfer_function_dictionary[ (input_select, output_select, 1)] freq_axis_fll = self.transfer_freq_axis_dictionary[(input_select, output_select, 1)] except: H_measured_fll = np.array((1, 1)) freq_axis_fll = np.array((1, 1)) # Predicted closed-loop response: # Add the PLL loop filter's transfer function ###### TODO: Have the sl object return the loop filters' transfer function instead of re-deriving it everywhere. P_gain = 0 I_gain = 0 N_delay_p = 5 # TODO: put the correct values here N_delay_i = 6 # TODO: put the correct values here H_cumsum = 1 / ( 1 - np.exp(-1j * 2 * np.pi * freq_axis_openloop / self.sl.fs)) phase_ramp = 2 * np.pi * freq_axis_openloop / self.sl.fs H_controller = P_gain * np.exp( -1j * N_delay_p * phase_ramp) + I_gain * H_cumsum * np.exp( -1j * N_delay_i * phase_ramp) H_measured_openloop = H_measured_openloop * np.exp( 1j * 2 * np.pi * 3 * freq_axis_openloop / self.sl.fs ) # we cancel 3 samples delay because these come from the VNA itself H_measured_fll = H_measured_fll * np.exp( 1j * 2 * np.pi * 3 * freq_axis_fll / self.sl.fs ) # we cancel 3 samples delay because these come from the VNA itself H_predicted_fll = H_measured_openloop / ( 1 + H_measured_openloop * H_controller) if len(freq_axis_openloop) > 2: self.curve_openloop.setData( freq_axis_openloop, 20 * np.log10(np.abs(H_measured_openloop * H_controller))) self.curve_openloop_closed.setData( freq_axis_openloop, 20 * np.log10(np.abs(1 / (1 + H_measured_openloop * H_controller)))) # Handle the units # magnitude is currently in linear a linear scale units/units. # The units choices for the graph are: # self.qcombo_transfer_units.addItems(['dBunits/units', 'Hz/fullscale', 'Hz/V']) if self.qcombo_transfer_units.currentIndex() == 0: # dB units/units if len(freq_axis_openloop) > 2: self.curve_transfer_openloop.setData( freq_axis_openloop, 20 * np.log10(np.abs(H_measured_openloop))) self.curve_transfer_closedloop_predicted.setData( freq_axis_openloop, 20 * np.log10(np.abs(H_predicted_fll))) if len(freq_axis_fll) > 2: self.curve_transfer_closedloop.setData( freq_axis_fll, 20 * np.log10(np.abs(H_measured_fll))) self.qplt_transfer.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.qplt_transfer.setAxisTitle(Qwt.QwtPlot.yLeft, 'Gain [dBunits/units]') elif self.qcombo_transfer_units.currentIndex() == 1: # Hz/fullscale # 2**10 is the number of fractional bits on the phase, while 2**16 is the fullscale output range in counts conversion_factor = self.sl.fs / 2**10 * 2**16 if len(freq_axis_openloop) > 2: self.curve_transfer_openloop.setData( freq_axis_openloop, conversion_factor * (np.abs(H_measured_openloop))) self.curve_transfer_closedloop_predicted.setData( freq_axis_openloop, conversion_factor * (np.abs(H_predicted_fll))) if len(freq_axis_fll) > 2: self.curve_transfer_closedloop.setData( freq_axis_fll, conversion_factor * (np.abs(H_measured_fll))) # if len(H_closedloop) > 2: # self.curve_transfer_gainwithcontroller.setData(freq_axis, np.abs(H_closedloop) * conversion_factor) # else: # self.curve_transfer_gainwithcontroller.setData(freq_axis, magnitude * conversion_factor) self.qplt_transfer.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.qplt_transfer.setAxisTitle(Qwt.QwtPlot.yLeft, 'Gain [Hz/fullscale]') elif self.qcombo_transfer_units.currentIndex() == 2: # Hz/V, assumes 1V fullscale DAC output (which might be incorrect depending on which DAC and the output PGA gain setting) # 2**10 is the number of fractional bits on the phase, while 2**16 is the fullscale output range in counts # The 1 at the end represents 1V/fullscale conversion_factor = self.sl.fs / 2**10 * 2**16 * 1 if len(freq_axis_openloop) > 2: self.curve_transfer_openloop.setData( freq_axis_openloop, conversion_factor * (np.abs(H_measured_openloop))) self.curve_transfer_closedloop_predicted.setData( freq_axis_openloop, conversion_factor * (np.abs(H_predicted_fll))) if len(freq_axis_fll) > 2: self.curve_transfer_closedloop.setData( freq_axis_fll, conversion_factor * (np.abs(H_measured_fll))) # if len(H_closedloop) > 2: # self.curve_transfer_gainwithcontroller.setData(freq_axis, np.abs(H_closedloop) * conversion_factor) # else: # self.curve_transfer_gainwithcontroller.setData(freq_axis, magnitude * conversion_factor) self.qplt_transfer.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.qplt_transfer.setAxisTitle(Qwt.QwtPlot.yLeft, 'Gain [Hz/V]') # The phase is unaffected by the units, it is always in radians: self.curve_transfer_phase.setData(freq_axis_openloop, np.angle(H_measured_openloop)) # Refresh the display: self.qplt_transfer.replot() self.qplt_openloop.replot() return
def updateGraph(self): if self.qcombo_units.currentIndex() == 0: bGraphIndBs = True else: bGraphIndBs = False # System sign: if self.qradio_signp.isChecked(): sign = 1 else: sign = -1 # add looping over many curves... print "updateGraph: %d curves in list." % (len(self.curve_mag_list)) for kCurve in range(len(self.curve_mag_list)): print "updateGraph: curve %d of %d." % (kCurve, len(self.curve_mag_list)) self.curve_phase_list[kCurve].setData( self.frequency_axis_list[kCurve], np.angle(sign * (self.transfer_function_list[kCurve])) ) # phase graph is usually just the phase of the transfer function, except for a few scalings if bGraphIndBs == True: self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], 20 * np.log10(np.abs(self.transfer_function_list[kCurve]))) self.qplt_mag.setAxisTitle( Qwt.QwtPlot.yLeft, 'dB[(%s)^2]' % self.vertical_units_list[kCurve]) self.qplt_mag.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) else: if self.qcombo_units.currentIndex() == 2: # Linear real part self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], (np.real(self.transfer_function_list[kCurve]))) self.qplt_mag.setAxisTitle( Qwt.QwtPlot.yLeft, '%s' % self.vertical_units_list[kCurve]) self.qplt_mag.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) elif self.qcombo_units.currentIndex() == 3: # Linear imag part self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], (np.imag(self.transfer_function_list[kCurve]))) self.qplt_mag.setAxisTitle( Qwt.QwtPlot.yLeft, '%s' % self.vertical_units_list[kCurve]) self.qplt_mag.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) elif self.qcombo_units.currentIndex() == 1: # linear magnitude and phase self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], (np.abs(self.transfer_function_list[kCurve]))) self.qplt_mag.setAxisTitle( Qwt.QwtPlot.yLeft, '%s' % self.vertical_units_list[kCurve]) self.qplt_mag.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) elif self.qcombo_units.currentIndex() == 4: # 'Ohms, 50*Vin/Vout' Zsource = 50 test_impedance = (Zsource / (self.transfer_function_list[kCurve])) self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], np.abs(test_impedance)) self.qplt_mag.setAxisTitle(Qwt.QwtPlot.yLeft, 'Ohms') self.qplt_mag.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.curve_phase_list[kCurve].setData( self.frequency_axis_list[kCurve], np.angle(-sign * (test_impedance))) elif self.qcombo_units.currentIndex() == 5: # 'Ohms, shunt DUT']) Zsource = 50. Zinput = 50. load_impedance = ( Zsource * (self.transfer_function_list[kCurve] / (1 - self.transfer_function_list[kCurve]))) # load impedance consists of the impedance that we want to measure in parallel with 50 ohms so we need to invert this too load_admittance = 1 / load_impedance unknown_admittance = load_admittance - 1 / Zinput unknown_impedance = 1 / unknown_admittance print load_admittance[0] print load_impedance[0] print unknown_admittance[0] print unknown_impedance[0] self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], np.abs(unknown_impedance)) self.qplt_mag.setAxisTitle(Qwt.QwtPlot.yLeft, 'Ohms') self.qplt_mag.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.curve_phase_list[kCurve].setData( self.frequency_axis_list[kCurve], np.angle(sign * (unknown_impedance))) print kCurve print len(self.curve_mag_list) - 1 if kCurve == len(self.curve_mag_list) - 1: strNotes = '' for kFreq in range( len(self.frequency_axis_list[kCurve])): strNotes += '%.2e Hz: Z = %.2e + j*%.2e\n' % ( self.frequency_axis_list[kCurve][kFreq], np.real(unknown_impedance[kFreq]), np.imag(unknown_impedance[kFreq])) self.qedit_comment.setText(strNotes) print strNotes elif self.qcombo_units.currentIndex() == 6: # 'Ohms, Shunt DUT, high-Z probe + Series source impedance' try: Zsource = float(self.qedit_SeriesImpedance.text()) except: Zsource = 100e3 + 50. pass # load_impedance = (Zsource*(10.*self.transfer_function_list[kCurve]/(1-10.*self.transfer_function_list[kCurve]))) load_impedance = ( -Zsource * (10. * self.transfer_function_list[kCurve] / (10. * self.transfer_function_list[kCurve] - 1.))) self.curve_mag_list[kCurve].setData( self.frequency_axis_list[kCurve], np.abs(load_impedance)) self.qplt_mag.setAxisTitle(Qwt.QwtPlot.yLeft, 'Ohms') self.qplt_mag.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLog10ScaleEngine()) self.curve_phase_list[kCurve].setData( self.frequency_axis_list[kCurve], np.angle(sign * (load_impedance))) if kCurve == len(self.curve_mag_list) - 1: strNotes = '' for kFreq in range( len(self.frequency_axis_list[kCurve])): strNotes += '%.2e Hz: Z = %.2e + j*%.2e\n' % ( self.frequency_axis_list[kCurve][kFreq], np.real(load_impedance[kFreq]), np.imag(load_impedance[kFreq])) self.qedit_comment.setText(strNotes) print "update curve complete." self.qplt_phase.setAxisTitle(Qwt.QwtPlot.yLeft, 'Phase [rad]') self.qplt_mag.replot() self.qplt_phase.replot()
def __init__(self, parent=None, logger=None): super(GLPlotWidget, self).__init__() self.glWidget = GLWidget(self) self.xmin = 0.1 self.xmax = 1. self.ymin = 0.1 self.ymax = 1. self.peaks_enabled = True self.peak = zeros((3, )) self.peak_int = zeros((3, )) self.peak_decay = ones((3, )) * PEAK_DECAY_RATE self.x1 = array([0.1, 0.5, 1.]) self.x2 = array([0.5, 1., 2.]) self.y = array([0., 0., 0.]) self.fmax = 1e3 self.transformed_x1 = self.x1 self.transformed_x2 = self.x2 self.baseline_transformed = False self.baseline = 0. self.topDist = 0 self.bottomDist = 0 self.leftDist = 0 self.rightDist = 0 self.needtransform = False self.verticalScaleEngine = Qwt.QwtLinearScaleEngine() self.verticalScale = Qwt.QwtScaleWidget(self) vtitle = Qwt.QwtText("PSD (dB)") vtitle.setFont(QtGui.QFont(8)) self.verticalScale.setTitle(vtitle) self.verticalScale.setScaleDiv( self.verticalScaleEngine.transformation(), self.verticalScaleEngine.divideScale(self.ymin, self.ymax, 8, 5)) self.verticalScale.setMargin(2) self.logx = False self.horizontalScaleEngine = Qwt.QwtLinearScaleEngine() self.horizontalScale = Qwt.QwtScaleWidget(self) htitle = Qwt.QwtText("Frequency (Hz)") htitle.setFont(QtGui.QFont(8)) self.horizontalScale.setTitle(htitle) self.horizontalScale.setScaleDiv( self.horizontalScaleEngine.transformation(), self.horizontalScaleEngine.divideScale(self.xmin, self.xmax, 8, 5)) self.horizontalScale.setAlignment(Qwt.QwtScaleDraw.BottomScale) self.horizontalScale.setMargin(2) self.horizontalScale.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) plotLayout = QtGui.QGridLayout() plotLayout.setSpacing(0) plotLayout.setContentsMargins(0, 0, 0, 0) plotLayout.addWidget(self.verticalScale, 0, 0) plotLayout.addWidget(self.glWidget, 0, 1) plotLayout.addWidget(self.horizontalScale, 1, 1) self.setLayout(plotLayout)
def displayFreqCounter(self): # (freq_counter_samples, time_axis, DAC0_output, DAC1_output, DAC2_output) = self.sl.read_zero_deadtime_freq_counter(self.output_number) try: (freq_counter_samples, time_axis, DAC0_output, DAC1_output, DAC2_output) = self.sl.read_dual_mode_counter(self.output_number) # print (freq_counter_samples, time_axis, DAC0_output, DAC1_output, DAC2_output) except: print( 'Exception occured reading counter data. disabling further updates.' ) self.killTimer(self.timerID) freq_counter_samples = 0 time_axis = 0 DAC0_output = 0 DAC1_output = 0 DAC2_output = 0 raise try: if time_axis is not None: # scale to seconds: time_axis = time_axis.astype(float) * self.gate_time # Write data to disk: self.file_output_time.write(time_axis) if DAC0_output is not None: # Scale to minimum and maximum limits: 0 means minimum, 1 means maximum DAC0_output = (DAC0_output - self.sl.DACs_limit_low[0]).astype( np.float) / float(self.sl.DACs_limit_high[0] - self.sl.DACs_limit_low[0]) # Write data to disk: self.file_output_dac0.write(DAC0_output) if DAC1_output is not None: # Scale to minimum and maximum limits: 0 means minimum, 1 means maximum DAC1_output = (DAC1_output - self.sl.DACs_limit_low[1]).astype( np.float) / float(self.sl.DACs_limit_high[1] - self.sl.DACs_limit_low[1]) # Write data to disk: self.file_output_dac1.write(DAC1_output) if DAC2_output is not None: # Scale to minimum and maximum limits: 0 means minimum, 1 means maximum DAC2_output = (DAC2_output - self.sl.DACs_limit_low[2]).astype( np.float) / float(self.sl.DACs_limit_high[2] - self.sl.DACs_limit_low[2]) # Write data to disk: self.file_output_dac2.write(DAC2_output) self.runTempControlLoop(time.clock(), DAC2_output[-1:]) if freq_counter_samples is not None: if self.bVeryFirst == True: # We flush the first two samples because the system isn't fully initialized and they always force the plot scale too wide freq_counter_samples = freq_counter_samples[2:] if self.output_number == 0 and (DAC0_output is not None): DAC0_output = DAC0_output[2:] if self.output_number == 1 and (DAC1_output is not None): DAC1_output = DAC1_output[2:] DAC2_output = DAC2_output[2:] self.bVeryFirst = False return self.runFreqControlLoop(time.clock(), freq_counter_samples[-1:]) # Write data to disk: if self.output_number == 0: self.file_output_counter0.write(freq_counter_samples) elif self.output_number == 1: self.file_output_counter1.write(freq_counter_samples) # Record the new chunk of data in the buffer: # print('len = %d' % len(freq_counter_samples)) self.freq_history[:-len(freq_counter_samples )] = self.freq_history[ len(freq_counter_samples):] self.freq_history[-len(freq_counter_samples ):] = freq_counter_samples if self.output_number == 0: self.DAC0_history[:-len(DAC0_output)] = self.DAC0_history[ len(DAC0_output):] self.DAC0_history[-len(DAC0_output):] = DAC0_output self.bValid_dacs[:-len(DAC0_output)] = self.bValid_dacs[ len(DAC0_output):] self.bValid_dacs[-len(DAC0_output):] = True if self.output_number == 1: self.DAC1_history[:-len(DAC1_output)] = self.DAC1_history[ len(DAC1_output):] self.DAC1_history[-len(DAC1_output):] = DAC1_output self.DAC2_history[:-len(DAC1_output)] = self.DAC2_history[ len(DAC1_output):] self.DAC2_history[-len(DAC1_output):] = DAC2_output self.bValid_dacs[:-len(DAC1_output)] = self.bValid_dacs[ len(DAC1_output):] self.bValid_dacs[-len(DAC1_output):] = True # self.time_history[:-len(freq_counter_samples)] = self.time_history[len(freq_counter_samples):] # self.time_history[-len(freq_counter_samples):] = time_axis self.bValid_counters[:-len(freq_counter_samples )] = self.bValid_counters[ len(freq_counter_samples):] self.bValid_counters[-len(freq_counter_samples):] = True channelName = '' if self.output_number == 0: channelName = 'CEO' if self.output_number == 1: channelName = 'Optical' # Update graph: self.curve_freq_error.setData( self.time_history_counters[self.bValid_counters] - self.time_history_counters[len(self.time_history_counters) - 1], self.freq_history[self.bValid_counters]) self.qplt_freq.setTitle( '%s Lock Freq error, mean = %.6f Hz, std = %.3f mHz' % (channelName, np.mean(self.freq_history[self.bValid_counters]), 1e3 * np.std(self.freq_history[self.bValid_counters]))) if self.qchk_fullscale_freq.isChecked(): self.qplt_freq.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) try: ymin = float(self.qedit_ymin.text()) ymax = float(self.qedit_ymax.text()) except: ymin = -25e6 ymax = 25e6 self.qplt_freq.setAxisScale(Qwt.QwtPlot.yLeft, ymin, ymax) else: self.qplt_freq.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.qplt_freq.replot() # Update graph: if self.output_number == 0: self.curve_dac0.setData( self.time_history_dacs[self.bValid_dacs] - self.time_history_dacs[len(self.time_history_dacs) - 1], self.DAC0_history[self.bValid_dacs]) self.qplt_dac.setTitle( '%s Lock DAC outputs, last raw code = %f' % (channelName, self.DAC0_history[-1])) if self.output_number == 1: self.curve_dac1.setData( self.time_history_dacs[self.bValid_dacs] - self.time_history_dacs[len(self.time_history_dacs) - 1], self.DAC1_history[self.bValid_dacs]) self.curve_dac2.setData( self.time_history_dacs[self.bValid_dacs] - self.time_history_dacs[len(self.time_history_dacs) - 1], self.DAC2_history[self.bValid_dacs]) self.qplt_dac.setTitle( '%s Lock DAC outputs, last raw codes = %f, %f' % (channelName, self.DAC1_history[-1], self.DAC2_history[-1])) if self.qchk_fullscale_dac.isChecked(): self.qplt_dac.setAxisScaleEngine( Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.qplt_dac.setAxisScale(Qwt.QwtPlot.yLeft, 0, 1) else: self.qplt_dac.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.qplt_dac.replot() except: print( 'Exception occured parsing counter data. disabling further updates.' ) self.killTimer(self.timerID) freq_counter_samples = 0 time_axis = 0 DAC0_output = 0 DAC1_output = 0 DAC2_output = 0 raise
def __init__(self, module, *args): ''' Constructor @param module: parent module ''' apply(Qt.QDialog.__init__, (self, ) + args) self.setupUi(self) self.module = module self.params = None # last received parameter block self.data = None # last received data block # create table view grid (10x16 eeg electrodes + 1 row for ground electrode) cc = 10 rc = 16 self.tableWidgetValues.setColumnCount(cc) self.tableWidgetValues.setRowCount(rc + 1) self.tableWidgetValues.horizontalHeader().setResizeMode( Qt.QHeaderView.Stretch) self.tableWidgetValues.horizontalHeader().setDefaultAlignment( Qt.Qt.Alignment(Qt.Qt.AlignCenter)) self.tableWidgetValues.verticalHeader().setResizeMode( Qt.QHeaderView.Stretch) self.tableWidgetValues.verticalHeader().setDefaultAlignment( Qt.Qt.Alignment(Qt.Qt.AlignCenter)) # add ground electrode row self.tableWidgetValues.setSpan(rc, 0, 1, cc) # row headers rheader = Qt.QStringList() for r in xrange(rc): rheader.append("%d - %d" % (r * cc + 1, r * cc + cc)) rheader.append("GND") self.tableWidgetValues.setVerticalHeaderLabels(rheader) # create cell items fnt = Qt.QFont() fnt.setPointSize(8) for r in xrange(rc): for c in xrange(cc): item = Qt.QTableWidgetItem() item.setTextAlignment(Qt.Qt.AlignCenter) item.setFont(fnt) self.tableWidgetValues.setItem(r, c, item) # GND electrode cell item = Qt.QTableWidgetItem() item.setTextAlignment(Qt.Qt.AlignCenter) item.setFont(fnt) item.setText("GND") self.tableWidgetValues.setItem(rc, 0, item) self.defaultColor = item.backgroundColor() # set range list self.comboBoxRange.clear() self.comboBoxRange.addItem("15") self.comboBoxRange.addItem("50") self.comboBoxRange.addItem("100") self.comboBoxRange.addItem("500") # set validators validator = Qt.QIntValidator(self) validator.setBottom(15) validator.setTop(500) self.comboBoxRange.setValidator(validator) self.comboBoxRange.setEditText(str(self.module.range_max)) # setup color scale self.linearscale = False self.scale_engine = Qwt.QwtLinearScaleEngine() self.scale_interval = Qwt.QwtDoubleInterval(0, self.module.range_max) self.scale_map = Qwt.QwtLinearColorMap(Qt.Qt.green, Qt.Qt.red) if self.linearscale: self.scale_map.addColorStop(0.45, Qt.Qt.yellow) self.scale_map.addColorStop(0.55, Qt.Qt.yellow) self.scale_map.setMode(Qwt.QwtLinearColorMap.ScaledColors) else: self.scale_map.addColorStop(0.33, Qt.Qt.yellow) self.scale_map.addColorStop(0.66, Qt.Qt.red) self.scale_map.setMode(Qwt.QwtLinearColorMap.FixedColors) self.ScaleWidget.setColorMap(self.scale_interval, self.scale_map) self.ScaleWidget.setColorBarEnabled(True) self.ScaleWidget.setColorBarWidth(30) self.ScaleWidget.setBorderDist(10, 10) # set default values self.setColorRange(0, self.module.range_max) self.checkBoxValues.setChecked(self.module.show_values) # actions self.connect(self.comboBoxRange, Qt.SIGNAL("editTextChanged(QString)"), self._rangeChanged) self.connect(self.checkBoxValues, Qt.SIGNAL("stateChanged(int)"), self._showvalues_changed) self.connect(self.module, Qt.SIGNAL('update(PyQt_PyObject)'), self._updateValues)
def displayFreqCounter(self): (freq_counter_samples, time_axis, DAC0_output, DAC1_output, DAC2_output) = self.sl.read_zero_deadtime_freq_counter( self.output_number) if type(time_axis) != type(0): # scale to seconds: time_axis = time_axis.astype(float) * self.gate_time # Write data to disk: self.file_output_time.write(time_axis) if type(DAC0_output) != type(0): # Scale to minimum and maximum limits: 0 means minimum, 1 means maximum DAC0_output = (DAC0_output - self.sl.DACs_limit_low[0]).astype( np.float) / float(self.sl.DACs_limit_high[0] - self.sl.DACs_limit_low[0]) # Write data to disk: self.file_output_dac0.write(DAC0_output) if type(DAC1_output) != type(0): # Scale to minimum and maximum limits: 0 means minimum, 1 means maximum DAC1_output = (DAC1_output - self.sl.DACs_limit_low[1]).astype( np.float) / float(self.sl.DACs_limit_high[1] - self.sl.DACs_limit_low[1]) # Write data to disk: self.file_output_dac1.write(DAC1_output) if type(DAC2_output) != type(0): # Scale to minimum and maximum limits: 0 means minimum, 1 means maximum DAC2_output = (DAC2_output - self.sl.DACs_limit_low[2]).astype( np.float) / float(self.sl.DACs_limit_high[2] - self.sl.DACs_limit_low[2]) # Write data to disk: self.file_output_dac2.write(DAC2_output) self.runTempControlLoop(time.clock(), DAC2_output[-1:]) if type(freq_counter_samples) != type(0): if self.bVeryFirst == True: # We flush the first two samples because the system isn't fully initialized and they always force the plot scale too wide freq_counter_samples = freq_counter_samples[2:] if self.output_number == 0: DAC0_output = DAC0_output[2:] if self.output_number == 1: DAC1_output = DAC1_output[2:] DAC2_output = DAC2_output[2:] self.bVeryFirst = False # Write data to disk: if self.output_number == 0: self.file_output_counter0.write(freq_counter_samples) elif self.output_number == 1: self.file_output_counter1.write(freq_counter_samples) # Record the new chunk of data in the buffer: self.freq_history[:-len(freq_counter_samples)] = self.freq_history[ len(freq_counter_samples):] self.freq_history[-len(freq_counter_samples ):] = freq_counter_samples if self.output_number == 0: self.DAC0_history[:-len(freq_counter_samples )] = self.DAC0_history[ len(freq_counter_samples):] self.DAC0_history[-len(freq_counter_samples):] = DAC0_output if self.output_number == 1: self.DAC1_history[:-len(freq_counter_samples )] = self.DAC1_history[ len(freq_counter_samples):] self.DAC1_history[-len(freq_counter_samples):] = DAC1_output self.DAC2_history[:-len(freq_counter_samples )] = self.DAC2_history[ len(freq_counter_samples):] self.DAC2_history[-len(freq_counter_samples):] = DAC2_output # self.time_history[:-len(freq_counter_samples)] = self.time_history[len(freq_counter_samples):] # self.time_history[-len(freq_counter_samples):] = time_axis self.bValid[:-len(freq_counter_samples )] = self.bValid[len(freq_counter_samples):] self.bValid[-len(freq_counter_samples):] = True # Update graph: self.curve_freq_error.setData( self.time_history[self.bValid] - self.time_history[len(self.time_history) - 1], self.freq_history[self.bValid]) self.qplt_freq.setTitle( 'Lock #%d Frequency error, mean = %f Hz, std = %.3f Hz' % (self.output_number, np.mean(self.freq_history[self.bValid]), np.std(self.freq_history[self.bValid]))) if self.qchk_fullscale_freq.isChecked(): self.qplt_freq.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.qplt_freq.setAxisScale(Qwt.QwtPlot.yLeft, -5e6, 5e6) else: self.qplt_freq.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.qplt_freq.replot() # Update graph: if self.output_number == 0: self.curve_dac0.setData( self.time_history[self.bValid] - self.time_history[len(self.time_history) - 1], self.DAC0_history[self.bValid]) self.qplt_dac.setTitle( 'Lock #%d DAC outputs, last raw code = %f' % (self.output_number, self.DAC0_history[-1])) if self.output_number == 1: self.curve_dac1.setData( self.time_history[self.bValid] - self.time_history[len(self.time_history) - 1], self.DAC1_history[self.bValid]) self.curve_dac2.setData( self.time_history[self.bValid] - self.time_history[len(self.time_history) - 1], self.DAC2_history[self.bValid]) self.qplt_dac.setTitle( 'Lock #%d DAC outputs, last raw codes = %f, %f' % (self.output_number, self.DAC1_history[-1], self.DAC2_history[-1])) if self.qchk_fullscale_dac.isChecked(): self.qplt_dac.setAxisScaleEngine(Qwt.QwtPlot.yLeft, Qwt.QwtLinearScaleEngine()) self.qplt_dac.setAxisScale(Qwt.QwtPlot.yLeft, 0, 1) else: self.qplt_dac.setAxisAutoScale(Qwt.QwtPlot.yLeft) self.qplt_dac.replot()
def plotSelection(self): if not self.measurementIsSelected() or not self.parameterIsSelected(): return # Clear already plotted Curves self.qwtPlot.detachItems() data = self.selectedParameterData() frequencies = self.currentProject().fft_frequencies() if self.useFrequencyRangeLimits: # We cast to float64 - equality on python-floats is a very risky thing lowerDisplayedFrequency = np.float64(self.dsbLowerDisplayedFrequency.value()) upperDisplayedFrequency = np.float64(self.dsbUpperDisplayedFrequency.value()) fftRes = self.currentProject().fft_resolution start_index = np.where(np.isclose(frequencies, lowerDisplayedFrequency))[0][0] stop_index = np.where(np.isclose(frequencies, upperDisplayedFrequency))[0][0] + 1 data = data[start_index:stop_index] frequencies = frequencies[start_index:stop_index] # Set Y Axis Title self.qwtPlot.setAxisTitle(Qwt5.QwtPlot.yLeft, self.selectedParameterName()) if self.graphConfig.showReal: curve = Qwt5.QwtPlotCurve('Realteil') curve.setData(frequencies, data.real) curve.setPen(QtGui.QPen(QtCore.Qt.red)) curve.setRenderHint(Qwt5.QwtPlotItem.RenderAntialiased) curve.attach(self.qwtPlot) if self.graphConfig.showImag: curve = Qwt5.QwtPlotCurve('Imaginaerteil') curve.setData(frequencies, data.imag) curve.setPen(QtGui.QPen(QtCore.Qt.yellow)) curve.setRenderHint(Qwt5.QwtPlotItem.RenderAntialiased) curve.attach(self.qwtPlot) if self.graphConfig.showAbs: curve = Qwt5.QwtPlotCurve('Betrag') curve.setData(frequencies, np.abs(data)) curve.setPen(QtGui.QPen(QtCore.Qt.blue)) curve.setRenderHint(Qwt5.QwtPlotItem.RenderAntialiased) curve.attach(self.qwtPlot) if self.graphConfig.showPhase: curve = Qwt5.QwtPlotCurve('Phase') if self.graphConfig.unwrapPhase: curve.setData(frequencies, np.unwrap(np.angle(data), self.graphConfig.unwrapDiscont)) else: curve.setData(frequencies, np.angle(data)) curve.setPen(QtGui.QPen(QtCore.Qt.green)) curve.setRenderHint(Qwt5.QwtPlotItem.RenderAntialiased) curve.attach(self.qwtPlot) # Build Legend legend = Qwt5.QwtLegend() legend.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken) self.qwtPlot.insertLegend(legend, Qwt5.QwtPlot.RightLegend) # Set Axis Scaling if self.graphConfig.xAxisLinear: self.qwtPlot.setAxisScaleEngine(Qwt5.QwtPlot.xBottom, Qwt5.QwtLinearScaleEngine()) else: self.qwtPlot.setAxisScaleEngine(Qwt5.QwtPlot.xBottom, Qwt5.QwtLog10ScaleEngine()) if self.graphConfig.yAxisLinear: self.qwtPlot.setAxisScaleEngine(Qwt5.QwtPlot.yLeft, Qwt5.QwtLinearScaleEngine()) else: self.qwtPlot.setAxisScaleEngine(Qwt5.QwtPlot.yLeft, Qwt5.QwtLog10ScaleEngine()) # See this: http://stackoverflow.com/questions/14685010/qwt-plot-auto-scale-not-working self.qwtPlot.axisScaleEngine(Qwt5.QwtPlot.xBottom).setAttribute(Qwt5.QwtScaleEngine.Floating, True) self.qwtPlot.axisScaleEngine(Qwt5.QwtPlot.yLeft).setAttribute(Qwt5.QwtScaleEngine.Floating, True) self.qwtPlot.replot()