|
| 1 | +classdef phaseMonitor < handle |
| 2 | + % Plot the relative phase of two AO tasks on different boards |
| 3 | + % |
| 4 | + % vidrio.sync.phaseMonitor |
| 5 | + % |
| 6 | + % |
| 7 | + % Hook up AO0 of DAQ_a to AI0 of DAQ_a and AO0 of DAQ_b to AI1 of DAQ_a |
| 8 | + % Then run, e.g. vidrio.sync.phaseMonitor('DAQ_a','DAQ_b'; |
| 9 | + % The input args are the device IDs. First is the one with the AI connections. |
| 10 | + % |
| 11 | + % Also see: |
| 12 | + % vidrio.sync.sine_AO_AI, vidrio.mixed.AOandAI, vidrio.mixed.AOandAI_OO, |
| 13 | + |
| 14 | + |
| 15 | + properties |
| 16 | + taskA |
| 17 | + taskB |
| 18 | + end %close properties block |
| 19 | + |
| 20 | + properties (Hidden) |
| 21 | + listeners |
| 22 | + |
| 23 | + % These properties hold information relevant to the plot window |
| 24 | + hFig %The handle to the figure which shows the data is stored here |
| 25 | + axis_A %Handles for the two axes |
| 26 | + axis_B |
| 27 | + axis_C |
| 28 | + |
| 29 | + lastDataHandle_A |
| 30 | + lastDataHandle_B |
| 31 | + lastDataHandle_BA %Copy of _A |
| 32 | + lastDataHandle_C |
| 33 | + |
| 34 | + histData_B |
| 35 | + histDataHandle_B |
| 36 | + histData_C |
| 37 | + histDataHandle_C |
| 38 | + |
| 39 | + minPointsToPlot % We trigger the waveform at the upward 0 V crossing so it looks consistent and we plot at least this many points |
| 40 | + end |
| 41 | + |
| 42 | + |
| 43 | + methods |
| 44 | + |
| 45 | + function obj=phaseMonitor(DAQ_ID_A, DAQ_ID_B) |
| 46 | + |
| 47 | + % Connect to DAQ |
| 48 | + obj.taskA=vidrio.sync.sine_AO_AI(DAQ_ID_A); |
| 49 | + obj.taskB=vidrio.sync.sine_AO_AI(DAQ_ID_B); |
| 50 | + |
| 51 | + |
| 52 | + obj.hFig = clf; |
| 53 | + obj.hFig.Position(3)=obj.hFig.Position(3)*1.5; %Make figure a little wider |
| 54 | + obj.hFig.Name='Close figure to stop acquisition'; %This is just the OO notation. We could also use the set command. |
| 55 | + obj.hFig.CloseRequestFcn = @obj.windowCloseFcn; |
| 56 | + |
| 57 | + |
| 58 | + %Make two empty axes which we fill in the method readAndPlotData |
| 59 | + obj.axis_A = axes('Parent', obj.hFig, 'Position', [0.1 0.12 0.4 0.4]); |
| 60 | + obj.axis_B = axes('Parent', obj.hFig, 'Position', [0.1 0.55 0.4 0.4]); |
| 61 | + obj.axis_C = axes('Parent', obj.hFig, 'Position', [0.55 0.12 0.4 0.8]); |
| 62 | + set([obj.axis_B,obj.axis_C],'NextPlot','add') |
| 63 | + |
| 64 | + % Plot some empty data which we will later modify in readAndPlotData |
| 65 | + % in the first two plots we show the two waveforms as a function of time |
| 66 | + obj.minPointsToPlot = round((obj.taskA.sampleRate*obj.taskA.updatePeriod)/3); |
| 67 | + obj.lastDataHandle_A = plot(obj.axis_A, zeros(obj.minPointsToPlot,1), '-','color', [1,0.4,0.4],'linewidth',2); |
| 68 | + obj.histData_B = nan(obj.minPointsToPlot,1); |
| 69 | + obj.histDataHandle_B = plot(obj.axis_B, obj.histData_B, '-'); |
| 70 | + obj.lastDataHandle_B = plot(obj.axis_B, zeros(obj.minPointsToPlot,1), '-k','linewidth',2); |
| 71 | + obj.lastDataHandle_BA = plot(obj.axis_B, zeros(obj.minPointsToPlot,1), '-','color', [1,0.75,0.75],'linewidth',3); |
| 72 | + |
| 73 | + |
| 74 | + % In the third plot we will show AI 1 as a function of AI 0 |
| 75 | + obj.lastDataHandle_C = plot(obj.axis_C, zeros(round(obj.taskA.sampleRate*obj.taskA.updatePeriod),1),'-k','linewidth',2); |
| 76 | + obj.histData_C = nan(obj.minPointsToPlot,1,2); |
| 77 | + obj.histDataHandle_C = plot(obj.axis_C, obj.histData_C(:,:,1), obj.histData_C(:,:,2), '-'); |
| 78 | + |
| 79 | + %Make plots look nice |
| 80 | + obj.axis_A.YLabel.String=[obj.taskA.DAQdevice, ' Voltage (V)']; |
| 81 | + obj.axis_A.XLabel.String='Samples'; |
| 82 | + |
| 83 | + obj.axis_B.YLabel.String=[obj.taskB.DAQdevice, ' Voltage (V)']; |
| 84 | + obj.axis_B.XLabel.String=''; |
| 85 | + obj.axis_B.XTickLabel=[]; |
| 86 | + |
| 87 | + obj.axis_C.XLabel.String=[obj.taskA.DAQdevice, ' Voltage (V)']; |
| 88 | + obj.axis_C.YLabel.String=[obj.taskB.DAQdevice, ' Voltage (V)']; |
| 89 | + |
| 90 | + % Set properties of axes together |
| 91 | + set([obj.axis_A,obj.axis_B,obj.axis_C], 'Box', 'On', 'XGrid', 'On', 'YGrid', 'On', 'YLim', [obj.taskA.minVoltage,obj.taskA.maxVoltage], 'XLim',[0,obj.minPointsToPlot]) |
| 92 | + |
| 93 | + addlistener(obj.taskA,'acquiredData', 'PostSet', @(src,eventData) obj.plotIt(src,eventData) ); |
| 94 | + |
| 95 | + |
| 96 | + obj.taskA.startAcquisition; |
| 97 | + obj.taskB.startAcquisition; |
| 98 | + |
| 99 | + end % close constructor |
| 100 | + |
| 101 | + |
| 102 | + function delete(obj) |
| 103 | + delete(obj.taskA) |
| 104 | + delete(obj.taskB) |
| 105 | + delete(obj.hFig) |
| 106 | + end %close destructor |
| 107 | + |
| 108 | + |
| 109 | + function plotIt(obj,src,eventData) |
| 110 | + |
| 111 | + AIdata=eventData.AffectedObject.acquiredData; %Get the data |
| 112 | + |
| 113 | + %lock to the first upward 0 V crossing |
| 114 | + tmp=smooth(AIdata(:,1)); |
| 115 | + tmp=round(tmp,2); |
| 116 | + f=find(tmp(1:end-1,1)==0 & diff(tmp(:,1))>0 ); |
| 117 | + if isempty(f) |
| 118 | + return |
| 119 | + end |
| 120 | + |
| 121 | + AIdata(1:f(1),:)=[]; |
| 122 | + if length(AIdata)<obj.minPointsToPlot |
| 123 | + %Do not proceed if not enough points are available to plot |
| 124 | + return |
| 125 | + end |
| 126 | + |
| 127 | + %We keep the plot objects the same and just change their data properties |
| 128 | + obj.lastDataHandle_A.YData=AIdata(:,1); |
| 129 | + |
| 130 | + |
| 131 | + |
| 132 | + obj.histData_B(:,end+1)=AIdata(1:obj.minPointsToPlot,2); |
| 133 | + obj.axis_B.ColorOrder=flipud(gray(size(obj.histData_B,2))) ; |
| 134 | + delete(obj.histDataHandle_B) |
| 135 | + obj.histDataHandle_B=plot(obj.axis_B,obj.histData_B,'linewidth',1.5); |
| 136 | + |
| 137 | + obj.lastDataHandle_B.YData=AIdata(:,2); |
| 138 | + uistack(obj.lastDataHandle_B,'top') |
| 139 | + obj.lastDataHandle_BA.YData = AIdata(:,1); |
| 140 | + |
| 141 | + |
| 142 | + obj.lastDataHandle_C.XData=AIdata(:,1); |
| 143 | + obj.lastDataHandle_C.YData=AIdata(:,2); |
| 144 | + |
| 145 | + |
| 146 | + obj.histData_C(:,end+1,1)=AIdata(1:obj.minPointsToPlot,1); |
| 147 | + obj.histData_C(:,end, 2)=AIdata(1:obj.minPointsToPlot,2); |
| 148 | + |
| 149 | + obj.axis_C.ColorOrder=flipud(gray(size(obj.histData_B,2))) ; |
| 150 | + delete(obj.histDataHandle_C) |
| 151 | + obj.histDataHandle_C=plot(obj.axis_C, obj.histData_C(:,:,1), obj.histData_C(:,:,2), 'linewidth',2); |
| 152 | + uistack(obj.lastDataHandle_C,'top') |
| 153 | + |
| 154 | + end %close plotIt |
| 155 | + |
| 156 | + |
| 157 | + function windowCloseFcn(obj,~,~) |
| 158 | + fprintf('You closed the window. Shutting down DAQ.\n') |
| 159 | + obj.delete % simply call the destructor |
| 160 | + end %close windowCloseFcn |
| 161 | + |
| 162 | + |
| 163 | + |
| 164 | + end %close methods block |
| 165 | + |
| 166 | +end %close the vidrio.mixed.AOandAI_OO class definition |
0 commit comments