Example 146: Scientific Graph showing Real Time with Local Data Circular Buffers

PesgoScientific Graph Objectadvanced

Real Time with Local Data Circular Buffers

Preview

ProEssentials Pesgo Scientific Graph Object - Scientific Graph showing Real Time with Local Data Circular Buffers
Click to enlarge

Source Code

Form3.cs
1Pesgo1.PeData.Subsets = 4;
2Pesgo1.PeData.Points = 2000000;
3
4// MouseWheelZooming shows frozen data, Example 145 MouseWheelZooming shows moving data
5
6// New v10 feature CircularBuffers // Only applies to Append type features.
7// Most beneficial with larger data sets and using AppendYData AppendXData
8// combined with ComputerShader construction with StagingBuffers.
9// CircularBuffers avoid having to shift existing data when appending.
10// ComputeShader rendering block copies data so there is no penalty in accessing data
11// to build the chart.
12Pesgo1.PeData.CircularBuffers = true;
13
14Pesgo1.PeData.DuplicateDataX = DuplicateData.PointIncrement;
15int nX = 1;
16for (int p = 0; p < 2000000; p++)
17{
18 MainWindow.MyXData146[p] = nX; // MyXData146 is app memory
19 nX++;
20}
21
22// quickly create 8 million random y data points, sin function is slow
23float[] MySubData0 = new float[8400];
24float[] MySubData1 = new float[8400];
25float[] MySubData2 = new float[8400];
26float[] MySubData3 = new float[8400];
27for (int p = 0; p < 8400; p++)
28{
29 MySubData0[p] = (float)(50 + (Math.Sin(p * 0.00075) * (0 + 1) * 30) + (Rand_Num.NextDouble() * 15));
30 MySubData1[p] = (float)(50 + (Math.Sin(p * 0.00075) * (1 + 1) * 30) + (Rand_Num.NextDouble() * 15));
31 MySubData2[p] = (float)(50 + (Math.Sin(p * 0.00075) * (2 + 1) * 30) + (Rand_Num.NextDouble() * 15));
32 MySubData3[p] = (float)(50 + (Math.Sin(p * 0.00075) * (3 + 1) * 30) + (Rand_Num.NextDouble() * 15));
33}
34
35// MyYData146 is app memory
36
37for (int j = 0; j < 1991600; j += 8400)
38 Array.Copy(MySubData0, 0, MainWindow.MyYData146, j, 8400);
39for (int j = 0; j < 1991600; j += 8400)
40 Array.Copy(MySubData1, 0, MainWindow.MyYData146, j + 2000000, 8400);
41for (int j = 0; j < 1991600; j += 8400)
42 Array.Copy(MySubData2, 0, MainWindow.MyYData146, j + 4000000, 8400);
43for (int j = 0; j < 1991600; j += 8400)
44 Array.Copy(MySubData3, 0, MainWindow.MyYData146, j + 6000000, 8400);
45
46// Provide local pointers to circular buffer data, data is not copied to chart // See example 145 that copies data to chart and circular buffer exists inside chart.
47Pesgo1.PeData.X.UseDataAtLocation(MainWindow.MyXData146, 2000000);
48Pesgo1.PeData.Y.UseDataAtLocation(MainWindow.MyYData146, 8000000);
49// compare speed of example 145 to 146. 146 is faster. Likely because it's not copying memory but using app local memory.
50
51// Set Manual Y scale // Avoiding cpu intensive searching for min max
52Pesgo1.PeGrid.Configure.ManualScaleControlY = ManualScaleControl.MinMax;
53Pesgo1.PeGrid.Configure.ManualMinY = -110;
54Pesgo1.PeGrid.Configure.ManualMaxY = 220;
55
56// Set Manual X scale // Avoiding cpu intensive searching for min max
57Pesgo1.PeGrid.Configure.ManualScaleControlX = ManualScaleControl.MinMax;
58Pesgo1.PeGrid.Configure.ManualMinX = 0;
59Pesgo1.PeGrid.Configure.ManualMaxX = 2000000;
60
61// Set Various Other Properties ///
62Pesgo1.PeColor.BitmapGradientMode = false;
63Pesgo1.PeColor.QuickStyle = QuickStyle.DarkNoBorder;
64
65// Set various properties //
66Pesgo1.PeString.MainTitle = "4 x 2 Million Real-Time Circular Buffer";
67Pesgo1.PeString.SubTitle = "";
68
69Pesgo1.PeConfigure.PrepareImages = true;
70Pesgo1.PeConfigure.CacheBmp = true;
71Pesgo1.PeFont.Fixed = true;
72
73Pesgo1.PeColor.SubsetColors[0] = Color.FromArgb(255, 255, 0, 0);
74Pesgo1.PeColor.SubsetColors[1] = Color.FromArgb(255, 0, 255, 0);
75Pesgo1.PeColor.SubsetColors[2] = Color.FromArgb(255, 255, 255, 0);
76Pesgo1.PeColor.SubsetColors[3] = Color.FromArgb(255, 0, 255, 255);
77
78Pesgo1.PeConfigure.TextShadows = TextShadows.BoldText;
79Pesgo1.PeFont.MainTitle.Bold = true;
80Pesgo1.PeFont.SubTitle.Bold = true;
81Pesgo1.PeFont.Label.Bold = true;
82Pesgo1.PeFont.SizeGlobalCntl = 1.4F;
83
84Pesgo1.PePlot.SubsetLineTypes[0] = LineType.ThinSolid;
85Pesgo1.PePlot.SubsetLineTypes[1] = LineType.ThinSolid;
86Pesgo1.PePlot.SubsetLineTypes[2] = LineType.ThinSolid;
87Pesgo1.PePlot.SubsetLineTypes[3] = LineType.ThinSolid;
88Pesgo1.PePlot.SubsetLineTypes[4] = LineType.ThinSolid;
89
90Pesgo1.PePlot.Method = SGraphPlottingMethod.Line;
91Pesgo1.PePlot.DataShadows = DataShadows.None;
92
93Pesgo1.PeGrid.Configure.AutoMinMaxPaddingX = 0;
94Pesgo1.PeConfigure.ImageAdjustLeft = 50;
95Pesgo1.PeConfigure.ImageAdjustRight = 0;
96
97Pesgo1.PeLegend.SimpleLine = true;
98Pesgo1.PeFont.FontSize = FontSize.Small;
99
100Pesgo1.PeUserInterface.Dialog.PlotCustomization = false;
101Pesgo1.PeUserInterface.Dialog.Page2 = false;
102Pesgo1.PeUserInterface.Allow.Popup = true;
103Pesgo1.PeUserInterface.Dialog.Axis = false;
104Pesgo1.PeUserInterface.Dialog.Subsets = true;
105Pesgo1.PeUserInterface.Allow.TextExport = false;
106Pesgo1.PeUserInterface.Dialog.AllowEmfExport = false;
107Pesgo1.PeUserInterface.Dialog.AllowWmfExport = false;
108
109Pesgo1.PeUserInterface.Menu.DataShadow = MenuControl.Hide;
110Pesgo1.PeUserInterface.Menu.MarkDataPoints = MenuControl.Hide;
111
112Pesgo1.PeConfigure.AntiAliasText = true;
113Pesgo1.PeConfigure.AntiAliasGraphics = true;
114
115// Allow MouseWheel Zooming //
116Pesgo1.PeUserInterface.Scrollbar.ScrollingHorzZoom = true;
117Pesgo1.PeUserInterface.Scrollbar.MouseWheelFunction = MouseWheelFunction.HorizontalZoom;
118
119Pesgo1.PeConfigure.RenderEngine = RenderEngine.Direct3D;
120
121Pesgo1.PeData.ComputeShader = true;
122Pesgo1.PeData.StagingBufferX = true;
123Pesgo1.PeData.StagingBufferY = true;
124Pesgo1.PeData.Filter2D3D = true;
125
126Pesgo1.PeSpecial.AutoImageReset = false;
127Pesgo1.PeUserInterface.Cursor.HourGlassThreshold = 99999999;
128
129Pesgo1.PeFunction.Force3dxVerticeRebuild = true;
130Pesgo1.PeFunction.ReinitializeResetImage();
131
132// Initialize Counters and Timer //
133MainWindow.m_nRealTimeCounter = 2000000;
134MainWindow.m_nSinCounter = 2000000;
135
136MainWindow.Timer1.Interval = 15;
137MainWindow.Timer1.Start();
138
139/*
140/////////////////////////
141// Example Timer Event //
142/////////////////////////
143private void Timer1_Tick(object sender, System.EventArgs e)
144{
145 int nNewSamplesPerSubsetsPerTick = 150;
146
147 // New y value and x value // Bock of memory subset0p0 subset0p1 subset0p2 subset0p3 subset0p4 subset1p0 subset1p0
148 for (int s = 0; s < 4; s++)
149 {
150 for (int p = 0; p < nNewSamplesPerSubsetsPerTick; p++)
151 {
152 pNewY145[(s * nNewSamplesPerSubsetsPerTick) + p] = (float)(50 + (Math.Sin((m_nSinCounter + p) * 0.00075) * (s + 1) * 30) + (Rand_Num.NextDouble() * 15));
153 }
154 }
155 for (int p = 0; p < nNewSamplesPerSubsetsPerTick; p++)
156 {
157 pNewX145[p] = m_nRealTimeCounter + p + 1;
158 }
159
160 // Append new values //
161 Pesgo1.PeData.Y.AppendData(pNewY145, nNewSamplesPerSubsetsPerTick);
162 Pesgo1.PeData.X.AppendData(pNewX145, nNewSamplesPerSubsetsPerTick);
163
164 // Increment counter ///
165 m_nRealTimeCounter = m_nRealTimeCounter + nNewSamplesPerSubsetsPerTick;
166
167 // We initialized chart with manual Scaling, so we need to manually control x axis range.
168 // For real-time with large data sets, manually scaling axes prevents the chart
169 // from having to search for min-max ranges which is cpu intensive.
170
171 Pesgo1.PeGrid.Configure.ManualMinX = m_nRealTimeCounter - 2000000;
172 Pesgo1.PeGrid.Configure.ManualMaxX = m_nRealTimeCounter;
173
174 m_nSinCounter = m_nSinCounter + nNewSamplesPerSubsetsPerTick;
175
176 //if (Pesgo1.PeGrid.Zoom.Mode == true) // without this, one can zoom and see a stationary view of the data, else the view shifts
177 //{
178 // Pesgo1.PeGrid.Zoom.MaxX = Pesgo1.PeGrid.Zoom.MaxX + nNewSamplesPerSubsetsPerTick;
179 // Pesgo1.PeGrid.Zoom.MinX = Pesgo1.PeGrid.Zoom.MinX + nNewSamplesPerSubsetsPerTick;
180 //}
181
182 Pesgo1.PeFunction.Force3dxVerticeRebuild = true;
183 Pesgo1.PeFunction.ReinitializeResetImage(); // needed to update the x axis to latest extents
184 Pesgo1.Invalidate();
185
186 if (m_nSinCounter >= 135) { m_nSinCounter = 0; }
187}
188
189*/
Tip: Uses property syntax like Pego1.PeData.Y[s, p]Click underlined properties to view documentation