The P1D class is among the central classes of jHepWork. A P1D object is a container which keeps information on a data point in (X,Y) together with 1st and 2nd level errors, which are usually used to show statistical and systematical errors in X and Y. This means that one entry of this container is characterized by 10 double-precision numbers. One single point of this container is illustrated in Figure :autoreffigure3.1.
[width=0.45]p1d.eps
|
The P1D container can be drawn using the same draw() method as for any histogram.
>>> from jhplot import P1D,HPlot >>>> >>> c1=HPlot("Canvas",600,400) >>> c1.visible() >>> c1.setAutoRange() >>> c1.setGTitle("Example of symbols", Color.blue) #put title >>> p1= P1D("show points") >>> for i in range(10): .... p1.add(i*2,i) # fills X and Y >>> c1.draw(p1)As before for F1D and H1D classes, the draw(P1D) method can take arrays of P1D objects.
The example above is not optimized for the speed. If one wants a script which is a factor 10 faster for huge loops, one should first create an array using jhplot.math or any other package, and fill the P1D with the single statement given below:
>>> ... >>> p1= P1D("show points") >>> x=... # create some array with some Java method >>> y=... # create some array with some Java method >>> p1.fill(x,y) # fills X and YIn the example above, all statistical errors are set to zero. If one needs to plot data points with 2-level error bars, use this method:
p1.add(x,y,xLeft,xRight,yUpper,yLower,xLeftSys,xRightSys,yUpperSys,yLowerSys)where xLeft, xRight, yUpper, yLower are the 1st level errors on X and Y, while xLeftSys, xRightSys, yUpperSys, yLowerSys are the 2nd level errors on X and Y.
Of course, in many cases, the full set of errors does not exists or is not known. In this case use this constructor:
p1.add(x,y) # fill X and Y. All errors set to 0which sets all errors on X and Y to be zero.
In case if one needs to specify only symmetrical uncertainties on Y (i.e., for example, statistical errors), then use this method:
p1.add(x,y,error) # fills X, Y and symmetric error on Ywhere error is a statistical error on Y, i.e. yUpper=yLower. All other errors are set to zero. If the error on Y is asymmetric, use this method:
p1.add(x,y,error_up, error_down)where error_up=yUpper and error_down=yLower are the upper and lower error on Y. If there are only 1st-level errors, then one can fill a P1D as:
p1.add(x,y,xLeft,xRight,yUpper,yLower)while the 2nd level errors are set to zero.
Here are several important methods associated with the P1D class:
>>> p1.setStyle("p") # set style ``p''- symbols, ``l'' - lines >>> p1.setColor(Color.red) # sets symbol color >>> p1.setSymbolSize(int) # sets symbol size >>> p1.setSymbol(int) # sets symbol typeOne can edit the plot using a pop-up menu Edit in order to set all object attributes using the style editor. Look at an example located in macros/examples/points1.py.
There are many methods which come together with the P1D data holder to display error bars, assuming that error values have been filled before. To display errors, use:
>>> p1.setErr(true) # true for 1st level errors >>> p1.setErrSys(true) # true for 2nd level errorsThere are two separate methods to control horizontal and vertical error bars:
>>> p1.setErrX(boolean) # set true or 1 (jython) >>> p1.setErrY(boolean) >>> p1.setErrColorX(Color) # indicate color used for X error bars >>> p1.setErrColorY(Color) # indicate color used for Y error bars >>> p1.setPenWidthErr(int) # pen width for 1st level errors >>> p1.setPenWidthErrSys(int)# pen width for 2nd level errorsTo control 2nd-level errors, use:
>>> p1.setErrSysX(boolean) # set or not 2nd level error >>> p1.setErrSysY(boolean)One can draw a filled area which spans 1st level error bars (i.e. statistical errors) with the following statements:
>>> p1.setErrFill(boolean) # fill or nor the area >>> p1.setErrFillColor(Color) # fill color >>> p1.setErrFillColor(Color, double) # same + transparency levelHere Color is the color used to fill the area and the second argument is the transparency level (from 0 to 1). For example, p1.fillErrorsColor(Color.green,0.5) will fill green area with
To fill an area which spans the 2nd level error bars use:
>>> p1.setErrSysFill(boolean) # fill or not 2nd level errors >>> p1.setErrSysFillColor(Color) # fill color >>> p1.setErrSysColor(Color, double) # same + transparency
The HPlot canvas can be used to display a P1D data in a form of a contour plot. To do this, use the method setContour(1) of the HPlot class:
>>> c1.setContour(boolean) # sets or not a contor style to HPlot >>> c1.setContourLevels(n) # n - number of color levels >>> c1.setContourBins(nX,nY) # number of bins in X and Y >>> c1.setContourBar(boolean) # set or not a color line >>> c1.setContourGray(boolean) # set or not white-black styleOne can find an example in contour.py file in the macros/examples directory. It should be noted that it is also possible to use the HPlot3D class to show data in 3D as well as in a contour plot.
One can initiate a P1D using data from an external file:
>>> from jhplot import P1D,HPlot >>> >>> c1=HPlot("Canvas",600,400) >>> c1.visible(1) >>> c1.setAutoRange() >>> p1=P1D("show points", "data.d") # fill P1D from a file >>> c1.draw(p1)where data.d is a file with data points. The file can contain statistical and systematical errors. As can be seen, unlike many graphical packages, one needs only a few lines to create a plot from a file with the name data.d! Please look at the example examples/points2.py.
It should be mentioned that this is the preferred way to fill a P1D from a file. The speed of the execution is about 10 times faster than if the user opens a file, reads numbers and uses add() method to add rows to a P1D object using the Jython syntax.
One can construct a P1D from a H1D histogram as:
>>> p1.P1D("New name",h1) # convert H1D to P1D >>> p1.P1D(h1) # convert H1D to P1D, keep the same titleIt should be noted that X values are given by the weighted mean in each histogram bin (not by the center of the bin). The values on Y are the sum of the weights of the histogram. The errors on X, as well as all 2nd level errors on X and Y are set to zero.
One can write a file with the P1D data as:
>>> p1=P1D("show points", "data.d") >>> p1.toFile("newfile.d")where newfile.d is a file name. It should be mentioned that this is the preferred way for the P1D output to a file. The speed of the execution is about 10 times faster than if the user open a file, and write numbers raw-by-raw using Jython.
One can also export the data to a LaTeX table as
>>> format=DecimalFormat("##.####E00") >>> p4.toFileAsLatex("Output.tex",xformat,xformat)One should specify an appropriate format for the numbers in the LaTeX table. Also, one can print a P1D container on the Linux console as
>>> p1.print()In some cases, it is convenient to show data as a table in a separate frame, so one can sort and search for a particular value. In this case, use
>>> p1.toTable()This method calls the class HTable which is discussed in Section :autorefsection3.22. Analogously, the data can be exported to a spreadsheet which is also discussed in Section :autorefsection3.22.
One can access P1D values as:
>>> p1=P1D("show points", "data.d") >>> p1.size() # size of the data >>> p1.clear() # clear the P1D >>> p1.getMin(int) # min value for axis=0,1,.. >>> p1.getMax(int) # max value for axis=0,1,.. >>> p1.mean() # mean value >>> p1.setTitle(String) # set a new title >>> p1.getTitle(String) # get a new title >>> p1.getX(i) # x value at position i >>> p1.getY(i) # y value at position i >>> p1.getXleft(i) # left error on x at position i >>> p1.getXright(i) # right error on x at position i >>> p1.getXleftSys(i) # left 2nd-level error on x at position i >>> p1.getXrightSys(i) # right 2nd-level error on x at position i >>> p1.getYupper(i) # upper error on y at position i >>> p1.getYlower(i) # lower error on y at position i >>> p1.getYupperSys(i) # upper 2nd-level error on y at position i >>> p1.getYlowerSys(i) # lowert 2nd-level error on y at position iThe 2nd-level error is usually used to show systematical uncertainty on a data point. Except for size(), all methods return double precision numbers. Use Jython statement type() to find out which type of value is returned.
As for H1D, all operations with the P1D class do not create new objects after modifications. All operations just modify the original object. If you want to create a new P1D object, use copy() method. Usually, all operations return the same (but modified) objects. Here are examples:
>>> # assume that p1 was created >>> p2=p1.copy() # p2 is different P1D object now >>> c1.draw(p1) # draw 2 different objects >> c1.draw(p2)
If there are two P1D containers, one can use the following operations:
>>> p1=P1D("first", "data1.d") >>> p2=P1D("second", "data2.d") >>> p3=p1.merge(p2) # merge 2 containers into p3 >>> p1.oper(p2,"New Title","+") # add p1 and p2 >>> p3=p1.oper(p2,"New Title","+") # also OK, but p3 is the same as modified p1. >>> p1.oper(p2,"New Title","-") # subtract p2 from p1 >>> p1.oper(p2,"New Title","*") # multiply p1 by p2 >>> p1.oper(p2,"New Title","/") # divide p1 by p2This is the preferred way for the P1D output to a file, as the speed of such operations is close to the corresponding C++/Java programs.
One can skip the string with a new title if you want to keep the same title as for the original P1D. For example, in this case, the additive operation will be p3=p1.oper(p2,"+"). The errors on p3 will be propagated assuming that all uncertainties associated with p1 and p2 are independent (for 1st and 2nd levels). All graphical attributes are preserved during the manipulations.
To scale P1D, use a similar statement:
>>> p3=p1.operScale("New Title", int axis, scaleFactor )where scaleFactor is a double or an integer number. If axis=0, the scaling is applied for X, if axis=1, the scaling is applied for Y. The title string is optional. The scale factor scales only values in Y and associated uncertainties on Y (i.e. 1st and 2nd levels). If you need to scale only errors, use:
>>> p3=p1.operScaleErr("New Title", int axis, scaleFactor)this scales only 1st level errors on either X (axis=0) or Y (axis=1). If the user needs to scale also 2nd level errors, he/she should use:
>>> p3=p1.operScaleErrSys("New Title", int axis, scaleFactor)which works exactly as operScaleErr but for 2nd level errors.
The operations above assume that there are no correlations between the P1D data holders. However, one can also specify correlation coefficients. Read the jHPlot API for more details. Look at the example below:
# fill data set 1 points with 2 points >>> p1= P1D("data1") # use only statistical errors on Y >>> p1.add(10,100,5,5) >>> p1.add(20,50,5,5) # fill data set 2 with 2 points >>> p2= P1D("data2") # use only statistical errors on Y >>> p2.add(10,40,5,5) >>> p2.add(20,40,5,5) # add with 50% correlations # build a data holder with correlation coefficient >>> corr=P1D("correlation coefficients") >>> corr.add(0,0,0.5,0.5) >>> corr.add(0,0,0.5,0.5) # add them. Do not do anything with X >>> corr.oper(p2,"added with 50% corr.","+","Y",corr)One can also transform a P1D data holder using some function with the error propagation for either "X" or "Y" component or both. One can do it as:
>>> p1=p1.move("function", "axis" )where function is exp(), log(), sqrt(), cos(), sin() etc. (see the API for more details). Axis is "X" (move only X values), "Y" (move only Y values), or "XY" (move both). For example:
>>> p1=p1.move("log", "Y" )will transform all "Y" values to log(Y) including the errors associated with them.
One can also calculate a weighted average from several P1D data containers using this method:
>>> p1.addAndAverage(P1D[])This method adds an array of P1D objects to the original P1D class and returns a weighted average based on statistical errors on Y (i.e. 1st-level errors).
To extract a range of P1D points from the original, use
>>> p1=p1.range(min,max) # min and max index for the rangeTo get index with either minimum or maximum values, use:
>>> p1=p1.getMinIndex() # index with min >>> p1=p1.getMaxIndex() # index with max
Using the P1D class, it is easy to evaluate systematical uncertainties of many measurements using only a few lines of jHepWork code. If there are several measurements with different resulting outcomes, and each measurement is represented by a P1D data holder, one can get P1D representing the final measurements using the method getSys(), which returns a P1D object with systematical uncertainties.
>>> p0= P1D("default") # original measurement >>> pp=[] >>> p1= P1D("data1") # below are other measurements.. >>> pp.append(p1) >>> p2= P1D("data2") >>> pp.append(p2) >>> p3= P1D("data3") >>> pp.append(p3) >>> .... >>> psys=p0.getSys(pp) # now "psys" includes syst. uncertainties >>> psys.setErr(1) >>> c1.draw(psys)It should be noted that systematical uncertainties are added in quadrature (i.e. it is assumed that they are independent of each other).
Often, you have 3 measurements or calculations, thus one P1D represents central values, and two others represent lower and upper deviations. One can build a new P1D with 2nd level errors represented by the differences between the central P1D and upper and lower P1D as:
>>> pCentral= P1D("default") # original measurement >>> pUpper= P1D("data1") # upper values >>> pLower= P1D("data2") # lower values >>> # fill all 3 objects here .. >>> p0=pCentral.operErrY("new",pUpper,pLower) # P1D with new 2nd level errors on Y >>> p0.setErr(1) >>> c1.draw(p0)This will plot p0 object with new second level errors given by the difference between the pCentral values and values given by pUpper and pLower values. Similarly, you can do the same with errors on X if you use operErrX() method.