// was before v 3.5: private async void LoadSampleDataGroupFromPatientDataList(SampleDataGroup g, TP_PatientReports p) private async Task LoadSampleDataGroupFromPatientDataList(SampleDataGroup g, TP_PatientReports p) { g.Items.Clear(); //string encodedTemp; foreach (TP_PatientReport pdi in p) { pdi.ImageEncoded = await pdi.FormatImageEncoded(); g.Items.Add(new SampleDataItem( pdi.FormatUniqueID(), pdi.FormatTitle(), pdi.FormatSubtitle(), pdi.ImageEncoded, // freshened above pdi.FormatImageBorderColor(), pdi.FormatDescription(), pdi.FormatContent(), g)); } }
private void UpdateChartPage7() { string eventName = ""; // No longer needed, now that we have App.PatientDataGroups.GetOutboxForStatistics(): // // sorting added June 2015, so call to outboxCountPerDaySpecificEventSet in UpdateChartPage7Impl will work right // List<TP_PatientReport> orig = App.PatientDataGroups.GetOutbox().GetAsList(); // List<TP_PatientReport> sort = new List<TP_PatientReport>(); // sort = orig.OrderBy(o => o.WhenLocalTime).ToList(); // //sort = orig.OrderByDescending(o => o.WhenLocalTime).ToList(); // TP_PatientReports pdl = new TP_PatientReports(); // pdl.ReplaceWithList(sort); TP_PatientReports pdl = App.PatientDataGroups.GetOutboxForStatistics(); TP_PatientReports results = new TP_PatientReports(); TP_EventsDataList edl = App.CurrentDisasterList; // Across events. Widen range by at least 2 days to prevent stupid clipping of line segments and/or data points. minDT = FindMinimumDate().AddDays(-2.0); maxDT = FindMaximumDate().AddDays(2.0); WidenRange(); // May adjust minDT, maxDT List<DateValueItem>[] arrivalLines = new List<DateValueItem>[10]; // Handle up to 10 events first draft LineSeries[] ls = new LineSeries[10]; int i = 0; foreach (var edi in edl) { eventName = edi.EventName; foreach (var pdi in pdl) { if (pdi.EventName == eventName) results.Add(pdi); } if (results.Count() > 0) { arrivalLines[i] = new List<DateValueItem>(); ls[i] = new LineSeries(); UpdateChartPage7Impl(eventName, results, ls[i], arrivalLines[i]); /* FIRST DRAFT, THEN MOVED if (i == 0) { ls[i].IndependentAxis = new DateTimeAxis() { Minimum = minDT, Maximum = maxDT, FontSize = 10, Orientation = AxisOrientation.X, Location = AxisLocation.Bottom }; // explicitly state bottom so won't end up with top & bottom labels ls[i].DependentRangeAxis = new LinearAxis() { Minimum = 0, Interval = 1.0, Orientation = AxisOrientation.Y, ShowGridLines = true, FontSize = 11 }; // BorderThickness = new Thickness(2.0), BorderBrush = new SolidColorBrush(Colors.White) }; } else { ls[i].IndependentAxis = new DateTimeAxis() { Minimum = minDT, Maximum = maxDT, FontSize = 0.1, Orientation = AxisOrientation.X, Location = AxisLocation.Bottom }; // explicitly state bottom so won't end up with top & bottom labels // When redraws, grid lines are not perfectly atop each other, so suppress ls[i].DependentRangeAxis = new LinearAxis() { Minimum = 0, Interval = 1.0, Orientation = AxisOrientation.Y, ShowGridLines = false, FontSize = 0.1 }; // BorderThickness = new Thickness(2.0), BorderBrush = new SolidColorBrush(Colors.White) }; } //ls[i].DataPointStyle = GetDataPointStyleWithNoPointsRandomLineColors(); LineChartArrivalsAllStations_Page7.Series.Add(ls[i]); */ results.Clear(); i++; } } // Can't rely on auto-scaling to work right with multilines if we're setting axis (in order to set interval) // So calculate max count here across events, for benefit of setting axes: int maxCount = 0; for(int j=0; j < i; j++) { foreach(var dvi in arrivalLines[j]) { if(dvi.Value > maxCount) maxCount = dvi.Value; } } // Prettify: double yinterval = 1.0; if (maxCount <= 10) { maxCount = 10; } else if (maxCount <= 25) { maxCount = 25; yinterval = 5.0; } else if (maxCount <= 50) { maxCount = 50; yinterval = 5.0; } else if (maxCount <= 100) { maxCount = 100; yinterval = 10.0; } else { maxCount = (maxCount % 100) * 100; yinterval = 25.0; } // Set axes & finish for (int j = 0; j < i; j++) { if (j == 0) { ls[j].IndependentAxis = new DateTimeAxis() { Minimum = minDT, Maximum = maxDT, FontSize = 10, Orientation = AxisOrientation.X, Location = AxisLocation.Bottom }; // explicitly state bottom so won't end up with top & bottom labels ls[j].DependentRangeAxis = new LinearAxis() { Minimum = 0, Maximum = maxCount, Interval = yinterval, Orientation = AxisOrientation.Y, ShowGridLines = true, Location = AxisLocation.Left, FontSize = 11 }; // BorderThickness = new Thickness(2.0), BorderBrush = new SolidColorBrush(Colors.White) }; } else { ls[j].IndependentAxis = new DateTimeAxis() { Minimum = minDT, Maximum = maxDT, FontSize = 0.1, Orientation = AxisOrientation.X, Location = AxisLocation.Bottom }; // explicitly state bottom so won't end up with top & bottom labels // When redraws, grid lines are not perfectly atop each other, so suppress ls[j].DependentRangeAxis = new LinearAxis() { Minimum = 0, Maximum = maxCount, Interval = yinterval, Orientation = AxisOrientation.Y, ShowGridLines = true, Location=AxisLocation.Left, FontSize = 0.1 }; // BorderThickness = new Thickness(2.0), BorderBrush = new SolidColorBrush(Colors.White) }; } //ls[i].DataPointStyle = GetDataPointStyleWithNoPointsRandomLineColors(); LineChartArrivalsAllStations_Page7.Series.Add(ls[j]); } }
private void UpdateChartPage7Impl(string eventName, TP_PatientReports arrivalsOneEvent, LineSeries series, List<DateValueItem> arrivalLine) { outboxCountPerDaySpecificEventSet(arrivalsOneEvent, arrivalLine); series.ItemsSource = arrivalLine; series.Name = "Chart 7 " + eventName; series.Title = eventName; // should these be "Name" or "Value" instead of "Path"? series.IndependentValueBinding = new Binding(); series.DependentValueBinding = new Binding(); series.IndependentValueBinding.Path = new PropertyPath("DateTimeBucket"); series.DependentValueBinding.Path = new PropertyPath("Value"); /* MAYBENOT series.IndependentValuePath = "DateTimeBucket"; series.DependentValuePath = "Value"; */ series.IsSelectionEnabled = true; }
/// <summary> /// Given an input list of patients, ordered from oldest first to newest last, for either a single event or a set of events that we don't care to distinguish (e.g., all events), /// returns a list with the date of each one-day bucket (with time zeroed) and the count within the bucket /// </summary> /// <param name="arrivalsByDateSpecificEvent"></param> public void outboxCountPerDaySpecificEventSet(TP_PatientReports arrivalsIn, List<DateValueItem> arrivalsOut) { if (arrivalsIn.Count<TP_PatientReport>() == 0) return; DateTimeOffset startOfBucket; DateTimeOffset currentItem; bool firstloop = true; int inBucket = 0; foreach (var i in arrivalsIn) { // For Release 6, use of i.WhenLocalTime in this loop replaced by i.WhenLocalTimeMsg1, i.e., arrival time if (String.IsNullOrEmpty(i.WhenLocalTimeMsg1)) continue; // assume weird empty record if (firstloop) { firstloop = false; DateTimeOffset firstInBucket = DateTimeOffset.Parse(i.WhenLocalTimeMsg1); // Zero out anything under 1 day startOfBucket = new DateTimeOffset(firstInBucket.Year, firstInBucket.Month, firstInBucket.Day, 0, 0, 0, firstInBucket.Offset); inBucket = 1; continue; } currentItem = DateTime.Parse(i.WhenLocalTimeMsg1); if (currentItem.Year == startOfBucket.Year && currentItem.DayOfYear == startOfBucket.DayOfYear) { inBucket++; continue; } // record count accumulated from last through loop: arrivalsOut.Add(new DateValueItem { DateTimeBucket = startOfBucket.DateTime, Value = inBucket }); #if OK_BUT_TOO_MANY_ZERO_POINTS startOfBucket = startOfBucket.AddDays(1.0); // Generate buckets with zeros, 1 per day: while (currentItem.Year > startOfBucket.Year || currentItem.DayOfYear > startOfBucket.DayOfYear) { arrivalsOut.Add(new DateValueItem { DateTimeBucket = startOfBucket.DateTime, Value = 0 }); startOfBucket = startOfBucket.AddDays(1.0); } #endif startOfBucket = startOfBucket.AddDays(1.0); // Generate two buckets with zeros, at either end of range (or a single bucket if there's only 1 zero day between non-zero days): if (currentItem.Year > startOfBucket.Year || currentItem.DayOfYear > startOfBucket.DayOfYear) { arrivalsOut.Add(new DateValueItem { DateTimeBucket = startOfBucket.DateTime, Value = 0 }); // 1st one startOfBucket = startOfBucket.AddDays(1.0); if (currentItem.Year > startOfBucket.Year || currentItem.DayOfYear > startOfBucket.DayOfYear) { while (currentItem.Year > startOfBucket.Year || currentItem.DayOfYear > startOfBucket.DayOfYear) startOfBucket = startOfBucket.AddDays(1.0); // skip redundant zero points in center of their range arrivalsOut.Add(new DateValueItem { DateTimeBucket = startOfBucket.DateTime.AddDays(-1.0), Value = 0 }); // 2nd one. Note -1 day } } // New bucket starting inBucket = 1; } // Last bucket: arrivalsOut.Add(new DateValueItem { DateTimeBucket = startOfBucket.DateTime, Value = inBucket }); // Special case... if (arrivalsOut.Count == 1) { // Need to generate an extra zero point so that there's at least 1 line segment visible. // We'll do it here at end, rather than beginning... smarter algorithm would have caller give us hint to generate at beginning, at end, or both. startOfBucket = startOfBucket.AddDays(1.0); arrivalsOut.Add(new DateValueItem { DateTimeBucket = startOfBucket.DateTime, Value = 0 }); } }