/// <summary> /// Get the names of the x and y column of the active plot. /// </summary> /// <param name="ctrl">The current active graph controller.</param> /// <returns>An array of two strings. The first string is the name of the x-column, the second /// the name of the y-column.</returns> public static string[] GetActivePlotName(Altaxo.Graph.GUI.GraphController ctrl) { string[] result = new string[2] { String.Empty, String.Empty }; IGPlotItem plotItem = ctrl.ActiveLayer.PlotItems.Flattened[ctrl.CurrentPlotNumber]; XYColumnPlotItem xyPlotItem = plotItem as XYColumnPlotItem; if (xyPlotItem == null) { return(result); } XYColumnPlotData data = xyPlotItem.XYColumnPlotData; if (data == null) { return(result); } result[0] = data.XColumn.FullName; result[1] = data.YColumn.FullName; return(result); }
private IGPlotItem CreatePlotItem(string tablename, string columnname) { // create a new plotassociation from the column // first, get the y column from table and name Data.DataTable tab = Current.Project.DataTableCollection[tablename]; if (null != tab) { Data.DataColumn ycol = tab[columnname]; if (null != ycol) { Data.DataColumn xcol = tab.DataColumns.FindXColumnOf(ycol); XYColumnPlotItem result; if (null == xcol) { result = new XYColumnPlotItem(new XYColumnPlotData(new Altaxo.Data.IndexerColumn(), ycol), new G2DPlotStyleCollection(LineScatterPlotStyleKind.Scatter)); } else { result = new XYColumnPlotItem(new XYColumnPlotData(xcol, ycol), new G2DPlotStyleCollection(LineScatterPlotStyleKind.LineAndScatter)); } return(result); } } return(null); }
/// <summary> /// Moves the cross to the next plot item. If no plot item is found in this layer, it moves the cross to the next layer. /// </summary> /// <param name="increment"></param> void MoveUpDown(int increment) { if (!TestMovementPresumtions()) { return; } int numlayers = _grac.Layers.Count; int nextlayer = _LayerNumber; int nextplotitemnumber = this._PlotItemNumber; XYScatterPointInformation scatterPoint = null; XYColumnPlotItem plotitem = null; do { nextplotitemnumber = this._PlotItemNumber + Math.Sign(increment); if (nextplotitemnumber < 0) { nextlayer -= 1; nextplotitemnumber = nextlayer < 0 ? int.MaxValue : _grac.Layers[nextlayer].PlotItems.Flattened.Length - 1; } else if (nextplotitemnumber >= _grac.Layers[nextlayer].PlotItems.Flattened.Length) { nextlayer += 1; nextplotitemnumber = 0; } // check if this results in a valid information if (nextlayer < 0 || nextlayer >= numlayers) { break; } if (nextplotitemnumber < 0 || nextplotitemnumber >= _grac.Layers[nextlayer].PlotItems.Flattened.Length) { continue; } plotitem = _grac.Layers[nextlayer].PlotItems.Flattened[nextplotitemnumber] as XYColumnPlotItem; if (null == plotitem) { continue; } scatterPoint = plotitem.GetNextPlotPoint(_grac.Layers[nextlayer], this._PlotIndex, 0); } while(scatterPoint == null); if (null != scatterPoint) { this.m_PlotItem = plotitem; this._LayerNumber = nextlayer; this._PlotItemNumber = nextplotitemnumber; this._PlotIndex = scatterPoint.PlotIndex; this._RowIndex = scatterPoint.RowIndex; ShowCross(scatterPoint); } }
/// <summary> /// Plots selected data columns of a table. /// </summary> /// <param name="table">The source table.</param> /// <param name="selectedColumns">The data columns of the table that should be plotted.</param> /// <param name="graph">The graph document to plot into.</param> /// <param name="templatePlotStyle">The plot style which is the template for all plot items.</param> /// <param name="groupStyles">The group styles for the newly built plot item collection.</param> public static IGraphController Plot(DataTable table, IAscendingIntegerCollection selectedColumns, Graph.Gdi.GraphDocument graph, G2DPlotStyleCollection templatePlotStyle, PlotGroupStyleCollection groupStyles) { List <IGPlotItem> pilist = CreatePlotItems(table, selectedColumns, templatePlotStyle); // now create a new Graph with this plot associations Altaxo.Graph.GUI.IGraphController gc = Current.ProjectService.CreateNewGraph(graph); // Set x and y axes according to the first plot item in the list if (pilist.Count > 0 && (pilist[0] is XYColumnPlotItem)) { XYColumnPlotItem firstitem = (XYColumnPlotItem)pilist[0]; if (firstitem.Data.XColumn is TextColumn) { gc.Doc.Layers[0].LinkedScales.SetScale(0, new Graph.Scales.TextScale()); } else if (firstitem.Data.XColumn is DateTimeColumn) { gc.Doc.Layers[0].LinkedScales.SetScale(0, new Graph.Scales.DateTimeScale()); } if (firstitem.Data.YColumn is TextColumn) { gc.Doc.Layers[0].LinkedScales.SetScale(1, new Graph.Scales.TextScale()); } else if (firstitem.Data.YColumn is DateTimeColumn) { gc.Doc.Layers[0].LinkedScales.SetScale(1, new Graph.Scales.DateTimeScale()); } } PlotItemCollection newPlotGroup = new PlotItemCollection(gc.Doc.Layers[0].PlotItems); foreach (IGPlotItem pi in pilist) { newPlotGroup.Add(pi); } if (groupStyles != null) { newPlotGroup.GroupStyles = groupStyles; } else { newPlotGroup.CollectStyles(newPlotGroup.GroupStyles); } gc.Doc.Layers[0].PlotItems.Add(newPlotGroup); return(gc); }
/// <summary> /// Handles the MouseDown event when the plot point tool is selected /// </summary> /// <param name="e">The mouse event args</param> public override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { base.OnMouseDown(e); PointF mouseXY = new PointF(e.X, e.Y); PointF graphXY = _grac.PixelToPrintableAreaCoordinates(mouseXY); // search for a object first IHitTestObject clickedObject; int clickedLayerNumber = 0; _grac.FindGraphObjectAtPixelPosition(mouseXY, true, out clickedObject, out clickedLayerNumber); if (null != clickedObject && clickedObject.HittedObject is XYColumnPlotItem) { m_PlotItem = (XYColumnPlotItem)clickedObject.HittedObject; PointF[] transXY = new PointF[] { graphXY }; Matrix inv = clickedObject.Transformation.Clone(); inv.Invert(); inv.TransformPoints(transXY); XYScatterPointInformation scatterPoint = m_PlotItem.GetNearestPlotPoint(clickedObject.ParentLayer, transXY[0]); this._PlotItemNumber = GetPlotItemNumber(clickedLayerNumber, m_PlotItem); this._LayerNumber = clickedLayerNumber; if (null != scatterPoint) { this._PlotIndex = scatterPoint.PlotIndex; this._RowIndex = scatterPoint.RowIndex; // convert this layer coordinates first to PrintableAreaCoordinates PointF printableCoord = clickedObject.ParentLayer.LayerToGraphCoordinates(scatterPoint.LayerCoordinates); m_Cross = printableCoord; m_Cross.X += _grac.Doc.PrintableBounds.X; m_Cross.Y += _grac.Doc.PrintableBounds.Y; PointF newPixelCoord = _grac.PrintableAreaToPixelCoordinates(printableCoord); Cursor.Position = new Point((int)(Cursor.Position.X + newPixelCoord.X - mouseXY.X), (int)(Cursor.Position.Y + newPixelCoord.Y - mouseXY.Y)); this.DisplayData(m_PlotItem, scatterPoint.RowIndex, m_PlotItem.XYColumnPlotData.XColumn[scatterPoint.RowIndex], m_PlotItem.XYColumnPlotData.YColumn[scatterPoint.RowIndex]); // here we shoud switch the bitmap cache mode on and link us with the AfterPaint event // of the grac _grac.RepaintGraphArea(); // no refresh necessary, only invalidate to show the cross } } } // end of function
/// <summary> /// Find the plot item number of a given plot item. /// </summary> /// <param name="layernumber"></param> /// <param name="plotitem"></param> /// <returns></returns> int GetPlotItemNumber(int layernumber, XYColumnPlotItem plotitem) { if (layernumber < _grac.Doc.Layers.Count) { for (int i = 0; i < _grac.Doc.Layers[layernumber].PlotItems.Flattened.Length; i++) { if (object.ReferenceEquals(_grac.Doc.Layers[layernumber].PlotItems.Flattened[i], plotitem)) { return(i); } } } return(-1); }
/// <summary> /// Find the plot item number of a given plot item. /// </summary> /// <param name="layer">The layer in which this plot item resides.</param> /// <param name="plotitem">The plot item for which the number should be retrieved.</param> /// <returns></returns> private int GetPlotItemNumber(XYPlotLayer layer, XYColumnPlotItem plotitem) { if (null != layer) { for (int i = 0; i < layer.PlotItems.Flattened.Length; i++) { if (object.ReferenceEquals(layer.PlotItems.Flattened[i], plotitem)) { return(i); } } } return(-1); }
/// <summary> /// Handles the MouseDown event when the plot point tool is selected /// </summary> /// <param name="position">Mouse position.</param> /// <param name="e">The mouse event args</param> public override void OnMouseDown(PointD2D position, MouseButtonEventArgs e) { base.OnMouseDown(position, e); var graphXY = _grac.ConvertMouseToRootLayerCoordinates(position); _grac.FindGraphObjectAtPixelPosition(position, true, out var clickedObject, out var clickedLayerNumber); if (null != clickedObject && clickedObject.HittedObject is XYColumnPlotItem) { _PlotItem = (XYColumnPlotItem)clickedObject.HittedObject; var transXY = clickedObject.Transformation.InverseTransformPoint(graphXY); _layer = (XYPlotLayer)(clickedObject.ParentLayer); XYScatterPointInformation scatterPoint = _PlotItem.GetNearestPlotPoint(_layer, transXY); _PlotItemNumber = GetPlotItemNumber(_layer, _PlotItem); if (null != scatterPoint) { _PlotIndex = scatterPoint.PlotIndex; _RowIndex = scatterPoint.RowIndex; // convert this layer coordinates first to PrintableAreaCoordinates var rootLayerCoord = clickedObject.ParentLayer.TransformCoordinatesFromHereToRoot(scatterPoint.LayerCoordinates); _positionOfCrossInRootLayerCoordinates = rootLayerCoord; // m_Cross.X -= _grac.GraphViewOffset.X; // m_Cross.Y -= _grac.GraphViewOffset.Y; var newPixelCoord = _grac.ConvertGraphToMouseCoordinates(rootLayerCoord); // TODO (Wpf) //var newCursorPosition = new Point((int)(Cursor.Position.X + newPixelCoord.X - mouseXY.X),(int)(Cursor.Position.Y + newPixelCoord.Y - mouseXY.Y)); //SetCursorPos(newCursorPosition.X, newCursorPosition.Y); DisplayData(_PlotItem, scatterPoint.RowIndex, _PlotItem.XYColumnPlotData.XColumn[scatterPoint.RowIndex], _PlotItem.XYColumnPlotData.YColumn[scatterPoint.RowIndex]); // here we shoud switch the bitmap cache mode on and link us with the AfterPaint event // of the grac _grac.RenderOverlay(); // no refresh necessary, only invalidate to show the cross } } } // end of function
/// <summary> /// Retrieves the data points of the current active plot. /// </summary> /// <param name="ctrl">The graph controller which controls the graph from which the points are to retrieve.</param> /// <param name="xarr">The array of the data point's x values.</param> /// <param name="yarr">The array of the data point's y values.</param> /// <param name="nPlotPoints">The number of plot points (may be smaller than the length of x and y arrays.</param> /// <returns>Null if all is ok, or error message if not.</returns> public static string GetActivePlotPoints(Altaxo.Graph.GUI.GraphController ctrl, ref double[] xarr, ref double[] yarr, out int nPlotPoints) { nPlotPoints = 0; ctrl.EnsureValidityOfCurrentLayerNumber(); ctrl.EnsureValidityOfCurrentPlotNumber(); IGPlotItem plotItem = ctrl.ActiveLayer.PlotItems.Flattened[ctrl.CurrentPlotNumber]; XYColumnPlotItem xyPlotItem = plotItem as XYColumnPlotItem; if (xyPlotItem == null) { return("No active plot!"); } XYColumnPlotData data = xyPlotItem.XYColumnPlotData; if (data == null) { return("Active plot item has no data"); } if (!(data.XColumn is Altaxo.Data.INumericColumn) || !(data.YColumn is Altaxo.Data.INumericColumn)) { return("X-Y values of plot data are not both numeric"); } Altaxo.Data.INumericColumn xcol = (Altaxo.Data.INumericColumn)data.XColumn; Altaxo.Data.INumericColumn ycol = (Altaxo.Data.INumericColumn)data.YColumn; int n = data.PlottablePoints; if (null == xarr || xarr.Length < n) { xarr = new double[n]; } if (null == yarr || yarr.Length < n) { yarr = new double[n]; } int end = data.PlotRangeEnd; int j = 0; for (int i = data.PlotRangeStart; i < end && j < n; i++) { double x = xcol[i]; double y = ycol[i]; if (double.IsNaN(x) || double.IsNaN(y)) { continue; } xarr[j] = x; yarr[j] = y; ++j; } nPlotPoints = j; return(null); }
public static string Fit(Altaxo.Graph.GUI.GraphController ctrl) { if (ctrl.CurrentPlotNumber < 0) { return("No active plot!"); } IGPlotItem plotItem = ctrl.ActiveLayer.PlotItems.Flattened[ctrl.CurrentPlotNumber]; XYColumnPlotItem xyPlotItem = plotItem as XYColumnPlotItem; if (xyPlotItem == null) { return("Active plot is not a X-Y Plot!"); } INumericColumn xColumn = xyPlotItem.XYColumnPlotData.XColumn as INumericColumn; INumericColumn yColumn = xyPlotItem.XYColumnPlotData.YColumn as INumericColumn; if (xColumn == null) { return("The x-column is not numeric"); } if (yColumn == null) { return("The y-column is not numeric"); } Calc.Regression.Nonlinear.NonlinearFitDocument localdoc = ctrl.Doc.GetGraphProperty(FitDocumentPropertyName) as Calc.Regression.Nonlinear.NonlinearFitDocument; if (localdoc == null) { if (_lastFitDocument == null) { localdoc = new Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument(); } else { localdoc = (Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument)_lastFitDocument.Clone(); } } if (localdoc.FitEnsemble.Count == 0) { Calc.Regression.Nonlinear.FitElement fitele = new Altaxo.Calc.Regression.Nonlinear.FitElement( xColumn, yColumn, xyPlotItem.XYColumnPlotData.PlotRangeStart, xyPlotItem.XYColumnPlotData.PlotRangeLength); localdoc.FitEnsemble.Add(fitele); } else // localdoc.FitEnsemble.Count>0 { localdoc.FitEnsemble[0].SetIndependentVariable(0, xColumn); localdoc.FitEnsemble[0].SetDependentVariable(0, yColumn); localdoc.FitEnsemble[0].SetRowRange(xyPlotItem.XYColumnPlotData.PlotRangeStart, xyPlotItem.XYColumnPlotData.PlotRangeLength); } localdoc.FitContext = ctrl; object fitdocasobject = localdoc; if (true == Current.Gui.ShowDialog(ref fitdocasobject, "Non-linear fitting")) { // store the fit document in the graphs property ctrl.Doc.SetGraphProperty(FitDocumentPropertyName, localdoc); _lastFitDocument = (Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument)localdoc.Clone(); } return(null); }
/// <summary> /// Gets a new or recycled fit document for a given plot item <see cref="XYColumnPlotItem"/>. /// </summary> /// <param name="xyPlotItem">The xy plot item.</param> /// <param name="ctrl">The control.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">xyPlotItem</exception> private static Tuple <string, NonlinearFitDocument, string, XYPlotLayer> GetNewFitDocumentFor(XYColumnPlotItem xyPlotItem, Altaxo.Gui.Graph.Gdi.Viewing.IGraphController ctrl) { if (null == xyPlotItem) { throw new ArgumentNullException(nameof(xyPlotItem)); } var activeLayer = Altaxo.Main.AbsoluteDocumentPath.GetRootNodeImplementing <XYPlotLayer>(xyPlotItem); var xColumn = xyPlotItem.XYColumnPlotData.XColumn; var yColumn = xyPlotItem.XYColumnPlotData.YColumn; if (xColumn == null || xColumn.ItemType != typeof(double)) { return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>("The x-column is not numeric", null, null, activeLayer)); } if (yColumn == null || yColumn.ItemType != typeof(double)) { return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>("The y-column is not numeric", null, null, activeLayer)); } var localdoc = (ctrl.Doc.GetGraphProperty(FitDocumentPropertyName) as Calc.Regression.Nonlinear.NonlinearFitDocument) ?? (Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument)_lastFitDocument?.Clone() ?? new Altaxo.Calc.Regression.Nonlinear.NonlinearFitDocument(); if (localdoc.FitEnsemble.Count == 0) // if there was no fit before { var fitele = new Altaxo.Calc.Regression.Nonlinear.FitElement( xyPlotItem.Data.DataTable, xyPlotItem.Data.GroupNumber, xyPlotItem.Data.DataRowSelection, xColumn, yColumn); localdoc.FitEnsemble.Add(fitele); } else // there was a fit before, thus localdoc.FitEnsemble.Count>0 { bool hasColumnsChanged = false; hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].DataTable, xyPlotItem.Data.DataTable)); hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].GroupNumber, xyPlotItem.Data.GroupNumber)); hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].IndependentVariables(0), xColumn)); hasColumnsChanged |= !(object.ReferenceEquals(localdoc.FitEnsemble[0].DependentVariables(0), yColumn)); localdoc.FitEnsemble[0].SetIndependentVariable(0, xColumn); localdoc.FitEnsemble[0].SetDependentVariable(0, yColumn); if (hasColumnsChanged) // if some of the columns has changed, take the data row selection of the plot item { localdoc.FitEnsemble[0].DataRowSelection = xyPlotItem.Data.DataRowSelection; } } return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>(string.Empty, localdoc, null, activeLayer)); }
private static Tuple <string, NonlinearFitDocument, string, XYPlotLayer> SelectFitDocument(Gui.Graph.Gdi.Viewing.IGraphController ctrl, XYColumnPlotItem columnPlotItem) { if (null == columnPlotItem) { throw new ArgumentNullException(nameof(columnPlotItem)); } var activeLayer = Altaxo.Main.AbsoluteDocumentPath.GetRootNodeImplementing <XYPlotLayer>(columnPlotItem); DataColumn columPlotItemDataColumn = columnPlotItem.Data.YColumn.GetUnderlyingDataColumnOrDefault(); if (null != columPlotItemDataColumn) { // try to find a nonlinear function plot item whose dependent variable equals to the y of the column plot item foreach (var funcItem in TreeNodeExtensions.TakeFromHereToFirstLeaves((IGPlotItem)activeLayer.PlotItems).OfType <XYNonlinearFitFunctionPlotItem>()) { if (object.ReferenceEquals(columPlotItemDataColumn, funcItem.DependentVariableColumn.GetUnderlyingDataColumnOrDefault())) { return(new Tuple <string, NonlinearFitDocument, string, XYPlotLayer>(string.Empty, funcItem.FitDocumentCopy, funcItem.FitDocumentIdentifier, activeLayer)); } } } // Get a new fit document from the selected xy plot item return(GetNewFitDocumentFor(columnPlotItem, ctrl)); }
/// <summary> /// Moves the cross to the next plot item. If no plot item is found in this layer, it moves the cross to the next layer. /// </summary> /// <param name="increment"></param> private void MoveUpDown(int increment) { if (!TestMovementPresumtions()) { return; } var layerList = _layer.SiblingLayers; int numlayers = layerList.Count; var nextlayer = _layer as XYPlotLayer; int indexOfNextLayer = layerList.IndexOf(_layer); int nextplotitemnumber = _PlotItemNumber; XYScatterPointInformation scatterPoint = null; XYColumnPlotItem plotitem = null; do { nextplotitemnumber = nextplotitemnumber + Math.Sign(increment); if (nextplotitemnumber < 0) // then try to use the previous layer { --indexOfNextLayer; nextlayer = indexOfNextLayer >= 0 ? layerList[indexOfNextLayer] as XYPlotLayer : null; nextplotitemnumber = nextlayer == null ? int.MaxValue : nextlayer.PlotItems.Flattened.Length - 1; } else if (nextplotitemnumber >= nextlayer.PlotItems.Flattened.Length) { ++indexOfNextLayer; nextlayer = indexOfNextLayer < layerList.Count ? layerList[indexOfNextLayer] as XYPlotLayer : null; nextplotitemnumber = 0; } // check if this results in a valid information if (indexOfNextLayer < 0 || indexOfNextLayer >= numlayers) { break; // no more layers available } if (nextlayer == null) { continue; // this is not an XYPlotLayer } if (nextplotitemnumber < 0 || nextplotitemnumber >= nextlayer.PlotItems.Flattened.Length) { continue; } plotitem = nextlayer.PlotItems.Flattened[nextplotitemnumber] as XYColumnPlotItem; if (null == plotitem) { continue; } scatterPoint = plotitem.GetNextPlotPoint(nextlayer, _PlotIndex, 0); } while (scatterPoint == null); if (null != scatterPoint) { _PlotItem = plotitem; _layer = nextlayer; _PlotItemNumber = nextplotitemnumber; _PlotIndex = scatterPoint.PlotIndex; _RowIndex = scatterPoint.RowIndex; ShowCross(scatterPoint); } }