protected void AddDataToChart(Chart chart, MOE.Common.Business.SignalPhase signalPhase, DateTime startDate, DateTime endDate, int binSize, string signalId, bool showDelayPerHour, bool showDelayPerVehicle) { foreach (MOE.Common.Business.Plan plan in signalPhase.Plans.PlanList) { //double totalPlanAoR = 0; //double totalPlanDelay = 0; //double avgPlanDelay = 0; //double totalPlanDetHits = 0; if (plan.CycleCollection.Count > 0) { DateTime dt = plan.StartTime; //int Yvalueholder = 0; //int Y2valueholder = 0; while (dt < plan.EndTime) { var pcds = from item in plan.CycleCollection where item.StartTime > dt && item.EndTime < dt.AddMinutes(binSize) select item; if (showDelayPerVehicle) { if (pcds.Count() > 0) { chart.Series["Approach Delay Per Vehicle"].Points.AddXY(dt, pcds.Sum(d => d.TotalDelay) / pcds.Sum(d => d.TotalVolume)); } else { chart.Series["Approach Delay Per Vehicle"].Points.AddXY(dt, 0); } } if (showDelayPerHour) { chart.Series["Approach Delay"].Points.AddXY(dt, (pcds.Sum(d => d.TotalDelay) * (60 / binSize))); } dt = dt.AddMinutes(binSize); } } } Dictionary <string, string> statistics = new Dictionary <string, string>(); statistics.Add("Average Delay Per Vehicle (AD)", Math.Round(signalPhase.AvgDelay) + " seconds"); statistics.Add("Total Delay For Selected Period (TD)", Math.Round(signalPhase.TotalDelay) + " seconds"); SetChartTitles(signalPhase, statistics); }
//public SignalPhaseCollection( DateTime startDate, DateTime endDate, string signalID, // bool showVolume, int binSize, int metricTypeID) //{ // MOE.Common.Models.Repositories.ISignalsRepository repository = // MOE.Common.Models.Repositories.SignalsRepositoryFactory.Create(); // var signal = repository.GetSignalBySignalID(signalID); // var detectors = signal.GetDetectorsForSignal(); // if (detectors.Count > 0) // { // foreach (Models.Detector detector in detectors) // { // int detChannel = detector.DetChannel; // Double offset = detector.GetOffset(); // String direction = detector.Approach.DirectionType.Description; // bool isOverlap = detector.Approach.IsProtectedPhaseOverlap; // //Get the phase // MOE.Common.Business.SignalPhase signalPhase = new MOE.Common.Business.SignalPhase( // startDate, endDate, detector.Approach, showVolume, binSize, metricTypeID); // this.SignalPhaseList.Add(signalPhase); // } // } //} public SignalPhaseCollection(DateTime startDate, DateTime endDate, string signalID, bool showVolume, int binSize, int metricTypeID) { MOE.Common.Models.Repositories.ISignalsRepository repository = MOE.Common.Models.Repositories.SignalsRepositoryFactory.Create(); var signal = repository.GetSignalBySignalID(signalID); List <Models.Approach> approaches = signal.GetApproachesForSignalThatSupportMetric(metricTypeID); if (signal.Approaches != null && approaches.Count > 0) { Parallel.ForEach(approaches, approach => //foreach (Models.Approach approach in approaches) { String direction = approach.DirectionType.Description; bool isOverlap = approach.IsProtectedPhaseOverlap; int phaseNumber = approach.ProtectedPhaseNumber; //double offset = approach.GetOffset(); //Get the phase MOE.Common.Business.SignalPhase signalPhase = new MOE.Common.Business.SignalPhase( startDate, endDate, approach, showVolume, binSize, metricTypeID); //try not to add the same direction twice var ExsitingPhases = from MOE.Common.Business.SignalPhase phase in this.SignalPhaseList where phase.Approach.DirectionType.Description == signalPhase.Approach.DirectionType.Description select phase; if (ExsitingPhases.Count() < 1) { this.SignalPhaseList.Add(signalPhase); } }); this.signalPhaseList = signalPhaseList.OrderBy(s => s.Approach.ProtectedPhaseNumber).ToList(); } }
/// <summary> /// Adds data points to a graph with the series GreenLine, YellowLine, Redline /// and Points already added. /// </summary> /// <param name="chart"></param> /// <param name="signalPhase"></param> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <param name="signalId"></param> private void AddDataToChart(Chart chart, MOE.Common.Business.SignalPhase signalPhase, DateTime startDate, DateTime endDate, bool showVolume, bool showArrivalOnGreen) { decimal totalDetectorHits = 0; decimal totalOnGreenArrivals = 0; decimal percentArrivalOnGreen = 0; //Add the data by plan foreach (MOE.Common.Business.Plan plan in signalPhase.Plans.PlanList) { //check for empty pcd collection if (plan.CycleCollection.Count > 0) { foreach (MOE.Common.Business.Cycle pcd in plan.CycleCollection) { //add the data for the green line chart.Series["Change to Green"].Points.AddXY( pcd.GreenEvent, pcd.GreenLineY); //add the data for the yellow line chart.Series["Change to Yellow"].Points.AddXY( pcd.YellowEvent, pcd.YellowLineY); //add the data for the red line chart.Series["Change to Red"].Points.AddXY( pcd.EndTime, pcd.RedLineY); //add the detector hits to the running total totalDetectorHits += pcd.DetectorCollection.Count; //add the detector hits to the detector activation series foreach (MOE.Common.Business.DetectorDataPoint detectorPoint in pcd.DetectorCollection) { chart.Series["Detector Activation"].Points.AddXY( detectorPoint.TimeStamp, detectorPoint.YPoint); //if this is an arrival on green add it to the running total if (detectorPoint.YPoint > pcd.GreenLineY && detectorPoint.YPoint < pcd.RedLineY) { totalOnGreenArrivals++; } } } } } //add the volume data to the volume series if true if (showVolume) { foreach (MOE.Common.Business.Volume v in signalPhase.Volume.Items) { chart.Series["Volume Per Hour"].Points.AddXY(v.XAxis, v.YAxis); } } //if arrivals on green is selected add the data to the chart if (showArrivalOnGreen) { if (totalDetectorHits > 0) { percentArrivalOnGreen = (totalOnGreenArrivals / totalDetectorHits) * 100; } else { percentArrivalOnGreen = 0; } Title title = new Title(); title.Text = Math.Round(percentArrivalOnGreen).ToString() + "% AoG"; title.Font = new Font(FontFamily.GenericSansSerif, 20); chart.Titles.Add(title); SetPlanStrips(signalPhase.Plans.PlanList, chart, startDate); } MOE.Common.Models.Repositories.IMetricCommentRepository mcr = MOE.Common.Models.Repositories.MetricCommentRepositoryFactory.Create(); MOE.Common.Models.MetricComment comment = mcr.GetLatestCommentForReport(signalPhase.Approach.SignalID, MetricTypeID); if (comment != null) { chart.Titles.Add(comment.CommentText); chart.Titles[1].Docking = Docking.Bottom; chart.Titles[1].ForeColor = Color.Red; } }
/// <summary> /// /// </summary> /// <param name="signalId"></param> /// <param name="direction"></param> /// <param name="delta"></param> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <param name="upstream"></param> /// <param name="maxYAxis"></param> private void GeneratePCD(Models.Approach approach, int delta, DateTime startDate, DateTime endDate, bool upstream, int maxYAxis) { MOE.Common.Models.Repositories.ISignalsRepository repository = MOE.Common.Models.Repositories.SignalsRepositoryFactory.Create(); //var signal = repository.GetSignalBySignalID(approach.SignalId); //Create a location string to show the combined cross strees string location = string.Empty; if (approach.Signal != null) { location = approach.Signal.PrimaryName + " " + approach.Signal.SecondaryName; } string chartName = string.Empty; //MOE.Common.Data.LinkPivotTableAdapters.Graph_DetectorsTableAdapter gdAdapter = // new Data.LinkPivotTableAdapters.Graph_DetectorsTableAdapter(); //find the upstream approach if (!String.IsNullOrEmpty(approach.DirectionType.Description)) { //Find PCD detector for this appraoch MOE.Common.Models.Detector gd = approach.Signal.GetDetectorsForSignalThatSupportAMetricByApproachDirection( 6, approach.DirectionType.Description).FirstOrDefault(); //Check for null value if (gd != null) { //Instantiate a signal phase object SignalPhase sp = new MOE.Common.Business.SignalPhase( startDate, endDate, approach, false, 15, 13); //Check the direction of the Link Pivot if (upstream) { //Create a chart for the upstream detector before adjustments upstreamBeforePCDPath = CreateChart(sp, startDate, endDate, location, "before", ConfigurationManager.AppSettings["ImageLocation"], maxYAxis, "UpstreamBefore"); //Add the total arrival on green before adjustments to the running total existingTotalAOG += sp.TotalArrivalOnGreen; //Add the volume from the signal phase to the running total existingVolume += sp.TotalVolume; //Re run the signal phase by the optimized delta change to get the adjusted pcd sp.LinkPivotAddSeconds(delta * -1); //Create a chart for the upstream detector after adjustments upstreamAfterPCDPath = CreateChart(sp, startDate, endDate, location, "after", ConfigurationManager.AppSettings["ImageLocation"], maxYAxis, "UpstreamAfter"); //Add the total arrival on green after adjustments to the running total predictedTotalAOG += sp.TotalArrivalOnGreen; //Add the volume from the signal phase to the running total predictedVolume += sp.TotalVolume; } else { //Create a chart for downstream detector before adjustments downstreamBeforePCDPath = CreateChart(sp, startDate, endDate, location, "before", ConfigurationManager.AppSettings["ImageLocation"], maxYAxis, "DownstreamBefore"); //Add the arrivals on green to the total arrivals on green running total existingTotalAOG += sp.TotalArrivalOnGreen; //Add the volume before adjustments to the running total volume existingVolume += sp.TotalVolume; //Re run the signal phase by the optimized delta change to get the adjusted pcd sp.LinkPivotAddSeconds(delta); //Create a pcd chart for downstream after adjustments downstreamAfterPCDPath = CreateChart(sp, startDate, endDate, location, "after", ConfigurationManager.AppSettings["ImageLocation"], maxYAxis, "DownstreamAfter"); //Add the total arrivals on green to the running total predictedTotalAOG += sp.TotalArrivalOnGreen; //Add the total volume to the running total after adjustments predictedVolume += sp.TotalVolume; } } } }
public DelayChart(WCFServiceLibrary.ApproachDelayOptions options, MOE.Common.Business.SignalPhase signalPhase) { Options = options; TimeSpan reportTimespan = Options.EndDate - Options.StartDate; string extendedDirection = signalPhase.Approach.DirectionType.Description; //Set the chart properties chart.ImageStorageMode = ImageStorageMode.UseImageLocation; chart.ImageType = ChartImageType.Jpeg; chart.Height = 550; chart.Width = 1100; //Create the chart legend Legend chartLegend = new Legend(); chartLegend.Name = "MainLegend"; chartLegend.Docking = Docking.Left; chart.Legends.Add(chartLegend); //Create the chart area ChartArea chartArea = new ChartArea(); chartArea.Name = "ChartArea1"; //Primary Y axis (delay per vehicle) if (Options.ShowDelayPerVehicle) { if (Options.YAxisMax != null) { chartArea.AxisY.Maximum = Options.YAxisMax.Value; } chartArea.AxisY.Minimum = 0; chartArea.AxisY.Enabled = AxisEnabled.True; chartArea.AxisY.MajorTickMark.Enabled = true; chartArea.AxisY.MajorGrid.Enabled = true; chartArea.AxisY.Interval = 5; chartArea.AxisY.TitleForeColor = Color.Blue; chartArea.AxisY.Title = "Delay Per Vehicle (Seconds) "; } //secondary y axis (total delay) if (Options.ShowDelayPerVehicle) { if (Options.Y2AxisMax != null && Options.Y2AxisMax > 0) { chartArea.AxisY2.Maximum = Options.Y2AxisMax.Value; } else { chartArea.AxisY2.Maximum = 50000; } chartArea.AxisY2.Minimum = 0; chartArea.AxisY2.Enabled = AxisEnabled.True; chartArea.AxisY2.MajorTickMark.Enabled = true; chartArea.AxisY2.MajorGrid.Enabled = false; chartArea.AxisY2.Interval = 5000; chartArea.AxisY2.Title = "Delay per Hour (Seconds) "; chartArea.AxisY2.TitleForeColor = Color.Red; } chartArea.AxisX.Title = "Time (Hour of Day)"; chartArea.AxisX.IntervalType = DateTimeIntervalType.Hours; chartArea.AxisX.LabelStyle.Format = "HH"; chartArea.AxisX2.LabelStyle.Format = "HH"; if (reportTimespan.Days < 1) { if (reportTimespan.Hours > 1) { chartArea.AxisX2.Interval = 1; chartArea.AxisX.Interval = 1; } else { chartArea.AxisX.LabelStyle.Format = "HH:mm"; chartArea.AxisX2.LabelStyle.Format = "HH:mm"; } } chartArea.AxisX2.Enabled = AxisEnabled.True; chartArea.AxisX2.MajorTickMark.Enabled = true; chartArea.AxisX2.IntervalType = DateTimeIntervalType.Hours; chartArea.AxisX2.LabelAutoFitStyle = LabelAutoFitStyles.None; chart.ChartAreas.Add(chartArea); //Add the point series Series delayPerVehicleSeries = new Series(); delayPerVehicleSeries.ChartType = SeriesChartType.Line; delayPerVehicleSeries.Color = Color.Blue; delayPerVehicleSeries.Name = "Approach Delay Per Vehicle"; delayPerVehicleSeries.YAxisType = AxisType.Primary; delayPerVehicleSeries.XValueType = ChartValueType.DateTime; Series delaySeries = new Series(); delaySeries.ChartType = SeriesChartType.Line; delaySeries.Color = Color.Red; delaySeries.Name = "Approach Delay"; delaySeries.YAxisType = AxisType.Secondary; delaySeries.XValueType = ChartValueType.DateTime; Series pointSeries = new Series(); pointSeries.ChartType = SeriesChartType.Point; pointSeries.Color = Color.White; pointSeries.Name = "Posts"; pointSeries.XValueType = ChartValueType.DateTime; pointSeries.IsVisibleInLegend = false; chart.Series.Add(pointSeries); chart.Series.Add(delaySeries); chart.Series.Add(delayPerVehicleSeries); //Add points at the start and and of the x axis to ensure //the graph covers the entire period selected by the user //whether there is data or not chart.Series["Posts"].Points.AddXY(Options.StartDate, 0); chart.Series["Posts"].Points.AddXY(Options.EndDate, 0); AddDataToChart(chart, signalPhase, Options.StartDate, Options.EndDate, Options.SelectedBinSize, signalPhase.Approach.SignalID, Options.ShowTotalDelayPerHour, Options.ShowDelayPerVehicle); SetPlanStrips(signalPhase.Plans.PlanList, chart, Options.StartDate, Options.ShowPlanStatistics); }
public ArriveOnRedChart(WCFServiceLibrary.AoROptions options, MOE.Common.Business.SignalPhase signalPhase) { Options = options; TimeSpan reportTimespan = Options.EndDate - Options.StartDate; //Set the chart properties chart.ImageStorageMode = ImageStorageMode.UseImageLocation; chart.ImageType = ChartImageType.Jpeg; chart.Height = 550; chart.Width = 1100; //Create the chart legend Legend chartLegend = new Legend(); chartLegend.Name = "MainLegend"; chartLegend.Docking = Docking.Left; chart.Legends.Add(chartLegend); //Create the chart area ChartArea chartArea = new ChartArea(); chartArea.Name = "ChartArea1"; if (Options.YAxisMax != null) { chartArea.AxisY.Maximum = Options.YAxisMax.Value; } chartArea.AxisY.Minimum = 0; chartArea.AxisY.Title = "Volume (Vehicles Per Hour)"; chartArea.AxisY.Interval = 500; chartArea.AxisY2.Title = "Percent AoR"; chartArea.AxisY2.Maximum = 100; chartArea.AxisY2.Interval = 10; chartArea.AxisY2.Enabled = AxisEnabled.True; chartArea.AxisX.Title = "Time (Hour of Day)"; chartArea.AxisX.IntervalType = DateTimeIntervalType.Hours; chartArea.AxisX.LabelStyle.Format = "HH"; chartArea.AxisX2.LabelStyle.Format = "HH"; if (reportTimespan.Days < 1) { if (reportTimespan.Hours > 1) { chartArea.AxisX2.Interval = 1; chartArea.AxisX.Interval = 1; } else { chartArea.AxisX.LabelStyle.Format = "HH:mm"; chartArea.AxisX2.LabelStyle.Format = "HH:mm"; } } chartArea.AxisX2.Enabled = AxisEnabled.True; chartArea.AxisX2.MajorTickMark.Enabled = true; chartArea.AxisX2.IntervalType = DateTimeIntervalType.Hours; chartArea.AxisX2.LabelAutoFitStyle = LabelAutoFitStyles.None; chart.ChartAreas.Add(chartArea); //Add the point series Series AoRSeries = new Series(); AoRSeries.ChartType = SeriesChartType.Line; AoRSeries.BorderDashStyle = ChartDashStyle.Dash; AoRSeries.Color = Color.Red; AoRSeries.Name = "Arrivals on Red"; AoRSeries.XValueType = ChartValueType.DateTime; Series TVSeries = new Series(); TVSeries.ChartType = SeriesChartType.Line; TVSeries.BorderDashStyle = ChartDashStyle.Dash; TVSeries.Color = Color.Black; TVSeries.Name = "Total Vehicles"; TVSeries.XValueType = ChartValueType.DateTime; Series PARSeries = new Series(); PARSeries.ChartType = SeriesChartType.Line; PARSeries.Color = Color.Red; PARSeries.Name = "Percent Arrivals on Red"; PARSeries.BorderWidth = 2; PARSeries.XValueType = ChartValueType.DateTime; PARSeries.YAxisType = AxisType.Secondary; Series pointSeries = new Series(); pointSeries.ChartType = SeriesChartType.Point; pointSeries.Color = Color.White; pointSeries.Name = "Posts"; pointSeries.XValueType = ChartValueType.DateTime; pointSeries.IsVisibleInLegend = false; chart.Series.Add(pointSeries); chart.Series.Add(AoRSeries); chart.Series.Add(PARSeries); chart.Series.Add(TVSeries); //Add points at the start and and of the x axis to ensure //the graph covers the entire period selected by the user //whether there is data or not chart.Series["Posts"].Points.AddXY(Options.StartDate, 0); chart.Series["Posts"].Points.AddXY(Options.EndDate, 0); AddDataToChart(chart, signalPhase); SetPlanStrips(signalPhase.Plans.PlanList, chart, Options.StartDate, Options.ShowPlanStatistics); }
protected void AddDataToChart(Chart chart, MOE.Common.Business.SignalPhase signalPhase) { double totalDetectorHits = 0; int yAxisHolder = 0; foreach (MOE.Common.Business.Plan plan in signalPhase.Plans.PlanList) { if (plan.CycleCollection.Count > 0) { DateTime dt = plan.StartTime; while (dt < plan.EndTime) { double binTotalStops = 0; double binPercentAoR = 0; double binDetectorHits = 0; var pcds = from item in plan.CycleCollection where item.StartTime > dt && item.EndTime < dt.AddMinutes(Options.SelectedBinSize) select item; foreach (MOE.Common.Business.Cycle pcd in pcds) { totalDetectorHits += pcd.DetectorCollection.Count; binDetectorHits += pcd.DetectorCollection.Count; foreach (MOE.Common.Business.DetectorDataPoint detectorPoint in pcd.DetectorCollection) { if (detectorPoint.YPoint < pcd.GreenLineY) //&& detectorPoint.YPoint < pcd.RedLineY) { binTotalStops++; totalAoR++; } } if (binDetectorHits > 0) { binPercentAoR = ((binTotalStops / binDetectorHits) * 100); } } chart.Series["Percent Arrivals on Red"].Points.AddXY(dt, binPercentAoR); chart.Series["Total Vehicles"].Points.AddXY(dt, (binDetectorHits * (60 / Options.SelectedBinSize))); chart.Series["Arrivals on Red"].Points.AddXY(dt, (binTotalStops * (60 / Options.SelectedBinSize))); dt = dt.AddMinutes(Options.SelectedBinSize); if (yAxisHolder < (binTotalStops * (60 / Options.SelectedBinSize)) && Options.YAxisMax == null) { yAxisHolder = Convert.ToInt16(binDetectorHits * (60 / Options.SelectedBinSize)); yAxisHolder = RoundToNearest(yAxisHolder, 100); chart.ChartAreas[0].AxisY.Maximum = yAxisHolder + 250; } } } } totalCars = totalDetectorHits; if (totalDetectorHits > 0) { totalPercentAoR = ((totalAoR / totalCars) * 100); } Dictionary <string, string> statistics = new Dictionary <string, string>(); statistics.Add("Total Detector Hits", totalCars.ToString()); statistics.Add("Total AoR", totalAoR.ToString()); statistics.Add("Percent AoR for the select period", Math.Round(totalPercentAoR).ToString()); SetChartTitles(signalPhase, statistics); }