/// <summary> /// Adds a tagged datapoint to a series. /// </summary> private static void AddDataPoint(MCharting.Series series, int x, double y, GroupInfo type) { MCharting.DataPoint dp = new MCharting.DataPoint(x, y); dp.Tag = new IntensityInfo(null, null, type, y); if (double.IsNaN(y) || double.IsInfinity(y)) { y = 0; } series.Points.Add(dp); }
/// <summary> /// Plots a line of conditions on the graph /// </summary> /// <param name="peak">Peak to plot</param> /// <param name="seriesNames">Names of existing series</param> /// <param name="intensities">Intensity values (y)</param> /// <param name="seriesName">Name of this series</param> /// <param name="xInfo">Info for x position of intentises (in same order as intensities)</param> /// <param name="line">Line or dots/</param> /// <param name="bold">Bold line?</param> /// <param name="isConditions">Order by conditions or obervations</param> private void AddToPlot( MCharting.Plot plot, Peak peak, Dictionary <string, MCharting.Series> seriesNames, Vector intensities, string seriesName, StylisedPeakOptions o, EPlot draw, Dictionary <GroupInfoBase, MCharting.Series> groupLegends, MCharting.Series legend) { // Iterate whatever it is we're iterating for (int i = 0; i < intensities.Observations.Length; ++i) { // Get the values ObservationInfo obs = intensities.Observations[i]; // Name the series if (draw.HasFlag(EPlot.ByBatch)) { if (!o.ViewBatches.Contains(obs.Batch)) { continue; } } else { if (!o.ViewGroups.Contains(obs.Group)) { continue; } } bool colorByBatch = draw.HasFlag(EPlot.ByBatch); GroupInfoBase seriesUsing = colorByBatch ? (GroupInfoBase)obs.Batch : (GroupInfoBase)obs.Group; string name = seriesName + " for " + seriesUsing.DisplayName; MCharting.Series series; // Create the series (if required) if (!seriesNames.ContainsKey(name)) { series = plot.Series.Add(name); series.Style.StrictOrder = SeriesStyle.EOrder.X; series.ApplicableLegends.Add(groupLegends[seriesUsing]); series.ApplicableLegends.Add(legend); seriesNames.Add(name, series); series.Tag = peak; Color colour = (draw.HasFlag(EPlot.DrawBold) || draw.HasFlag(EPlot.ByBatch) || !o.ShowTrend) ? seriesUsing.Colour : seriesUsing.ColourLight; if (draw.HasFlag(EPlot.DrawLine)) { series.Style.DrawLines = new Pen(colour); series.Style.DrawLines.Width = draw.HasFlag(EPlot.DrawBold) ? this._core.Options.LineWidth * 4 : this._core.Options.LineWidth; } else { UiControls.CreateIcon(series, seriesUsing); } } else { series = seriesNames[name]; } // Get the X position double xPos; if (draw.HasFlag(EPlot.ByBatch)) { xPos = obs.Order; if (o.ConditionsSideBySide) { xPos += this.GetBatchOffset(o.ViewBatches, obs.Batch); } } else { xPos = obs.Time; if (o.ConditionsSideBySide) { xPos += this.GetTypeOffset(o.ViewGroups, obs.Group); } } // Get the Y position double yPos = intensities.Values[i]; if (double.IsNaN(yPos) || double.IsInfinity(yPos)) { yPos = 0; } // Create the point MCharting.DataPoint cdp = new MCharting.DataPoint(xPos, yPos); IntensityInfo tag = new IntensityInfo(obs.Time, obs.Rep, obs.Group, yPos); cdp.Tag = tag; series.Points.Add(cdp); } }
private void UpdatePlot() { if (this._scores == null) { this._lblSelection.Text = this._errorMessage; this._lblSelection.ForeColor = Color.Red; this._chart.Visible = false; return; } this._chart.Visible = true; this._lblSelection.Text = ""; this._lblSelection.ForeColor = ForeColor; MCharting.Plot plot = new MCharting.Plot(); plot.Title = $"{this._lblMethod.Text} of {this._core.FileNames.Title}"; plot.SubTitle = $"Source: {this._lblPcaSource.Text}, View: {this._lblPlotView.Text}, Legend: {this._lblLegend.Text}, Corrections: {this._lblCorrections.Text}, Observations: {this._lblObs.Text}, Peaks: {this._lblPeaks.Text}"; switch (this._method) { case EMethod.Pca: plot.XLabel = $"PC{this._component + 1}"; plot.YLabel = $"PC{this._component + 2}"; break; case EMethod.Plsr: plot.XLabel = $"Component {this._component + 1}"; plot.YLabel = $"Component {this._component + 2}"; plot.SubTitle += ", PLSR Response: " + this._lblPlsrSource.Text; break; } this._chart.Style.Margin = new Padding(48, 48, 48, 48); plot.Style.GridStyle = new Pen(Color.FromArgb(224, 224, 224)); // Get the "rows" IEnumerator enSources; Column column; this.GetSource(this._colourBy, out enSources, out column); // Get the "columns" double[,] plotPoints; if (this._plotSource == EPlotSource.Loadings) { plotPoints = this._loadings; } else { plotPoints = this._scores; } // Get the component if (this._component < 0) { this._component = 0; } if (this._component >= plotPoints.GetLength(1)) { this._component = plotPoints.GetLength(1) - 1; } this._btnPrevPc.Enabled = this._component != 0; this._btnNextPc.Enabled = this._component != plotPoints.GetLength(1) - 1; this._lblPlotView.Text = this._plotSource == EPlotSource.Loadings ? "Loadings" : "Scores"; this._btnScores.Checked = this._plotSource == EPlotSource.Scores; this._btnLoadings.Checked = this._plotSource == EPlotSource.Loadings; this._lblPcNumber.Text = "PC" + (this._component + 1).ToString() + " / " + plotPoints.GetLength(1); this._lblLegend.Text = column.DisplayName; bool isGroup = false; // Iterate scores for (int r = 0; r < plotPoints.GetLength(0); r++) { enSources.MoveNext(); MCharting.Series series = GetOrCreateSeriesForValue(plot, column, (Visualisable)enSources.Current, ref isGroup); var coord = new MCharting.DataPoint(plotPoints[r, this._component], plotPoints[r, this._component + 1]); coord.Tag = enSources.Current; series.Points.Add(coord); } // Assign colours if (!column.HasColourSupport && !isGroup) { foreach (var colour in PlotCreator.AutoColour(plot.Series)) { colour.Key.Style.DrawPoints = new SolidBrush(colour.Value); } } this._chart.Style.Animate = true; this._chart.Style.SelectionColour = Color.Yellow; this._chart.SetPlot(plot); }
private void AddUpperAndLowerShade( MCharting.Plot plot, StylisedPeakOptions o, Dictionary <string, MCharting.Series> seriesNames, Peak peak, Vector min, Vector max, Dictionary <GroupInfoBase, MCharting.Series> groupLegends) { MCharting.Series legendEntry = new MCharting.Series(); legendEntry.Name = "Range"; legendEntry.Style.DrawVBands = new SolidBrush(Color.Gray); plot.LegendEntries.Add(legendEntry); // Iterate the conditions for (int i = 0; i < min.Observations.Length; i++) { ObservationInfo obs = min.Observations[i]; Debug.Assert(max.Observations[i] == min.Observations[i], "Expected max and min trends to match sequences."); if (o.ViewGroups.Contains(obs.Group)) { // Name the series string name = "Range for " + obs.Group.DisplayName; MCharting.Series series; // Create the series (if required) if (!seriesNames.ContainsKey(name)) { series = plot.Series.Add(name); series.Style.StrictOrder = SeriesStyle.EOrder.X; Color c = obs.Group.ColourLight; c = Color.FromArgb(0x80, c.R, c.G, c.B); series.Tag = peak; series.Style.DrawVBands = obs.Group.CreateBrush(c); series.ApplicableLegends.Add(groupLegends[obs.Group]); series.ApplicableLegends.Add(legendEntry); seriesNames.Add(name, series); } else { series = seriesNames[name]; } // Get the X coordinate int typeOffset = this.GetTypeOffset(o.ViewGroups, obs.Group); double xVal = obs.Time; if (o.ConditionsSideBySide) { xVal += typeOffset; } // Get the Y coordinates double yMin = min.Values[i]; double yMax = max.Values[i]; if (double.IsNaN(yMin) || double.IsInfinity(yMin)) { yMin = 0; } if (double.IsNaN(yMax) || double.IsInfinity(yMax)) { yMax = 0; } // Create the point IntensityInfo info1 = new IntensityInfo(obs.Time, null, obs.Group, yMin); IntensityInfo info2 = new IntensityInfo(obs.Time, null, obs.Group, yMax); MCharting.DataPoint cdp = new MCharting.DataPoint(xVal, new[] { yMin, yMax }); cdp.Tag = new[] { info1, info2 }; series.Points.Add(cdp); } } }
/// <summary> /// Actual plotting. /// </summary> public void Plot(StylisedCluster stylisedCluster) { Debug.WriteLine("ClusterPlot: " + stylisedCluster); // Reset the chart bool isPreview = stylisedCluster != null && stylisedCluster.IsPreview; Cluster p = stylisedCluster != null ? stylisedCluster.Cluster : null; Plot plot = this.PrepareNewPlot(!isPreview, (stylisedCluster != null) ? stylisedCluster.Cluster : null, p?.Assignments.Vectors.FirstOrDefault()?.Source); // Set the selected cluster Dictionary <Peak, LineInfo> colours = stylisedCluster != null ? stylisedCluster.Colours : null; this.SelectedCluster = stylisedCluster; if (stylisedCluster != null) { this.SetCaption(stylisedCluster.CaptionFormat, stylisedCluster.ActualElement, stylisedCluster.WhatIsHighlighted); } else { this.SetCaption("No plot displayed."); } Core core = this._core; CoreColourSettings colourSettings = core.Options.Colours; // If there is nothing to plot then exit if (p == null) { this.CompleteNewPlot(plot); return; } // Sort the variables exemplars top-most List <Assignment> toPlot = new List <Assignment>(p.Assignments.List); // Too much to plot while (toPlot.Count > core.Options.MaxPlotVariables) { //toPlot = toPlot.OrderBy(z => z.Peak.Index).ToList(); toPlot.RemoveRange(core.Options.MaxPlotVariables, toPlot.Count - core.Options.MaxPlotVariables); } int numClusterCentres = 0; HashSet <GroupInfo> groupsInPlot = p.Assignments.Vectors.First().ColHeaders.Unique(z => z.Observation.Group); if (!this._core.Options.DisplayAllGroupsInClusterPlot) { groupsInPlot.RemoveWhere(z => !this._core.Options.ViewTypes.Contains(z)); } GroupInfo[] groupOrder = groupsInPlot.OrderBy(GroupInfoBase.GroupOrderBy).ToArray(); MCharting.Series legendEntry = new MCharting.Series(); legendEntry.Name = "Input vector"; legendEntry.Style.DrawLines = new Pen(Color.Black, this._core.Options.LineWidth * 2); plot.LegendEntries.Add(legendEntry); // --- LEGEND --- var groupLegends = this.DrawLegend(plot, groupOrder); HashSet <MCharting.Series> toBringToFront = new HashSet <MCharting.Series>(); // --- PLOT CLUSTER ASSIGNMENTS --- // Iterate variables in cluster for (int assignmentIndex = 0; assignmentIndex < toPlot.Count; assignmentIndex++) { Assignment assignment = toPlot[assignmentIndex]; Vector vec = assignment.Vector; Peak peak = vec.Peak; Dictionary <GroupInfo, MCharting.Series> vecSeries = new Dictionary <GroupInfo, MCharting.Series>(); Dictionary <GroupInfo, MCharting.Series> vec2Series = new Dictionary <GroupInfo, MCharting.Series>(); MCharting.DataPoint lastPoint = null; MCharting.Series lastSeries = null; /////////////////// // PLOT THE POINT // Okay! Now plot the values pertinent to this peak & type for (int i = 0; i < vec.Count; ++i) { // Peak, by observation ObservationInfo obs = vec.Observations[i]; GroupInfo group = obs.Group; if (!groupOrder.Contains(group)) { continue; } MCharting.Series series = this.GetOrCreateSeries(plot, vecSeries, group, vec, stylisedCluster, groupLegends, legendEntry, toBringToFront, false); // When the series changes we create an intermediate series to join the two together //MCharting.Series seriesb = null; //if (series != lastSeries && lastSeries != null) //{ // seriesb = GetOrCreateSeries(plot, vec2Series, group, vec, stylisedCluster, groupLegends, legendEntry, toBringToFront, true); //} lastSeries = series; int typeOffset = this.GetTypeOffset(groupOrder, group); int x = typeOffset + obs.Time; double v = vec.Values[i]; MCharting.DataPoint dataPoint = new MCharting.DataPoint(x, v); dataPoint.Tag = new IntensityInfo(obs.Time, obs.Rep, obs.Group, v); series.Points.Add(dataPoint); //if (seriesb != null) //{ // seriesb.Points.Add(lastPoint); // seriesb.Points.Add(dataPoint); //} lastPoint = dataPoint; } } // --- PLOT CLUSTER CENTRES --- if (!isPreview && core.Options.ShowCentres && p.Centres.Count != 0 && p.Centres.Count < 100) { MCharting.Series legendEntry2 = new MCharting.Series(); legendEntry2.Name = (p.Centres.Count == 1) ? "Cluster centre" : "Cluster centres"; legendEntry2.Style.DrawLines = new Pen(colourSettings.ClusterCentre, this._core.Options.LineWidth * 2); legendEntry2.Style.DrawLines.DashStyle = DashStyle.Dash; legendEntry2.Style.DrawPoints = new SolidBrush(colourSettings.ClusterCentre); legendEntry2.Style.DrawPointsSize = 8; // MarkerStyle.Diamond; plot.LegendEntries.Add(legendEntry2); var templateAssignment = p.Assignments.List.First(); foreach (double[] centre in p.Centres) { MCharting.Series series = new MCharting.Series(); series.Style.StrictOrder = SeriesStyle.EOrder.X; series.ApplicableLegends.Add(legendEntry2); plot.Series.Add(series); series.Name = "Cluster centre #" + (++numClusterCentres); series.Style.DrawLines = new Pen(colourSettings.ClusterCentre, this._core.Options.LineWidth * 2); series.Style.DrawLines.DashStyle = DashStyle.Dash; series.Style.DrawPoints = new SolidBrush(colourSettings.ClusterCentre); series.Style.DrawPointsSize = 8; // MarkerStyle.Diamond; IEnumerable <int> order = templateAssignment.Vector.Observations.WhichOrder(ObservationInfo.GroupTimeReplicateDisplayOrder); foreach (int index in order) { // Centre, by observation ObservationInfo cond = templateAssignment.Vector.Observations[index]; if (!groupOrder.Contains(cond.Group)) { continue; } double dp = centre[index]; int x = this.GetTypeOffset(groupOrder, cond.Group) + cond.Time; MCharting.DataPoint cdp = new MCharting.DataPoint(x, dp); cdp.Tag = new IntensityInfo(cond.Time, cond.Rep, cond.Group, dp); series.Points.Add(cdp); } } } // Bring highlighted series to the front foreach (MCharting.Series series in toBringToFront) { plot.Series.Remove(series); plot.Series.Add(series); } // --- LABELS --- this.DrawLabels(plot, true, groupOrder, true); // --- COMPLETE --- this.CompleteNewPlot(plot); }