Ticket #2656 (closed: fixed)

Opened 10 years ago

Last modified 5 years ago

Add the ability to interact with curves on an existing plot

Reported by: Nick Draper Owned by: Russell Taylor
Priority: major Milestone: Release 2.0
Component: MantidPlot Keywords:
Cc: Blocked By:
Blocking: Tester: Nick Draper

Description

Lots of this would be useful, but I can see it is a lot, we may have to cherry pick or split into separate tickets.

From QTIplot Handbook:

Working with 2D curves

You can then add or remove curves to or from this layer:

l.insertCurve(table, Ycolumn, type=Layer.Scatter, int startRow = 0, int endRow = -1)# returns a reference to the inserted curve
l.insertCurve(table, Xcolumn, Ycolumn, type=Layer.Scatter, int startRow = 0, int endRow = -1)# returns a reference to the inserted curve
l.addCurve(table, column, type=Layer.Line, lineWidth = 1, symbolSize = 3, startRow = 0, endRow = -1)# returns True on success
l.addCurves(table, (2,4), type=Layer.Line, lineWidth = 1, symbolSize = 3, startRow = 0, endRow = -1)# returns True on success
l.removeCurve(curveName)
l.removeCurve(curveIndex)
l.removeCurve(curveReference)
l.deleteFitCurves()
It is possible to change the order of the curves inserted in a layer using the following function:

l.changeCurveIndex(int oldIndex, int newIndex)
Sometimes, when performing data analysis, one might need the curve title. It is possible to obtain it using the method below:

title = l.curveTitle(curveIndex)
It is possible to get a reference to a curve on the layer l using it's index or it's title, like shown below:

c = l.curve(curveIndex)
c = l.curve(curveTitle)
dc = l.dataCurve(curveIndex)
Please, keep in mind the fact that the above methods might return an
 invalid reference if the curve with the specified index/title is 
not a PlotCurve or a DataCurve object, respectively. For example, an
 analytical function curve is a PlotCurve but not a DataCurve and 
spectrograms are a completely different type of plot items which are
 neither PlotCurves nor DataCurves.

Use the following function to change the axis attachment of a curve:


l.setCurveAxes(number, x-axis, y-axis)
where number is the curve's number, x-axis is either 0 or 1 (bottom or top) and y-axis is either 0 or 1 (left or right).

In case you need the number of curves on a layer, you can get it with

l.numCurves()
Once you have added a curve to a 2D plot, you can fully customize it's appearance:

l = newGraph().activeLayer()
l.setAntialiasing()
c = l.insertCurve(table("Table1"), "Table1_2", Layer.LineSymbols)
c.setPen(QtGui.QPen(Qt.red, 3))
c.setBrush(QtGui.QBrush(Qt.darkYellow))
c.setSymbol(PlotSymbol(PlotSymbol.Hexagon, QtGui.QBrush(Qt.yellow), QtGui.QPen(Qt.blue, 1.5), QtCore.QSize(15, 15)))
It is possible to change the number of symbols to be displayed for a curve using the function below. This option can be very usefull for very large data sets:

c.setSkipSymbolsCount(3)
print c.skipSymbolsCount()
An alternative way of customizing a curve is by using the functions below:

l.setCurveLineColor(int curve, int color) # uses the index of the colors in the default QtiPlot color list: 0 = black, 1 = red, 2 = green, etc...
l.setCurveLineStyle(int curve, Qt::PenStyle style)
l.setCurveLineWidth(int curve, double width)
You can also define a global color policy for the plot layer using the following convenience functions:

l.setGrayScale()
l.setIndexedColors() # uses the colors in the default QtiPlot color list: 0 = black, 1 = red, 2 = green, etc...
You can display labels showing the y values for each data point in a DataCurve:

c.setLabelsColumnName("Table1_2")
c.setLabelsOffset(50, 50)
c.setLabelsColor(Qt.red)
c.setLabelsFont(QtGui.QFont("Arial", 14))
c.setLabelsRotation(45)
c.loadData() # creates the labels and updates the display
and, of course, you can disable them using:

c.clearLabels()
l.replot() # redraw the plot layer object
If you need to change the range of data points displayed in a DataCurve you can use the following methods:

c.setRowRange(int startRow, int endRow)
c.setFullRange()
Also, you can hide/show a plot curve via:

c.setVisible(bool on)
In case you need to get information about the data stored in the curve, you have at your disposal the functions below:

points = c.dataSize()
for i in range (0, points):
	print i, "x = ", c.x(i), "y = ", c.y(i)

print c.minXValue()
print c.maxXValue()
print c.minYValue()
print c.maxYValue()
Curve symbols

Here's how you can customize the plot symbol used for a 2D plot curve c:

s = c.symbol()
s.setSize(QtCore.QSize(7, 7))# or s.setSize(7)
s.setBrush(QtGui.QBrush(Qt.darkYellow))
s.setPen(QtGui.QPen(Qt.blue, 3))
s.setStyle(PlotSymbol.Diamond)
l.replot() # redraw the plot layer object
The symbol styles available in QtiPlot are:
0
PlotSymbol.NoSymbol

1
PlotSymbol.Ellipse

2
PlotSymbol.Rect

3
PlotSymbol.Diamond

4
PlotSymbol.Triangle

5
PlotSymbol.DTriangle

6
PlotSymbol.UTriangle

7
PlotSymbol.LTriangle

8
PlotSymbol.RTriangle

9
PlotSymbol.Cross

10
PlotSymbol.XCross

11
PlotSymbol.HLine

12
PlotSymbol.VLine

13
PlotSymbol.Star1

14
PlotSymbol.Star2

15
PlotSymbol.Hexagon

It is also possible to define a custom image as the plot symbol for a curve:

g = newGraph().activeLayer()
c = g.addFunction("cos(x)", 0, 10, 20)
c.setSymbol(ImageSymbol("qtiplot/manual/html/icons/help.png"))
Here's a short script showing how to draw a custom plot symbol and assign it to a curve:

pix = QtGui.QPixmap(QtCore.QSize(11, 11))
pix.fill(Qt.transparent)
p = QtGui.QPainter(pix)
r = QtCore.QRect(0, 0, 10, 10)
p.drawEllipse(r)
p.setPen(QtGui.QPen(Qt.red))
p.drawLine(5, 0, 5, 10)
p.drawLine(0, 5, 10, 5)
p.end()

g = newGraph().activeLayer()
c = g.addFunction("sin(x)", 0, 10, 20)
c.setSymbol(ImageSymbol(pix))

Change History

comment:1 Changed 9 years ago by Nick Draper

  • Milestone changed from Iteration 28 to Iteration 29

Bulk move of tickets at the end of iteration 28

comment:2 Changed 9 years ago by Nick Draper

  • Milestone changed from Iteration 29 to Iteration 30

"New" tickets moved at the code freeze of iteration 29

comment:3 Changed 9 years ago by Nick Draper

  • Milestone changed from Iteration 30 to Iteration 31

Bulk move of tickets to iteration 31 at the iteration 30 code freeze

comment:4 Changed 9 years ago by Russell Taylor

  • Status changed from new to accepted

comment:5 Changed 9 years ago by Russell Taylor

Add ability to set a curve's symbol, pen & brush via python.

QwtSymbol is exposed as PlotSymbol and allows all aspects of the symbol to be customised. The setCurvePen method acts on the characteristics of the line and offers more advanced options than the setCurveLineColor/Style/Width methods. setCurveBrush acts on the area beneath a curve (e.g. fill colour, style...) Re #2656.

Changeset: f54a051d588704821b07568a685f0f5ce9d15af3

comment:6 Changed 9 years ago by Russell Taylor

Add a Graph::insertCurve overload for adding Mantid curves. Re #2656.

Takes a workspace name and index and adds a 1D curve. Exposed this method to python, along with the overload that takes just the Y column name of a table.

Changeset: fa814ca588355e13c24300fcdca984b7123095a4

comment:7 Changed 9 years ago by Russell Taylor

Later, I'll intercept the insertCurve method so that a reference to workspace can be given instead of (or as well as) the name.

Last edited 9 years ago by Russell Taylor (previous) (diff)

comment:8 Changed 9 years ago by Russell Taylor

Add curveTitle & setCurveAxes to python layer objects. Re #2656.

Changeset: 31754e5cc55e8e76c187844e6a2b8fc82164176d

comment:9 Changed 9 years ago by Russell Taylor

Add the ability to use a custom symbol on a plot. Re #2656.

Seems slightly frivolous, but it was easy so why not. Involved bringing in the ImageSymbol class from today's QtiPlot and exposing to python. A custom symbol can be loaded from an image file or drawn using the QPixmap class.

Changeset: 5a9bd8c84616908d3c629b984a89ed8d5b6bc2ce

comment:10 Changed 9 years ago by Russell Taylor

Indentation fixes only. Re #2656.

Changeset: 2ffcd8ea77f936494b8476297f999697b2c11fc9

comment:11 Changed 9 years ago by Russell Taylor

Indentation/formatting only. Re #2656.

Changeset: b14f31ca337df4e06681a70951cfb57ba9b4f662

comment:12 Changed 9 years ago by Russell Taylor

Add possibility to draw only every n'th symbol on a 1D plot. Re #2656.

Back-ported in from today's QtiPlot.

Changeset: 19e2007c71dc94d75f0d677e60a78475a532e4d4

comment:13 Changed 9 years ago by Russell Taylor

Retain skipped symbols in Mantid curves on reloading a saved project.

Re #2656.

Changeset: b90293339ffe2300c6d19d277a96b5b747854281

comment:14 Changed 9 years ago by Russell Taylor

Indentation/formatting changes only. Re #2656.

Changeset: d9e9c1fa3f62e9520446e8297ca9c392d5824b5f

comment:15 Changed 9 years ago by Russell Taylor

Draw error bars only when symbol is drawn (non-Mantid curves only).

Re #2656. Will address greater control of when error bars are drawn, including for Mantid curves under #2657.

Changeset: aa78ad5c34ca194678e2301c2c5ca56379108148

comment:16 Changed 9 years ago by Russell Taylor

Add setGrayScale & setIndexedColors methods to Graph. Re #2656.

Allows switching all curves on a plot between grayscale and colour. Exposed to python.

Changeset: cebbed0e01455b24c899b2499ba72c91b5f63425

comment:17 Changed 9 years ago by Russell Taylor

Expose arguments on insertCurve that allow plotting only a range...

...of rows from a table. Re #2656.

Changeset: 1130ba4c27e17537656b6fe0e288dbfea3480d06

comment:18 Changed 9 years ago by Russell Taylor

Almost everything in the description has now been implemented, with a few exceptions.

The most notable of these is that I decided not to expose the curve classes themselves. However, most of the actions can be accomplished through calling methods on Graph instead - e.g. l.setCurveSkipSymbolsCount(curveNum,3) instead of c.setSkipSymbolsCount(e).

The following items are missing:

  • Changing a curve's index (l.changeCurveIndex)
  • Showing and customising labels on individual points
  • Changing the range of points (e.g. rows of a table) that are plotted
  • Hiding a curve (except by removing it)
  • Retrieving the data values/min/max of a curve
  • Retaining a custom symbol (from file or 'hand drawn') after saving & reloading a project

I still need to update our wiki documentation before closing this ticket.

comment:19 Changed 9 years ago by Russell Taylor

Have Layer.insertCurve accept a WorkspaceProxy. Re #2656.

Also a bit more pertaining to #1037.

Changeset: 6c05dfba404e7a1f0b6965573c85ad02e6a6a78d

comment:20 Changed 9 years ago by Russell Taylor

  • Status changed from accepted to verify
  • Resolution set to fixed

comment:21 Changed 9 years ago by Russell Taylor

  • Status changed from verify to reopened
  • Resolution fixed deleted

Forgot that I still need to do the documentation.....

comment:22 Changed 9 years ago by Russell Taylor

  • Status changed from reopened to accepted

comment:23 Changed 9 years ago by Nick Draper

  • Milestone changed from Iteration 32 to Iteration 33

Moved to iteration 33 at iteration 32 code freeze

comment:24 Changed 9 years ago by Russell Taylor

  • Milestone changed from Iteration 33 to Iteration 32

comment:25 Changed 9 years ago by Russell Taylor

  • Status changed from accepted to verify
  • Resolution set to fixed

comment:26 Changed 9 years ago by Russell Taylor

A small fix to pass through call. Re #2656.

Changeset: 4be9f43c5ead234ccb30a0805cc3876e87756663

comment:27 Changed 9 years ago by Nick Draper

  • Status changed from verify to verifying
  • Tester set to Nick Draper

comment:28 Changed 9 years ago by Nick Draper

  • Status changed from verifying to closed

Tested on Windows 7 64 bit

particularly liked this one

g = newGraph().activeLayer()
g.addFunction("cos(x)", 0, 10, 20)
g.setCurveSymbol(0, ImageSymbol("C:/Mantid/Documents/Images/Mantid Icon32.gif"))

comment:29 Changed 5 years ago by Stuart Campbell

This ticket has been transferred to github issue 3503

Note: See TracTickets for help on using tickets.