/* * Scenario * 1. Called from UI-thread, on startup or change of timescale. invalidateData = true, isBackgrounThread = false * - calculate and store averaging factor * 2. Called from bakgroundthread when new data arrives. invalidateData = false, isBackgroundThread = false * - recall averaging factor * 3. Called from backgroundthread to produce plots on disk. invalidateData = false, isBackgroundThread = true * - calculate, do NOT store averaging factor */ private List <EFOSDataPoint> GetData(DateTime from, DateTime to, bool invalidateData, bool isBackgroundThread = false) { List <EFOSDataPoint> data = d.LoadData(from, to); if (data.Count == 0) { return(data); } int avg = 0; // Average date to around 2000 points. Charts are slow with too many points. // Bug: If requesting more data than is available, averagingFactor will be incorrectly set. // Not expected to happen.. string msg; if (invalidateData) { avg = (int)Math.Floor((double)data.Count / 2000); msg = String.Format("Averaging {0} pts", avg); if (!isBackgroundThread) { if (InvokeRequired) { Invoke((MethodInvoker) delegate { averagingLabel.Text = msg; }); } else { averagingLabel.Text = msg; } averagingFactor = avg; } } else { avg = averagingFactor; } //if (data.Count < averagingFactor) // return; // averagingFactor is preserved from the first load, any updated data // will use the same factor. if (avg > 1) { List <EFOSDataPoint> averagedData = new List <EFOSDataPoint>(); int i = 0; while (i < data.Count - 1) { EFOSDataPoint avPt = new EFOSDataPoint(); int cnt = 0; while (cnt < avg) { if (i + cnt > data.Count - 1) { goto Foo; // Break out, ensuring that the last "incomplete" datapoint is not added to collection. } EFOSDataPoint dataPt = data[i + cnt]; avPt.timestamp = dataPt.timestamp; // the timestamp of the last datapoint will be the // "from" to retrieve updated data if (cnt == 0) { avPt.values = dataPt.values; } else { for (int idx = 0; idx < avPt.values.Length; idx++) { avPt.values[idx] += dataPt.values[idx]; } } cnt++; } // Average for (int idx = 0; idx < avPt.values.Length; idx++) { avPt.values[idx] /= cnt; } i += cnt; averagedData.Add(avPt); } Foo: // Do not update from background thread. if (!isBackgroundThread) { msg = string.Format("Received {0} pts, plotted {1} pts, left {2} pts", data.Count, averagedData.Count, data.Count - (averagedData.Count * averagingFactor)); if (InvokeRequired) { Invoke((MethodInvoker) delegate { debugLabel.Text = msg; }); } else { debugLabel.Text = msg; } } data = averagedData; } else { // Do not update from background thread. if (!isBackgroundThread) { msg = string.Format("Received {0} pts", data.Count); if (InvokeRequired) { Invoke((MethodInvoker) delegate { debugLabel.Text = msg; }); } else { debugLabel.Text = msg; } } } return(data); }
public List <EFOSDataPoint> LoadData(DateTime from, DateTime to) { List <EFOSDataPoint> data = new List <EFOSDataPoint>(); string[] files = Directory.EnumerateFiles(path, filenames).ToArray(); Array.Sort(files); // Sort from oldest to newest // Need to strip off hour:in:sec from "from", in order to load the file containing that data. DateTime fromDate = DateTime.Parse(from.ToShortDateString()); foreach (string file in files) { DateTime currentFile = DateTime.Parse(file.Substring(file.Length - 14, 10)); // Filter out files older than "from" if (currentFile < fromDate) { continue; } // Skip datafiles newer than "to". if (currentFile > to) { continue; } var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); StreamReader f = new StreamReader(fs); // Read and discard first line, headers //f.ReadLine(); while (!f.EndOfStream) { try { EFOSDataPoint d = new EFOSDataPoint(); string[] words = f.ReadLine().Split(';'); // First column is timestamp. //d.timestamp = DateTime.Parse(words[0]).ToOADate(); //Skip lines where last field (parse error) is not 0 if (words[words.Length - 1] != "0") { continue; } // Skip lines not starting with a valid timestamp - headers DateTime tmp; if (!DateTime.TryParse(words[0], out tmp)) { continue; } d.timestamp = tmp.ToOADate(); // Skip data older than from if (d.timestamp <= from.ToOADate()) { continue; } // Skip data newer than to if (to != null && d.timestamp > to.ToOADate()) { continue; } // The rest is doubles. Transform transform t; double[] values = new double[words.Length - 2]; // Subract timestamp, and last field (error-flag) for (int i = 0; i < values.Length; i++) { switch (i) { case (int)EFOScol.IntVacA: case (int)EFOScol.IntVacV: case (int)EFOScol.ExtVacA: case (int)EFOScol.ExtVacV: t = val => Math.Abs(val); break; case (int)EFOScol.p24V: t = val => val - 24; break; case (int)EFOScol.p15V1: case (int)EFOScol.p15V2: t = val => val - 15; break; case (int)EFOScol.n15V1: case (int)EFOScol.n15V2: t = val => val + 15; break; case (int)EFOScol.p5V: t = val => val - 5; break; default: t = val => val; break; } values[i] = t(double.Parse(words[i + 1], NumberStyles.Float | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign)); } d.values = values; data.Add(d); } catch (Exception) { // TO do - log } } f.Close(); } // The last point read may be corrupted, as another process is writing to the file. Try to detect, and discard. if (data.Count > 0) { EFOSDataPoint last = data.Last(); while (data.Count > 0 && last.values.Length != 35) { data.Remove(last); last = data.Last(); } } return(data); }