<?xml version="1.0" encoding="UTF-8"?>

<title>Mathematical Expressions and Scripting</title>

  <para>QtiPlot supports two different interpreters
  for evaluating mathematical expressions and for executing scripts:
  <emphasis>muParser</emphasis> and <emphasis>Python</emphasis>.
  <emphasis>muParser</emphasis> can be only used for the evaluation of mathematical expressions,
  whereas <emphasis>Python</emphasis> can be used to execute scrips.
  The default interpreter is <emphasis>muParser</emphasis> therefore if you want to execute scripts you should first
  enable the <emphasis>Python</emphasis> scripting engine via the
  <link linkend="script-language-cmd">Scripting language dialog</link>.
  Also, you can define the default scripting interpreter via the <emphasis>General</emphasis> tab
  of the <link linkend="fig-preferences-dialog-1">Preferences dialog</link>.</para>

  <sect1 id="sec-muParser">
    <title>muParser</title>

    <para>The constants _e=e=E and _pi=pi=PI=Pi are defined, as well as the
    following fundamental physical constants, operators and functions.
    Please note that the fundamental constants cannot be redefined.
    Doing so will raise an error message.</para>

    <table frame="sides" pgwide="1" tocentry="1">
      <title>muParser: Predefined Fundamental Physical Constants</title>

      <tgroup cols="2">
        <colspec align="left" colname="name" colwidth="1*" />

        <colspec align="justify" colname="description" colwidth="10*" />

        <thead>
          <row>
            <entry>Name</entry>

            <entry>Description</entry>
          </row>
        </thead>

        <tbody>
          <row>
            <entry>c</entry>

            <entry>The speed of light in vacuum</entry>
          </row>

          <row>
            <entry>eV</entry>

            <entry>The energy of 1 electron volt</entry>
          </row>

          <row>
            <entry>g</entry>

            <entry>The standard gravitational acceleration on Earth</entry>
          </row>

          <row>
            <entry>G</entry>

            <entry>The gravitational constant</entry>
          </row>

          <row>
            <entry>h</entry>

            <entry>Planck's constant</entry>
          </row>

          <row>
            <entry>hbar</entry>

            <entry>Planck's constant divided by 2 pi</entry>
          </row>

          <row>
            <entry>k</entry>

            <entry>The Boltzmann constant</entry>
          </row>

          <row>
            <entry>Na</entry>

            <entry>Avogadro's number</entry>
          </row>

          <row>
            <entry>R0</entry>

            <entry>The molar gas constant</entry>
          </row>

          <row>
            <entry>V0</entry>

            <entry>The standard gas volume</entry>
          </row>

          <row>
            <entry>Ry</entry>

            <entry>The Rydberg constant, in units of energy</entry>
          </row>
        </tbody>
      </tgroup>
    </table>

    <table frame="sides" pgwide="1" tocentry="1">
      <title>muParser: Supported Mathematical Operators</title>

      <tgroup cols="2">
        <colspec align="left" colname="name" colwidth="1*" />

        <colspec align="justify" colname="description" colwidth="10*" />

        <thead>
          <row>
            <entry>Name</entry>

            <entry>Description</entry>
          </row>
        </thead>

        <tbody>
          <row>
            <entry>+</entry>

            <entry>Addition</entry>
          </row>

          <row>
            <entry>-</entry>

            <entry>Subtraction</entry>
          </row>

          <row>
            <entry>*</entry>

            <entry>Multiplication</entry>
          </row>

          <row>
            <entry>/</entry>

            <entry>Division</entry>
          </row>

          <row>
            <entry>^</entry>

            <entry>Exponentiation (raise a to the power of b)</entry>
          </row>

          <row>
            <entry>and</entry>

            <entry>logical and (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>or</entry>

            <entry>logical or (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>xor</entry>

            <entry>logical exclusive or (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>&lt;</entry>

            <entry>less then (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>&lt;=</entry>

            <entry>less then or equal (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>==</entry>

            <entry>equal (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>&gt;=</entry>

            <entry>greater then or equal (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>&gt;</entry>

            <entry>greater then (returns 0 or 1)</entry>
          </row>

          <row>
            <entry>!=</entry>

            <entry>not equal (returns 0 or 1)</entry>
          </row>
        </tbody>
      </tgroup>
    </table>

      <table frame="sides" pgwide="1" tocentry="1">
        <title>muParser: Mathematical Functions</title>

        <tgroup cols="2">
          <colspec align="left" colname="name" colwidth="1*" />

          <colspec align="justify" colname="description" colwidth="10*" />

          <thead>
            <row>
              <entry>Name</entry>

              <entry>Description</entry>
            </row>
          </thead>

          <tbody>
            <row>
              <entry>abs(x)</entry>

              <entry>absolute value of x</entry>
            </row>

            <row>
              <entry>acos(x)</entry>

              <entry>inverse cosine</entry>
            </row>

            <row>
              <entry>acosh(x)</entry>

              <entry>inverse hyperbolic cosine</entry>
            </row>

            <row>
              <entry>asin(x)</entry>

              <entry>inverse sine</entry>
            </row>

            <row>
              <entry>asinh(x)</entry>

              <entry>inverse hyperbolic sine</entry>
            </row>

            <row>
              <entry>atan(x)</entry>

              <entry>inverse tangent</entry>
            </row>

            <row>
              <entry>atanh(x)</entry>

              <entry>inverse hyperbolic tangent</entry>
            </row>

            <row>
              <entry>avg(x1,x2,x3,...)</entry>

              <entry>average value, this command accept a list of arguments
              separated by commas</entry>
            </row>

            <row>
              <entry>bessel_j0(x)</entry>

              <entry>Regular cylindrical Bessel function of zeroth order,
              J<subscript>0</subscript>(x).</entry>
            </row>

            <row>
              <entry>bessel_j1(x)</entry>

              <entry>Regular cylindrical Bessel function of first order,
              J<subscript>1</subscript>(x).</entry>
            </row>

            <row>
              <entry>bessel_jn(x,n)</entry>

              <entry>Regular cylindrical Bessel function of
              n<superscript>th</superscript> order,
              J<subscript>n</subscript>(x).</entry>
            </row>

            <row>
              <entry>bessel_y0(x)</entry>

              <entry>Irregular cylindrical Bessel function of zeroth order,
              Y<subscript>0</subscript>(x) for x&gt;0.</entry>
            </row>

            <row>
              <entry>bessel_y1(x)</entry>

              <entry>Irregular cylindrical Bessel function of first order,
              Y<subscript>1</subscript>(x) for x&gt;0.</entry>
            </row>

            <row>
              <entry>bessel_yn(x,n)</entry>

              <entry>Irregular cylindrical Bessel function of
              n<superscript>th</superscript> order,
              Y<subscript>n</subscript>(x) for x&gt;0.</entry>
            </row>

            <row>
              <entry>beta (a,b)</entry>

              <entry>Computes the Beta Function, B(a,b) =
              Gamma(a)*Gamma(b)/Gamma(a+b) for a &gt; 0 and b &gt; 0.</entry>
            </row>

            <row>
              <entry>cos(x)</entry>

              <entry>cosine of x</entry>
            </row>

            <row>
              <entry>cosh(x)</entry>

              <entry>hyperbolic cosine of x</entry>
            </row>

            <row>
              <entry>erf(x)</entry>

              <entry>error function of x</entry>
            </row>

            <row>
              <entry>erfc(x)</entry>

              <entry>Complementary error function erfc(x) = 1 -
              erf(x).</entry>
            </row>

            <row>
              <entry>erfz(x)</entry>

              <entry>The Gaussian probability density function Z(x).</entry>
            </row>

            <row>
              <entry>erfq(x)</entry>

              <entry>The upper tail of the Gaussian probability function
              Q(x).</entry>
            </row>

            <row>
              <entry>exp(x)</entry>

              <entry>Exponential function: e raised to the power of x.</entry>
            </row>

            <row>
              <entry>gamma(x)</entry>

              <entry>Computes the Gamma function, subject to x not being a
              negative integer</entry>
            </row>

            <row>
              <entry>gammaln(x)</entry>

              <entry>Computes the logarithm of the Gamma function, subject to
              x not a being negative integer. For x&lt;0, log(|Gamma(x)|) is
              returned.</entry>
            </row>

            <row>
              <entry>hazard(x)</entry>

              <entry>Computes the hazard function for the normal distribution
              h(x) = erfz(x)/erfq(x).</entry>
            </row>

            <row>
              <entry>ln(x)</entry>

              <entry>natural logarithm of x</entry>
            </row>

            <row>
              <entry>log(x)</entry>

              <entry>decimal logarithm of x</entry>
            </row>

            <row>
              <entry>log2(x)</entry>

              <entry>base 2 logarithm of x</entry>
            </row>

            <row>
              <entry>min(x1,x2,x3,...)</entry>

              <entry>Minimum of the list of arguments</entry>
            </row>

            <row>
              <entry>max(x1,x2,x3,...)</entry>

              <entry>Maximum of the list of arguments</entry>
            </row>

            <row>
              <entry>rint(x)</entry>

              <entry>Round to nearest integer.</entry>
            </row>

            <row>
              <entry>sign(x)</entry>

              <entry>Sign function: -1 if x&lt;0; 1 if x&gt;0.</entry>
            </row>

            <row>
              <entry>sin(x)</entry>

              <entry>sine of x</entry>
            </row>

            <row>
              <entry>sinh(x)</entry>

              <entry>hyperbolic sine of x</entry>
            </row>

            <row>
              <entry>sqrt(x)</entry>

              <entry>square root of x</entry>
            </row>

            <row>
              <entry>tan(x)</entry>

              <entry>tangent of x</entry>
            </row>

            <row>
              <entry>tanh(x)</entry>

              <entry>hyperbolic tangent of x</entry>
            </row>
          </tbody>
        </tgroup>
      </table>

      <table frame="sides" pgwide="1" tocentry="1">
        <title>muParser: Non-Mathematical Functions</title>

        <tgroup cols="2">
          <colspec align="left" colname="name" colwidth="1*" />

          <colspec align="justify" colname="description" colwidth="10*" />

          <thead>
            <row>
              <entry>Name</entry>

              <entry>Description</entry>
            </row>
          </thead>

          <tbody>
            <row>
              <entry>cell(a,b)</entry>

				  <entry>In the context of a matrix, returns the value at row a and column b.
					  In the context of a table, returns the value at column a and row b (remember that tables use column logic).
					  Everywhere else, this function is undefined.
				  </entry>
            </row>

            <row>
              <entry>col(c)</entry>

				  <entry>Only works in the context of a table.
					  Returns the value at column c and row i (the current row) in the context table.
					  c can either be the column's number, or its name in doublequotes.
				  </entry>
            </row>

            <row>
              <entry>if(e1,e2,e3)</entry>

              <entry>if e1 is true, e2 is executed else e3 is
              executed.</entry>
            </row>

            <row>
              <entry>tablecol(t,c)</entry>

				  <entry>Only works in the context of a table.
					  Returns the value at column c and row i (the current row) in the table t.
					  t is the table's name in doublequotes, c is either the column's number or its name in doublequotes.
				  </entry>
            </row>
          </tbody>
        </tgroup>
      </table>
  </sect1>

  <sect1 id="Python">
    <title>Python</title>

    <para>This module provides bindings to the <ulink
    url="http://www.python.org">Python</ulink> programming language. Basic
    usage in the context of QtiPlot will be discussed below, but for more
    in-depth information on the language itself, please refer to its excellent
    <ulink url="http://www.python.org/doc">documentation</ulink>.</para>

    <sect2 id="Python-init">
      <title>The Initialization File</title>

      <para>This file allows you to customize the Python environment, import
      modules and define functions and classes that will be available in all
      of your projects. The default initialization file shipped with QtiPlot
      imports Python's <link linkend="Python-functions">standard math
      functions</link> as well as (if available) special functions from
      <ulink url="http://www.scipy.org">SciPy</ulink>, the symbolic mathematics
      library <ulink url="http://www.sympy.org/">SymPy</ulink>
      and helper functions for <ulink url="http://rpy.sourceforge.net/rpy2.html">RPy2</ulink>.
      Also, it creates some handy shortcuts, like
      <userinput>table("table1")</userinput> for
      <userinput>qti.app.table("table1")</userinput>.</para>

      <para>When activating Python support, QtiPlot searches the initialization file in a
	  default folder, which can be customized via the <emphasis>File Locations</emphasis> tab
  	  of the <link linkend="fig-preferences-dialog-13">Preferences dialog</link>.
	  If the initialization file is not found, QtiPlot will issue a warning and
	  <emphasis>muParser</emphasis> will be kept as the default interpreter.</para>

      <para>Files ending in .pyc are compiled versions of the .py source files
      and therefore load a bit faster. The compiled version will be used if
      the source file is older or nonexistent. Otherwise, QtiPlot will try to
      compile the source file (if you've got write permissions for the output
      file).</para>
    </sect2>

    <sect2>
      <title>Python Basics</title>

      <para>Mathematical expressions work largely as expected. However,
      there's one caveat, especially when switching from muParser (which has
      been used exclusively in previous versions of QtiPlot):
      <userinput>a^b</userinput> does not mean "raise a to the power of b" but
      rather "bitwise exclusive or of a and b"; Python's power operator is **.
      Thus: <screen width="40">
<userinput>2^3 # read: 10 xor 11 = 01</userinput>
<computeroutput>#&gt; 1</computeroutput>
<userinput>2**3</userinput>
<computeroutput>#&gt; 8</computeroutput>
</screen></para>

      <para>One thing you have to know when working with Python is that
      indentation is very important. It is used for grouping (most other
      languages use either braces or keywords like
      <userinput>do...end</userinput> for this). For example, <programlisting
      width="40">
x=23
for i in (1,4,5):
	x=i**2
	print(x)
	</programlisting> will do what you would expect: it prints out the numbers 1, 16 and
      25; each on a line of its own. Deleting just a bit of space will change
      the functionality of your program: <programlisting>
x=23
for i in (1,4,5):
	x=i**2
print(x)
	</programlisting> will print out only one number - no, not 23, but rather 25. This
      example was designed to also teach you something about variable scoping:
      There are no block-local variables in Python.  All statements outside of any function
      use module scope; that is, variables attached to one column script or script window.
      All statements inside a function use that function's "local" scope, but they can also
      read module variables.  System-wide globals are stored in the special variable
      <varname>globals</varname>.  To store your own:<programlisting
      width="40">
globals.mydata = 5
print globals.mydata
      </programlisting><link linkend="Python-Scope-Changes">Global scope rules recently changed</link>  In older versions, write this instead:<programlisting>
global mydata
mydata = 5
print mydata
      </programlisting></para>
    </sect2>

    <sect2 id="Python-def">
      <title>Defining Functions and Control Flow</title>

      <para>The basic syntax for defining a function (for use within one
      particular note, for example) is <programlisting>
def answer():
	return 42
	</programlisting> If you want your function to be accessible from other modules,
      you have to add it to the <varname>globals</varname>: <programlisting
      width="40">
def answer():
	return 42
globals.answer = answer
	</programlisting> If you have an older versions of QtiPlot, you have to
      declare it global before the definition: <programlisting
      width="40">
global answer
def answer():
	return 42
	</programlisting> You can add your own function to QtiPlot's function list. We'll
      also provide a documentation string that will show up, for example, in
      the "set column values" dialog: <programlisting>
def answer():
	"Return the answer to the ultimate question about life, the universe and everything."
	return 42
qti.mathFunctions["answer"] = answer
	</programlisting> If you want to remove a function from the list, do: <programlisting
      width="40">
del qti.mathFunctions["answer"]
	</programlisting></para>

      <para><link linkend="Python-Scope-Changes">Global scope rules recently changed</link>
      In older versions, a function's local scope hid the module scope. That means that if
      you entered a function definition in a Note, you would not be able to
      access (neither reading nor writing) Note-local variables from within
      the function. However, you could access global variables as usual.</para>

      <para>If-then-else decisions are entered as follows: <programlisting>
if x&gt;23:
	print(x)
else:
	print("The value is too small.")
	</programlisting></para>

      <para>You can do loops, too: <programlisting>
for i in range(1, 11):
	print(i)
	</programlisting> This will print out the numbers between 1 and 10 inclusively (the
      upper limit does not belong to the range, while the lower limit
      does).</para>
    </sect2>

    <sect2 id="Python-functions">
      <title>Mathematical Functions</title>

      <para>Python comes with some basic mathematical functions that are
      automatically imported (if you use the <link
      linkend="Python-init">initialization file</link> shipped with QtiPlot).
      Along with them, the constants e (Euler's number) and pi (the one and
      only) are defined.</para>

      <table frame="sides" pgwide="1" tocentry="1">
        <title>Python: Supported Mathematical Functions</title>

        <tgroup cols="2">
          <colspec align="left" colname="name" colwidth="1*" />

          <colspec align="justify" colname="description" colwidth="10*" />

          <thead>
            <row>
              <entry>Name</entry>

              <entry>Description</entry>
            </row>
          </thead>

          <tbody>
            <row>
              <entry>acos(x)</entry>

              <entry>inverse cosine</entry>
            </row>

            <row>
              <entry>asin(x)</entry>

              <entry>inverse sine</entry>
            </row>

            <row>
              <entry>atan(x)</entry>

              <entry>inverse tangent</entry>
            </row>

            <row>
              <entry>atan2(y,x)</entry>

              <entry>equivalent to atan(y/x), but more efficient</entry>
            </row>

            <row>
              <entry>ceil(x)</entry>

              <entry>ceiling; smallest integer greater or equal to x</entry>
            </row>

            <row>
              <entry>cos(x)</entry>

              <entry>cosine of x</entry>
            </row>

            <row>
              <entry>cosh(x)</entry>

              <entry>hyperbolic cosine of x</entry>
            </row>

            <row>
              <entry>degrees(x)</entry>

              <entry>convert angle from radians to degrees</entry>
            </row>

            <row>
              <entry>exp(x)</entry>

              <entry>Exponential function: e raised to the power of x.</entry>
            </row>

            <row>
              <entry>fabs(x)</entry>

              <entry>absolute value of x</entry>
            </row>

            <row>
              <entry>floor(x)</entry>

              <entry>largest integer smaller or equal to x</entry>
            </row>

            <row>
              <entry>fmod(x,y)</entry>

              <entry>remainder of integer division x/y</entry>
            </row>

            <row>
              <entry>frexp(x)</entry>

              <entry>Returns the tuple (mantissa,exponent) such that
              x=mantissa*(2**exponent) where exponent is an integer and 0.5
              &lt;=abs(m)&lt;1.0</entry>
            </row>

            <row>
              <entry>hypot(x,y)</entry>

              <entry>equivalent to sqrt(x*x+y*y)</entry>
            </row>

            <row>
              <entry>ldexp(x,y)</entry>

              <entry>equivalent to x*(2**y)</entry>
            </row>

            <row>
              <entry>log(x)</entry>

              <entry>natural (base e) logarithm of x</entry>
            </row>

            <row>
              <entry>log10(x)</entry>

              <entry>decimal (base 10) logarithm of x</entry>
            </row>

            <row>
              <entry>modf(x)</entry>

              <entry>return fractional and integer part of x as a
              tuple</entry>
            </row>

            <row>
              <entry>pow(x,y)</entry>

              <entry>x to the power of y; equivalent to x**y</entry>
            </row>

            <row>
              <entry>radians(x)</entry>

              <entry>convert angle from degrees to radians</entry>
            </row>

            <row>
              <entry>sin(x)</entry>

              <entry>sine of x</entry>
            </row>

            <row>
              <entry>sinh(x)</entry>

              <entry>hyperbolic sine of x</entry>
            </row>

            <row>
              <entry>sqrt(x)</entry>

              <entry>square root of x</entry>
            </row>

            <row>
              <entry>tan(x)</entry>

              <entry>tangent of x</entry>
            </row>

            <row>
              <entry>tanh(x)</entry>

              <entry>hyperbolic tangent of x</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
    </sect2>

    <sect2 id="Python-API">
      <title>Accessing QtiPlot's objects from Python</title>

      <para>We will assume that you are using the <link
      linkend="Python-init">initialization file</link> shipped with
      QtiPlot. Accessing the objects in your project is straight-forward,
<programlisting>
t = table("Table1")
m = matrix("Matrix1")
g = graph("Graph1")
p = plot3D("Graph2")
n = note("Notes1")
# get a pointer to the QTextEdit object used to display information in the results log window:
log = resultsLog()
# display some information in the data display toolbar:
displayInfo(text)
# get a pointer to the QLineEdit object in the data display toolbar and access the information displayed:
info = infoLineEdit()
text = info.text()
</programlisting> as is creating new objects: <programlisting>
# create an empty table named "tony" with 5 rows and 2 columns:
t = newTable("tony", 5, 2)
# use defaults
t = newTable()
# create an empty matrix named "gina" with 42 rows and 23 columns:
m = newMatrix("gina", 42, 23)
# use defaults
m = newMatrix()
# create an empty graph window
g = newGraph()
# create a graph window named "test" with two layers disposed on a 2 rows x 1 column grid
g = newGraph("test", 2, 2, 1)
# create an empty 3D plot window with default title
p = newPlot3D()
# create an empty note named "momo"
n = newNote("momo")
# use defaults
n = newNote()
</programlisting>The currently selected Table/Matrix etc. can be accessed with the following commands:
<programlisting>
t = currentTable()
m = currentMatrix()
g = currentGraph()
n = currentNote()
</programlisting>
The functions will only return a valid object if a window of the wanted type is actually selected.
You can check if the object is valid with a simple if clause:
<programlisting>if isinstance(t,qti.Table): print "t is a table"</programlisting></para>
<para>Every piece of code is executed in the context of an
object which you can access via the <varname>self</varname> variable. For example,
entering <userinput>self.cell("t",i)</userinput> as a column formula is equivalent to the convenience
function <userinput>col("t")</userinput>.</para>

Once you have established contact with a MDI window, you can modify some of its properties, like the name, the window label, the geometry, etc..
For example, here's how to rename a window, change its label and the way they are displayed in the window title bar, the so called caption policy:
<programlisting>
t = table("Table1")
setWindowName(t, "toto")
t.setWindowLabel("tutu")
t.setCaptionPolicy(MDIWindow.Both)
</programlisting>
The caption policy can have one of the following values:
	<orderedlist>
        <listitem>
          Name <para>the window caption is determined by the window name</para>
        </listitem>
        <listitem>
          Label<para>the caption is determined by the window label</para>
        </listitem>
        <listitem>
          Both<para>caption = "name - label"</para>
        </listitem>
      </orderedlist>

You can access the name or label of a window by using the <userinput>objectName()</userinput> and <userinput>windowLabel()</userinput> functions.

Here's how you can access and modify the geometry of a window in the project:
<programlisting>
t = table("Table1")
t.setGeometry(10, 10, 800, 600)
print t.x(), t.y(), t.width(), t.height()
</programlisting>

For a fast editing process, you can create template files from existing tables, matrices or plots. The templates can be used later on in order to create customized windows very easily:
<programlisting>
saveAsTemplate(graph("Graph1"), "my_plot.qpt")
g = openTemplate("my_plot.qpt")
</programlisting>

Also, you can easily clone a MDI window:
<programlisting>
g1 = clone(graph("Graph1"))
</programlisting>

If you want to delete a project window, you can use the <userinput>close()</userinput> method.
You might want to deactivate the confirmation message, first:
<programlisting>
w.confirmClose(False)
w.close()
</programlisting>

All QtiPlot subwindows are displayed in a QMdiArea. You can get a pointer to this object
via the <userinput>workspace()</userinput> method. This can be particularly usefull if you need to customize the
behavior of the workspace via your scripts. Here follows a small example script that
pops-up a message displaying the name of the active MDI subwindow each time a new window is activated:
<programlisting>
def showMessage():
	QtGui.QMessageBox.about(qti.app, "", workspace().activeSubWindow().objectName())

QtCore.QObject.connect(workspace(), QtCore.SIGNAL("subWindowActivated(QMdiSubWindow *)"), showMessage)
</programlisting>

</sect2>

<sect2 id="Python-Folders">
<title>Project Folders</title>
Storing your data tables/matrices and your plots in folders can be very convenient and helpful
when you're analyzing loads of data files in the same project.
New objects will always be added to the active folder. You can get a pointer to it via:
<programlisting>
f = activeFolder()
</programlisting>
The functions table, matrix, graph and note will start searching in the active folder and, failing this,
will continue with a depth-first recursive search of the project's root folder, given by:
<programlisting>
f = rootFolder()
</programlisting>
In order to access subfolders and windows, there are the following functions:
<programlisting>
f2 = f.folders()[number]
f2 = f.folder(name, caseSensitive=True, partialMatch=False)
t = f.table(name, recursive=False)
m = f.matrix(name, recursive=False)
g = f.graph(name, recursive=False)
n = f.note(name, recursive=False)
</programlisting>
If you supply True for the recursive argument, a depth-first recursive search of all subfolders will
be performed and the first match returned.
<para>New folders can be created using:</para>
<programlisting>
newFolder = addFolder("New Folder", parentFolder = 0)
</programlisting>
If the <varname>parentFolder</varname> is not specified, the new folder will be added as a subfolder of the project's
root folder. When you create a new folder via a Python script, it doesn't automatically become the active folder
of the project. You have to set this programatically, using:
<programlisting>
changeFolder(newFolder, bool force=False)
</programlisting>
Folders can be deleted using:
<programlisting>
deleteFolder(folder)
</programlisting>
You can save a folder as a project file, and of course, you can also save the whole project:
<programlisting>
saveFolder(folder, "new_file.qti", compress=False)
saveProjectAs("new_file_2.qti", compress=False)
</programlisting>
If <varname>compress</varname> is set to True, the project file will be archived to the .gz format, using zlib.
<para>Also, you can load a QtiPlot or an Origin project file into a new folder.
The new folder will have the base name of the project file and will be added as a subfolder
to the <varname>parentFolder</varname> or to the current folder if no parent folder is specified.</para>
<programlisting>
newFolder = appendProject("projectName", parentFolder = 0)
</programlisting>
If you don't want to be asked for confirmation when a table/matrix is renamed during this operation,
or when deleting a folder via a Python script, you must change your preferences
concerning prompting of warning messages, using the <link linkend="fig-preferences-dialog-2">Preferences dialog ("Confirmations" tab)</link>.

<para>
Folders store their own log information containing the results
of the analysis operations performed on the child windows. This information
is updated in the result log window each time you change the active folder
in the project. You can access and manipulate these log strings via the following functions:
<programlisting>
text = folder.logInfo()
folder.appendLogInfo("Hello!")
folder.clearLogInfo()
</programlisting>
</para>
</sect2>

<sect2 id="Python-Tables">
<title>Working with Tables</title>
We'll assume that you have assigned some table to the variable
<varname>t</varname>. You can access its numeric cell values with
<programlisting>
t.cell(col, row)
# and
t.setCell(col, row, value)
</programlisting>
<para>
Whenever you have to specify a column, you can use either the
column name (as a string) or the consecutive column number (starting
with 1). Row numbers also start with 1, just as they are displayed.
In many places there is an alternative API which represents a table
as a Python sequence is provided. Here rows are addressed by Python
indices or slices which start at 0. These places are marked as such.
</para>

If you want to work with arbitrary texts or the textual representations
of numeric values, you can use:
<programlisting>
t.text(col, row)
# and
t.setText(col, row, string)
</programlisting>
An alternative way to get/set the value of a cell is using the format of the column (Text, Numeric, ...).
Qtiplot handles all the casting under the hood and throws an <varname>TypeError</varname> if this isn't possible.
Assigning <varname>None</varname> will clear the cell's value.
The column type Day-of-Week returns/accepts the numbers 1 (monday) to 7 (sunday, for which also 0 is accepted).
The column type Month returns/accepts the numbers 1 to 12.
The column type Date returns/accepts <varname>datetime.datetime</varname> objects and also accepts a <varname>QDateTime</varname>.
The column type Time returns/accepts <varname>datetime.time</varname> objects and also accepts a <varname>QTime</varname>.
<programlisting>
t.cellData(col, row)
# and
t.setCellData(col, row, value)
</programlisting>
The number of columns and rows is accessed via:
<programlisting>
t.numRows() # same as len(t)
t.numCols()
t.setNumRows(number)
t.setNumCols(number)
</programlisting>

You can add a new column at the end of the table or you can insert new columns before a
<varname>startColumn</varname> using the functions below:
<programlisting>
t.addColumn()
t.insertColumns(startColumn, count)
</programlisting>
Adding an empty row at the end of the table is done with the <varname>addRow()</varname> method.
It returns the new row number.
<programlisting>
newRowIndex = t.addRow()
</programlisting>

If you need all the data of a row or column you can use the <varname>rowData()</varname>
and <varname>colData()</varname> methods. This is much faster then iterating manually over the cells.
Alternatively you can use the <varname>[]</varname> operator in combination with Python indices or slices,
which start at 0.
<programlisting>
valueList = t.colData(col) # col may be a string or a number starting at 1
rowTuple = t.rowData(row) # row number starting at 1
rowTuple = t[idx] # row index starts at 0
rowTupleList = t[slice]
</programlisting>

A Table is iterable. The data is returned row wise as tuple.
<programlisting>
for c1, c2, c3 in t:
  # do stuff, assuming t has three columns
</programlisting>

It is possible to assign random or normal random values to a complete column or to a subset of rows in a column:
<programlisting>
	t.setRandomValues(col, startRow = 1, endRow = -1)
	t.setNormalRandomValues(col, startRow = 1, endRow = -1, standardDeviation = 1.0)
</programlisting>

Assigning values to a complete row or column is also possible.
While the new row data has to be a tuple which length must match the column number,
column data just has to be iteratable. If the iterator stops before the end of the table
is reached, a <varname>StopIteration</varname> exception is raised.
In combination with the <varname>offset</varname> this allows to fill a column chunk wise.
A positive offset starts filling the column after this row number.
A negative offset ignores the firsts values of the iterator.
<programlisting>
t.setColData(col, iterableValueSequence, offset=0)
# just fill the first column with a list of values, staring at row 6
t.setColData(1, [12,23,34,56,67], 5)
# fill the second column with Fibonacci numbers, omitting the first three.
def FibonacciGenerator():
  a, b = 1, 1
  while True:
    a, b = b, a+b
    yield a
t.setColData(2, FibonacciGenerator(), -3)
t.setRowData(row, rowTuple) # row starts at 1
# assuming t has exactly two columns...
t.setRowData(2, (23, 5)) # fill the second row
t[1] = 23, 5 # using a Python index, starting at 0
# adding a new row and set it's values
t.appendRowData(rowTuple)
</programlisting>

You can set the format of a column to text using:
<programlisting>
t.setColTextFormat(col)
</programlisting>

Or you can adjust the numeric format:
<programlisting>
t.setColNumericFormat(col, format, precision, update=True)
</programlisting>
were <varname>col</varname> is the number of the column to adjust and <varname>precision</varname> states the number of digits.
The <varname>format</varname> can be one of the following:
<variablelist spacing="compact">
            <varlistentry>
              <term>Table.Default (0)</term>
              <listitem>
                <para>standard format</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>Table.Decimal (1)</term>
              <listitem>
                <para>decimal format with <varname>precision</varname> digits</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>Table.Scientific (2)</term>
              <listitem>
                <para>scientific format</para>
              </listitem>
            </varlistentry>
</variablelist>

In the same way you can set a column hold a date. Here the text of a cell is interpreted using a format string:
<programlisting>
t.setColDateFormat(col, format, update=True)
t.setColDateFormat("col1", "yyyy-MM-dd HH:mm")
</programlisting>
were <varname>col</varname> is the name/number of a column and <varname>format</varname> the format string.
In this string, the following placeholder are recognized:
<variablelist spacing="compact">
            <varlistentry>
              <term>d</term>
              <listitem>
                <para>the day as number without a leading zero (1 to 31)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>dd</term>
              <listitem>
                <para>the day as number with a leading zero (01 to 31)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>ddd</term>
              <listitem>
                <para>the abbreviated localized day name (e.g. 'Mon' to 'Sun')</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>dddd</term>
              <listitem>
                <para>the long localized day name (e.g. 'Monday' to 'Sunday')</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>M</term>
              <listitem>
                <para>the month as number without a leading zero (1-12)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>MM</term>
              <listitem>
                <para>the month as number with a leading zero (01-12)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>MMM</term>
              <listitem>
                <para>the abbreviated localized month name (e.g. 'Jan' to 'Dec')</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>MMMM</term>
              <listitem>
                <para>the long localized month name (e.g. 'January' to 'December')</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>yy</term>
              <listitem>
                <para>the year as two digit number (00-99)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>yyyy</term>
              <listitem>
                <para>the year as four digit number</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>h</term>
              <listitem>
                <para>the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>hh</term>
              <listitem>
                <para>the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>H</term>
              <listitem>
                <para>the hour without a leading zero (0 to 23, even with AM/PM display)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>HH</term>
              <listitem>
                <para>the hour with a leading zero (00 to 23, even with AM/PM display)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>m</term>
              <listitem>
                <para>the minute without a leading zero (0 to 59)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>mm</term>
              <listitem>
                <para>the minute with a leading zero (00 to 59)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>s</term>
              <listitem>
                <para>the second without a leading zero (0 to 59)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>ss</term>
              <listitem>
                <para>the second with a leading zero (00 to 59)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>z</term>
              <listitem>
                <para>the milliseconds without leading zeroes (0 to 999)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>zzz</term>
              <listitem>
                <para>the milliseconds with leading zeroes (000 to 999)</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>AP or A</term>
              <listitem>
                <para>interpret as an AM/PM time. AP must be either "AM" or "PM".</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>ap or a</term>
              <listitem>
                <para>interpret as an AM/PM time. ap must be either "am" or "pm".</para>
              </listitem>
            </varlistentry>
</variablelist>

Analog you can say that a text column should hold a time only...
<programlisting>
t.setColTimeFormat(col, format, update=True)
t.setColTimeFormat(1, "HH:mm:ss")
</programlisting>

... a month ...
<programlisting>
t.setColMonthFormat(col, format, update=True)
t.setColMonthFormat(1, "M")
</programlisting>
Here the format is the following:
<variablelist spacing="compact">
            <varlistentry>
              <term>M</term>
              <listitem>
                <para>Only the first letter of the month, i.e. "J"</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>MMM</term>
              <listitem>
                <para>The short form, like "Jan"</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>MMMM</term>
              <listitem>
                <para>The full name, "January"</para>
              </listitem>
            </varlistentry>
</variablelist>

... or the day of week:
<programlisting>
t.setColDayFormat(col, format, update=True)
t.setColDayFormat(1, "ddd")
</programlisting>
Here the format is the following:
<variablelist spacing="compact">
            <varlistentry>
              <term>d</term>
              <listitem>
                <para>Only the first letter of the day, i.e. "M"</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>ddd</term>
              <listitem>
                <para>The short form, like "Mon"</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>dddd</term>
              <listitem>
                <para>The full name, "Monday"</para>
              </listitem>
            </varlistentry>
</variablelist>

It is also possible to swap two columns using:
<programlisting>
t.swapColumns(column1, column2)
</programlisting>

You can delete a column or a range of rows using the functions below:
<programlisting>
t.removeCol(number)
t.deleteRows(startRowNumber, endRowNumber)
</programlisting>
It is also possible to use Python's <varname>del</varname> statement to remove rows.
Note that in this case a Python index or slice (instead of row numbers) is used, which start at 0.
<programlisting>
del t[5] # deletes row 6
del t[0:4] # deletes row 1 to 5
</programlisting>

Column names can be read and written with:
<programlisting>
t.colName(number)
t.colNames()
t.setColName(col, newName, enumerateRight=False)
t.setColNames(newNamesList)
</programlisting>
If <varname>enumerateRight</varname> is set to True, all the table columns starting from index
<varname>col</varname> will have their names modified to a combination of the
<varname>newName</varname> and a numerical increasing index. If this parameter is not specified,
by default it is set to False.
The plural forms get/set all headers at once.

<para>You can change the plot role of a table column (abscissae, ordinates, error bars, etc...) using:</para>
<programlisting>
t.setColumnRole(col, role)
</programlisting>
where <varname>role</varname> specifies the desired column role:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Table.None</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Table.X</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Table.Y</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>3.</term>
              <listitem>
                <para>Table.Z</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>4.</term>
              <listitem>
                <para>Table.xErr</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>5.</term>
              <listitem>
                <para>Table.yErr</para>
              </listitem>
            </varlistentry>
			<varlistentry>
              <term>6.</term>
              <listitem>
                <para>Table.Label</para>
              </listitem>
            </varlistentry>
</variablelist>

<para>You can normalize a single column or all columns in a table:</para>
<programlisting>
t.normalize(col)
t.normalize()
</programlisting>
Sort a single or all columns:
<programlisting>
t.sortColumn(col, order = 0)
t.sort(type = 0, order = 0, leadingColumnName)
</programlisting>

<sect3 id = "Python-ImportASCII">
<title>Import ASCII files</title>

Import values from <varname>file</varname>, using <varname>sep</varname> as separator char, ignoring
<varname>ignoreLines</varname> lines at the head of the file and all lines starting with a <varname>comment</varname> string.
<programlisting>
t.importASCII(file, sep="\t",ignoreLines=0,renameCols=False,stripSpaces=True,simplifySpace=False,
importComments=False,comment="#",readOnly=False,importAs=Table.Overwrite,locale=QLocale(),endLine=0,maxRows=-1)
</programlisting>

As you see from the above list of import options, you have the possibility to set the new columns as read-only.
This will prevent the imported data from being modified. You have the possibility to remove this protection
at any time, by using:
<programlisting>
t.setReadOnlyColumn(col, False)
</programlisting>

<para>The <varname>importAs</varname> flag can have the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Table.NewColumns: data values are added as new columns.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Table.NewRows: data values are added as new rows.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Table.Overwrite: all existing values are overwritten (default value).</para>
              </listitem>
            </varlistentry>
</variablelist></para>

<para>The <varname>endLine</varname> flag specifies the end line character convention used in the ascii file.
Possible values are: 0 for line feed (LF), which is the default value,
1 for carriage return + line feed (CRLF) and 2 for carriage return only (usually on Mac computers).</para>

<para>The last parameter <varname>maxRows</varname> allows you to specify a maximum number of imported
lines. Negative values mean that all data lines must be imported.</para>

<para>If the decimal separator of the imported file does not match the currently used conventions, you have to
adjust them before using the table:</para>
<programlisting>
t.setDecimalSeparators(country,ignoreGroupSeparator=True)
</programlisting>
<para>Where country can have one of the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Use the system value</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Use the following format: 1,000.00</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Use the following format: 1.000,00</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>3.</term>
              <listitem>
                <para>Use the following format: 1 000,00</para>
              </listitem>
            </varlistentry>
</variablelist></para>
</sect3>

<sect3 id = "Python-ImportExcel">
<title>Importing Excel sheets</title>

<para>It is possible to import a sheet from an Excel .xls file <varname>file</varname> to a table, using:</para>
<programlisting>
t = importExcel(file, sheet)
</programlisting>
<para>If the integer <varname>sheet</varname> variable is not specified, all non-empty sheets in the Excel workbook are imported
 into separate tables and a reference to the table containing the data from the last sheet is returned.</para>
</sect3>

<sect3 id = "Python-ImportODF">
<title>Importing ODF spreadsheets</title>

<para>It is possible to import a sheet from an ODF spreadsheet .ods <varname>file</varname> to a table, using:</para>
<programlisting>
t = importOdfSpreadsheet(file, sheet)
</programlisting>
<para>If the integer <varname>sheet</varname> variable is not specified, all non-empty sheets in the spreadsheet are imported
 into separate tables and a reference to the table containing the data from the last sheet is returned.</para>
</sect3>

<sect3 id = "Python-ExportTables">
<title>Export Tables</title>

<para>You can export values from a table to an ASCII <varname>file</varname>, using
<varname>sep</varname> as separator character. The <varname>ColumnLabels</varname> option
allows you to export or ignore the column labels, <varname>ColumnComments</varname> does the same for the comments
displayed in the table header and the <varname>SelectionOnly</varname> option makes
possible to export only the selected cells of the table.</para>
<programlisting>
t.exportASCII(file,sep="\t",ignore=0,ColumnLabels=False,ColumnComments=False,SelectionOnly=False)
</programlisting>
Other settings that you can modify are the text displayed as a comment in the header of a column...
<programlisting>
t.setComment(col, newComment)
</programlisting>
... or the expression used to calculate the column values. Please beware that changing the command doesn't automatically
update the values of the column; you have to call <varname>recalculate</varname> explicitly.
Calling it with just the column as argument will recalculate every row. Forcing muParser can speed things up.
<programlisting>
t.setCommand(col, newExpression)
t.recalculate(col, startRow=1, endRow=-1, forceMuParser=False, notifyChanges=True)
</programlisting>
</sect3>

You can access the column comments and enable/disable their display via the following functions:
<programlisting>
t.comment(col)
t.showComments(on = True)
</programlisting>

You can also modify the width of a column (in pixels) or hide/show table columns:
<programlisting>
t.setColumnWidth(col, width)
t.hideColumn(col, True)
</programlisting>

If one or several table columns are hidden you can make them visible again using:
<programlisting>
t.showAllColumns()
</programlisting>

You can ensure the visibility of a cell with:
<programlisting>
t.scrollToCell(col, row)
</programlisting>

After having changed some table values from a script, you will likely want to update dependent Graphs:
<programlisting>
t.notifyChanges()
</programlisting>

As a simple example, let's set some column values without using the dialog.
<programlisting>
t = table("table1")
for i in range(1, t.numRows()+1):
	t.setCell(1, i, i**2)
t.notifyChanges()
</programlisting>
While the above is easy to understand, there is a faster and more pythonic way of doing the same:
<programlisting>
t = table("table1")
t.setColData(1, [i*i for i in range(len(t))])
t.notifyChanges()
</programlisting>


You can check if a column or row of a table is selected by using the following functions:
<programlisting>
t.isColSelected(col)
t.isRowSelected(row)
</programlisting>

<sect3 id = "Python-R">
<title>R interface</title>

If <ulink url="http://rpy.sourceforge.net/rpy2.html">RPy2</ulink> is available,
the <link linkend="Python-init">default initialization file</link> sets up the
helper functions <userinput>qti.Table.toRDataFrame</userinput> and
<userinput>qti.app.newTableFromRDataFrame</userinput> to convert back and forth
between R data frames and &appname; tables.
Here is a little example of an R session...
<programlisting>
df &lt;- read.table("/some/path/data.csv", header=TRUE)
m &lt;- mean(df)
v &lt;- var(df)
source("/some/path/my_func.r")
new_df &lt;- my_func(df, foo=bar)
</programlisting>
... and now the same from within &appname;:
<programlisting>
df = table("Table1").toRDataFrame()
print R.mean(df), R.var(df)
R.source("/some/path/my_func.r")
new_df = R.my_func(df, foo=bar)
newTableFromRDataFrame(new_df, "my result table")
</programlisting>
</sect3>

</sect2>
<sect2 id="Python-Matrix">
<title>Working with Matrices</title>
Matrix objects have a dual view mode: either as images or as data tables.
Assuming that you have assigned some matrix to the variable
<varname>m</varname>, you can change its display mode via the following function:
<programlisting>
m.setViewType(Matrix.TableView)
m.setViewType(Matrix.ImageView)
</programlisting>

If a matrix is viewed as an image, you have the choice to display it
either as gray scale or using a predefined color map:
<programlisting>
m.setGrayScale()
m.setRainbowColorMap()
m.setDefaultColorMap() # default color map defined via the 3D plots tab of the preferences dialog
</programlisting>

You can also define custom color maps:
<programlisting>
map = LinearColorMap(QtCore.Qt.yellow, QtCore.Qt.blue)
map.setMode(LinearColorMap.FixedColors) # default mode is LinearColorMap.ScaledColors
map.addColorStop(0.2, QtCore.Qt.magenta)
map.addColorStop(0.7, QtCore.Qt.cyan)
m.setColorMap(map)
</programlisting>

You have direct access to the color map used for a matrix via the following functions:
<programlisting>
map = m.colorMap()
col1 = map.color1()
print col1.green()
col2 = map.color2()
print col2.blue()
</programlisting>

Accessing cell values is very similar to Table,
but since Matrix doesn't use column logic, row arguments are specified
before columns and obviously you can't use column name.
<programlisting>
m.cell(row, col)
m.setCell(row, col, value)
m.text(row, col)
m.setText(row, col, string)
</programlisting>

An alternative solution to assign values to a Matrix, would be to define a formula and to calculate the values using this formula, like in the following example:
<programlisting>
m.setFormula("x*y*sin(x*y)")
m.calculate()
</programlisting>

You can also specify a column/row range in the calculate() function, like this:
<programlisting>
m.calculate(startRow, endRow, startColumn, endColumn)
</programlisting>

Before setting the values in a matrix you might want to define the numeric precision,
that is the number of significant digits used for the computations:
<programlisting>
m.setNumericPrecision(prec)
</programlisting>

You can change the dimensions of a matrix:
<programlisting>
m.setDimensions(rows, columns)
m.setNumRows(rows)
m.setNumCols(columns)
</programlisting>

Also, like with tables, you can access the number of rows/columns in a matrix:
<programlisting>
rows = m.numRows()
columns = m.numCols()
</programlisting>

If QtiPlot has been built with support for <ulink url="http://www.alglib.net/">ALGLIB</ulink>, you can also change the dimensions of a matrix by resampling it, using
bilinear or bicubic interpolation:

<programlisting>
m.resample(rows, cols)# bilinear interpolation by default
m.resample(rows, cols, 1) # bicubic interpolation
</programlisting>

If ALGLIB is available you can also smooth the matrix data using:

<programlisting>
m.smooth()
</programlisting>

Matrix objects allow you to define a system of x/y coordinates that will be used when plotting color/contour maps or 3D height maps.
You can manipulate these coordinates using the following functions:
<programlisting>
xs = m.xStart()
xe = m.xEnd()
ys = m.yStart()
ye = m.yEnd()
m.setCoordinates(xs + 2.5, xe, ys - 1, ye + 1)
</programlisting>

The horizontal and vertical headers of a matrix can display either the x/y coordinates or
the column/row indexes:
<programlisting>
m.setHeaderViewType(Matrix.ColumnRow)
m.setHeaderViewType(Matrix.XY)
</programlisting>

There are several built-in transformations that you can apply to a matrix object.
You can transpose or invert a matrix and calculate its determinant, provided, of course, that
the conditions on the matrix dimensions, required by these operations, are matched:
<programlisting>
m.transpose()
m.invert()
d = m.determinant()
</programlisting>

Some other operations, very useful when working with images, like 90 degrees rotations and mirroring,
can also be performed. By default rotations are performed clockwise. For a counterclockwise rotation
you must set the <varname>clockwise</varname> parameter to <varname>False</varname>.
<programlisting>
m.flipVertically()
m.flipHorizontally()
m.rotate90(clockwise = True)
</programlisting>

Please note that sometimes, after a change in the matrix settings,
you need to use the following function in order to update the display:
<programlisting>
m.resetView()
</programlisting>

If you need to get data from a table, in order to use it in a matrix (or vice-versa), you can
avoid time consuming copy/paste operations and speed up the whole process by simply converting
the table into a matrix:
<programlisting>
m = tableToMatrix(table("Table1"))
t = matrixToTable(m)
</programlisting>

For the production of contour plots, you can convert a regular XYZ data table
("regular", meaning that cells in the X and Y columns of the table define a regular 2D grid) into a matrix:
<programlisting>
m = tableToMatrixRegularXYZ(table("Table1"), "Table1_3")
</programlisting>

Also, it's worth knowing that you can easily import image files to matrices, that can be
used afterwards for plotting (see the next section for more details about 2D plots):
<programlisting>
m1 = importImage("C:/poze/adi/PIC00074.jpg")
m2 = newMatrix()
m2.importImage("C:/poze/adi/PIC00075.jpg")
</programlisting>
The algorithm used to import the image returns a gray value between 0 and 255 from the (r, g, b) triplet
corresponding to each pixel. The gray value is calculated using the formula: (r * 11 + g * 16 + b * 5)/32

<para>For custom image analysis operations, you can get a copy of the matrix image view, as a QImage object, via:</para>
<programlisting>
image = m.image()
</programlisting>

You can export matrices to all raster image formats supported by Qt or to any of the following vectorial image format:
EPS, PS, PDF or SVG using:
<programlisting>
m.export(fileName)
</programlisting>

This is a shortcut function which uses some default parameters in order to generate the output image.
If you need more control over the export parameters you must use one of the following functions:
<programlisting>
m1.exportRasterImage(fileName, quality = 100, dpi = 0, compression = 0)
m2.exportVector(fileName, resolution, color = True)
</programlisting>,

where the <varname>quality</varname> parameter influences the size of the output file.
The higher this value (maximum is 100), the higher the quality of the image, but the larger the size of the resulting files.
The <varname>dpi</varname> parameter represents the export resolution in pixels per inch (the default is screen resolution).
The <varname>compression</varname> parameter can be 0 (no compression) or 1 (LZW) and is only effectif for .tif/.tiff images.
It is neglected for all other raster image formats.

<para>You can also import an ASCII data <varname>file</varname>, using <varname>sep</varname> as separator characters, ignoring
<varname>ignore</varname> lines at the head of the file and all lines starting with a <varname>comment</varname> string:
</para>
<programlisting>
m.importASCII(file, sep="\t", ignore=0, stripSpaces=True, simplifySpace=False, comment="#",
				importAs=Matrix.Overwrite, locale=QLocale(), endLine=0, maxRows=-1)
</programlisting>

<para>The <varname>importAs</varname> flag can have the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Matrix.NewColumns: data values are added as new columns.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Matrix.NewRows: data values are added as new rows.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Matrix.Overwrite: all existing values are overwritten (default value).</para>
              </listitem>
            </varlistentry>
</variablelist>

The <varname>locale</varname> parameter can be used to specify the convention for decimal separators used in your ASCII file.</para>

<para>The <varname>endLine</varname> flag specifies the end line character convention used in the ascii file.
Possible values are: 0 for line feed (LF), which is the default value,
1 for carriage return + line feed (CRLF) and 2 for carriage return only (usually on Mac computers).</para>

<para>The last parameter <varname>maxRows</varname> allows you to specify a maximum number of imported
lines. Negative values mean that all data lines must be imported.</para>

<para>Also, you can export values from a matrix to an ASCII <varname>file</varname>, using
<varname>sep</varname> as separator characters. The <varname>SelectionOnly</varname> option makes
possible to export only the selected cells of the matrix.</para>
<programlisting>
m.exportASCII(file, sep="\t", SelectionOnly=False)
</programlisting>
</sect2>

<sect2 id = "Python-Stem-and-Leaf-Plot">
<title>Stem Plots</title>
<para>
A stem-plot (or stem-and-leaf plot), in statistics, is a device for presenting
quantitative data in a graphical format, similar to a histogram,
to assist in visualizing the shape of a distribution.
A basic stem-plot contains two columns separated by a vertical line.
The left column contains the stems and the right column contains the leaves.
See <ulink url="http://en.wikipedia.org/wiki/Stemplot">Wikipedia</ulink> for more details.
</para>

<para>
QtiPlot provides a text representation of a stem-plot. The following function
returns a string of characters representing the statistical analysis of the data:

<programlisting>
text = stemPlot(Table *t, columnName, power = 1001, startRow = 0, endRow = -1)
</programlisting>

where the <varname>power</varname> variable is used to specify the stem unit as a power of 10.
If this parameter is greater than 1000 (the default behavior), than QtiPlot will
try to guess the stem unit from the input data and will pop-up a dialog asking you to
confirm the automatically detected stem unit.
</para>

<para>
Once you have created the string representation of the stem-plot, you can display it in any text editor you like:
in a note within the project or even in the results log:

<programlisting>
resultsLog().append(stemPlot(table("Table1"), "Table1_2", 1, 2, 15))
</programlisting>
</para>
</sect2>

<sect2 id = "Python-Plots2D">
<title>2D Plots</title>
If you want to create a new Graph window for some data in table Table1, you can use the plot command:
<programlisting>
t = table("Table1")
g = plot(t, column, type)
</programlisting>
<varname>type</varname> specifies the desired plot type and can be one of the following numbers or the equivalent reserved word:
	  <variablelist spacing="compact">
            <varlistentry>
              <term>0</term>

              <listitem>
                <para>Layer.Line</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>1</term>

              <listitem>
                <para>Layer.Scatter</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>2</term>

              <listitem>
                <para>Layer.LineSymbols</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>3</term>

              <listitem>
                <para>Layer.VerticalBars</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>4</term>

              <listitem>
                <para>Layer.Area</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>5</term>

              <listitem>
                <para>Layer.Pie</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>6</term>

              <listitem>
                <para>Layer.VerticalDropLines</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>7</term>

              <listitem>
                <para>Layer.Spline</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>8</term>

              <listitem>
                <para>Layer.HorizontalSteps</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>9</term>

              <listitem>
                <para>Layer.Histogram</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>10</term>

              <listitem>
                <para>Layer.HorizontalBars</para>
              </listitem>
            </varlistentry>

			 <varlistentry>
              <term>13</term>

              <listitem>
                <para>Layer.Box</para>
              </listitem>
            </varlistentry>

			<varlistentry>
              <term>15</term>

              <listitem>
                <para>Layer.VerticalSteps</para>
              </listitem>
            </varlistentry>
          </variablelist>

You can plot more than one column at once by giving a Python tuple (see the <ulink url="http://docs.python.org/tut">Python
Tutorial</ulink>) as an argument:
<programlisting>
g1 = plot(table("Table1"), (2,4,7), 2)
g2 = plot(table("Table1"), ("Table1_2","Table1_3"), Layer.LineSymbols)
</programlisting>

All the curves in a plot layer can be customized in terms of color, line width and line style.
Here's a short script showing the corresponding functions at work:
<programlisting>
t = newTable("test", 30, 4)
for i in range(1, t.numRows()+1):
	t.setCell(1, i, i)
	t.setCell(2, i, i)
	t.setCell(3, i, i+2)
	t.setCell(4, i, i+4)

l = plot(t, (2,3,4), Layer.Line).activeLayer() # plot columns 2, 3 and 4
for i in range(0, l.numCurves()):
	l.setCurveLineColor(i, 1 + i) #curve color is defined as an integer value
	l.setCurveLineWidth(i, 0.5 + 2*i)

l.setCurveLineStyle(1, QtCore.Qt.DotLine)
l.setCurveLineStyle(2, QtCore.Qt.DashLine)
</programlisting>

You can also create a vector plot by giving four columns in
a Python tuple as an argument and the plot type as Layer.VectXYXY (11) or Layer.VectXYAM (14),
depending on how you want to define the end point of your vectors: using (X, Y) coordinates or
(Angle, Magnitude) coordinates.
<programlisting>
g = plot(table("Table1"), (2,3,4,5), Layer.VectXYXY)
</programlisting>

If you want to add a curve to an existing Graph window, you have
to choose the destination layer. Usually,
<programlisting>
l = g.activeLayer()
</programlisting>
will do the trick, but you can also select a layer by its number:
<programlisting>
l = g.layer(num)
</programlisting>

<sect3 id="Python-Title">
<title>The plot title</title>
<programlisting>
l.setTitle("My beautiful plot")
l.setTitleFont(QtGui.QFont("Arial", 12))
l.setTitleColor(QtGui.QColor("red"))
l.setTitleAlignment(QtCore.Qt.AlignLeft)
</programlisting>
The alignment parameter can be any combination of the Qt alignment flags (see the
<ulink url="http://www.riverbankcomputing.com/static/Docs/PyQt4/html/qt.html#AlignmentFlag-enum">PyQt documentation</ulink>
for more details).
<para>If you want you can remove the plot title using:</para>
<programlisting>
l.removeTitle()
</programlisting>

Here's how you can add greek symbols in the plot title or in any other text in the plot layer: axis labels, legends:
<programlisting>
<![CDATA[
l.setTitle("normal text <font face=\"Symbol\">greek text</font>")
]]>
</programlisting>

Using the font specifications, you can also change the color of some parts of the title only:
<programlisting>
<![CDATA[
l=newGraph().activeLayer()
l.setTitle("<font color = red>red</font> <font color = yellow>yellow</font> <font color = blue>blue</font>")
]]>
</programlisting>
</sect3>

<sect3 id="Python-Axes">
<title>Customizing the axes</title>
Layer axes can be shown/hidden using the following function:
<programlisting>
l.enableAxis(int axis, on = True)
</programlisting>
where <varname>axis</varname> can be any integer value between 0 and 3 or the equivalent reserved word:
	  <variablelist spacing="compact">
			<varlistentry>
			  <term>0.</term>
			  <listitem>
				<para>Layer.Left</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>1.</term>
			  <listitem>
				<para>Layer.Right</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>2.</term>
			  <listitem>
				<para>Layer.Bottom</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>3.</term>
			  <listitem>
				<para>Layer.Top</para>
			  </listitem>
			</varlistentry>
		  </variablelist>

If an axis is enabled, you can fully customize it via a Python script.
For example you can set its title:
<programlisting>
l.setAxisTitle(axis, "My axis title")
l.setAxisTitleFont(axis, QtGui.QFont("Arial", 11))
l.setAxisTitleColor(axis, QtGui.QColor("blue"))
l.setAxisTitleAlignment(axis, alignFlags)
</programlisting>
its color and the font used for the tick labels:
<programlisting>
l.setAxisColor(axis, QtGui.QColor("green"))
l.setAxisFont(axis, QtGui.QFont("Arial", 10))
</programlisting>

The tick labels of an axis can be enabled or disabled, you can set their color and their rotation angle:
<programlisting>
l.enableAxisLabels(axis, on = True)
l.setAxisLabelsColor(axis, QtGui.QColor("black"))
l.setAxisLabelRotation(axis, angle)
</programlisting>
<varname>angle</varname> can be any integer value between -90 and 90 degrees.
A rotation angle can be set only for horizontal axes (Bottom and Top).
<para>The numerical format of the labels can be set using:</para>
<programlisting>
l.setAxisNumericFormat(axis, format, precision = 6, formula)
</programlisting>
where <varname>format</varname> can have the following values: <variablelist spacing="compact">
			<varlistentry>
			  <term>0.</term>
			  <listitem>
				<para>Automatic: the most compact numeric representation is chosen</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>1.</term>
			  <listitem>
				<para>Decimal: numbers are displayed in floating point form</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>2.</term>
			  <listitem>
				<para>Scientific: numbers are displayed using the exponential notation</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>3.</term>
			  <listitem>
				<para>Superscripts: like Scientific, but the exponential part is displayed as a power of 10</para>
			  </listitem>
			</varlistentry>
		  </variablelist>
<varname>precision</varname> is the number of significant digits and
<varname>formula</varname> is a mathematical expression that can be used to link opposite scales. It's
argument must be <varname>x</varname> for horizontal axes and <varname>y</varname> for vertical axes.
For example, assuming that the bottom axis displays a range of wavelengths in nanometers and that the top
axis represents the equivalent energies in eV, with the help of the code below all the wavelengths
will be automatically converted to electron-volts and the result will be displayed in floating point form
with two significant digits after the decimal dot sign:
<programlisting>
l.setAxisNumericFormat(Layer.Top, 1, 2, "1239.8419/x")
</programlisting>

The axis ticks can be customized via the following functions:

<programlisting>
l.setTicksLength(minLength, majLength)
l.setMajorTicksType(axis, majTicksType)
l.setMinorTicksType(axis, minTicksType)
l.setAxisTicksLength(axis, majTicksType, minTicksType, minLength, majLength)
</programlisting>
where the <varname>majTicksType</varname> and <varname>minTicksType</varname> parameters specify the
desired orientation for the major and minor ticks, respectively:
<variablelist spacing="compact">
			<varlistentry>
			  <term>0.</term>
			  <listitem>
				<para>Layer.NoTicks</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>1.</term>
			  <listitem>
				<para>Layer.Out: outward orientation for ticks, with respect to the plot canvas</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>2.</term>
			  <listitem>
				<para>Layer.InOut: both inward and outward ticks</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>3.</term>
			  <listitem>
				<para>Layer.In: inward ticks</para>
			  </listitem>
			</varlistentry>
		  </variablelist>
<varname>minLength</varname> specifies the length of the minor ticks, in pixels and
<varname>majLength</varname> the length of the major ticks.

<para>You can also customize the scales of the different axes using: <programlisting>
l.setScale(int axis, double start, double end, double step=0.0, int majorTicks=5, int minorTicks=5, int type=0, bool inverted=False)
</programlisting>
where <varname>type</varname> specifies the desired scale type: <variablelist spacing="compact">
			<varlistentry>
			  <term>0.</term>
			  <listitem>
				<para>Layer.Linear</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>1.</term>
			  <listitem>
				<para>Layer.Log10</para>
			  </listitem>
			</varlistentry>
			  <varlistentry>
				<term>2.</term>
				<listitem>
				  <para>Layer.Ln</para>
				</listitem>
			  </varlistentry>
			  <varlistentry>
				<term>3.</term>
				<listitem>
				  <para>Layer.Log2</para>
				</listitem>
			  </varlistentry>
				<varlistentry>
				  <term>4.</term>
				  <listitem>
					<para>Layer.Reciprocal</para>
				  </listitem>
				</varlistentry>
				<varlistentry>
				  <term>5.</term>
				  <listitem>
					<para>Layer.Probability</para>
				  </listitem>
				</varlistentry>
				  <varlistentry>
					<term>6.</term>
					<listitem>
					  <para>Layer.Logit</para>
					</listitem>
				  </varlistentry>
		  </variablelist>
and <varname>step</varname> defines the size of the interval between the major scale ticks. If not specified (default value is 0.0), the step size is calculated automatically.
The other flags should be self-explanatory.</para>

Defining a scale range for an axis doesn't automatically disable autoscaling.
This means that if a curve is added or removed from the layer, the axes will still automatically
adapt to the new data interval. This can be avoided by disabling the autoscaling mode, thus
making sure that your scale settings will always be taken into account:
<programlisting>
l.enableAutoscaling(False)
</programlisting>

If you want to rescale the plot layer so that all the data points are visible, you can use the following utility function:
<programlisting>
l.setAutoScale()
</programlisting>

The same <varname>setScale</varname> function above, with a longer list of arguments,
can be used to define an axis break region:
<programlisting>
l.setScale(axis, start, end, step=0.0, majorTicks=5, minorTicks=5, type=0, inverted=False,
	left=-DBL_MAX, right=DBL_MAX, breakPosition=50, stepBeforeBreak=0.0, stepAfterBreak=0.0,
	minTicksBeforeBreak=4, minTicksAfterBreak=4, log10AfterBreak=False, breakWidth=4, breakDecoration=True)
</programlisting>
where <varname>left</varname> specifies the left limit of the break region,
<varname>right</varname> the right limit,
<varname>breakPosition</varname> is the position of the break expressed as a percentage of the axis length and
<varname>breakWidth</varname> is the width of the break region in pixels.
The names of the other parameters should be self-explanatory.

<para>Finally, you can specify the width of all axes and enable/disable the drawing of their
backbone line, using:</para>
<programlisting>
l.setAxesLinewidth(2)
l.drawAxesBackbones(True)
</programlisting>
</sect3>

<sect3 id="Python-Canvas">
<title>The canvas</title>
You can display a rectangular frame around the drawing area of the plot (the canvas) and
fill it with a background color or with an image, using:
<programlisting>
l.setCanvasFrame(2, QtGui.QColor("red"))
l.setCanvasColor(QtGui.QColor("lightGrey"))
l.setCanvasBackgroundImage("C:/qtiplot/qtiplot/qtiplot_logo.png")
</programlisting>

The following access methods are available for the canvas background image:
<programlisting>
pic = l.backgroundPixmap() # QPixmap
path = l.canvasBackgroundFileName()
</programlisting>

Drawing the canvas frame and disabling the axes backbone lines
is the only possible solution for the issue of axes not touching themselves at their ends.
</sect3>

<sect3 id="Python-Frame">
<title>The layer frame</title>
You can display a rectangular frame around the whole layer and fill it with a background color,
using:<programlisting>
l.setFrame(2, QtGui.QColor("blue"))
l.setBackgroundColor(QtGui.QColor("grey"))
</programlisting>
The default spacing between the layer frame and the other layer elements (axes, title) can be changed via:
<programlisting>
l.setMargin(10)
</programlisting>
</sect3>

<sect3 id="Python-Grid-2D">
<title>Customizing the grid</title>

You can display the grid associated to a layer axis or the whole grid using:<programlisting>
l.showGrid(axis)
l.showGrid()
l.setGridOnTop(on = True, update = True) # draw grid on top of data
</programlisting>
This will display the grid with the default color, width and pen style settings.
If you need to change these settings, as well as to enable/disable certain grid lines,
you can use the following functions:<programlisting>
grid = l.grid()
grid.setMajPenX(QtGui.QPen(QtCore.Qt.red, 1))
grid.setMinPenX(QtGui.QPen(QtCore.Qt.yellow, 1, QtCore.Qt.DotLine))
grid.setMajPenY(QtGui.QPen(QtCore.Qt.green, 1))
grid.setMinPenY(QtGui.QPen(QtCore.Qt.blue, 1, QtCore.Qt.DashDotLine))
grid.enableXMax(True)
grid.enableXMin()
grid.enableYMax()
grid.enableYMin(False)
grid.enableZeroLineX(True)
grid.enableZeroLineY(False)
grid.setXZeroLinePen(QtGui.QPen(QtCore.Qt.black, 2))
grid.setYZeroLinePen(QtGui.QPen(QtCore.Qt.black, 2))
l.replot()
</programlisting>
All the grid functions containing an <varname>X</varname> refer to the vertical grid lines, whereas the <varname>Y</varname> letter indicates the horizontal ones.
Also, the <varname>Maj</varname> word refers to the main grid lines and <varname>Min</varname> to the secondary grid.
</sect3>

<sect3 id="Python-Legends">
<title>The plot legend</title>
You can add a new legend to a plot using: <programlisting>
legend = l.newLegend()
#or
legend = l.newLegend("enter your text here")
</programlisting>

Plot legends are special text objects which are updated each time you add or remove a curve from the layer.
They have a special <varname>auto-update</varname> flag which is enabled by default.
The following function returns <varname>True</varname> for a legend object:
<programlisting>
legend.isAutoUpdateEnabled()
</programlisting>

You can disable/enable the auto-update behavior of a legend/text object using:
<programlisting>
legend.setAutoUpdate(False/True)
</programlisting>

You can add common texts like this:
<programlisting>
text = l.addText(legend)
text.setOrigin(legend.x(), legend.y()+50)
</programlisting>
Please notice that the <varname>addText</varname> function returns a different reference
to the new text object. You can use this new reference later on in order to remove the text:
<programlisting>
l.remove(text)
</programlisting>

Once you have created a legend/text, it's very easy to customize it.
If you want to modify the text you can use:<programlisting>
legend.setText("Enter your text here")
</programlisting>

All other properties of the legend: rotation angle, text color, background color, frame style, font and position of the top-left corner
can be modified via the following functions:<programlisting>
legend.setAngle(90)
legend.setTextColor(QtGui.QColor("red"))
legend.setBackgroundColor(QtGui.QColor("yellow"))
legend.setFrameStyle(Frame.Shadow)
legend.setFrameColor(QtCore.Qt.red)
legend.setFrameWidth(3)
legend.setFrameLineStyle(QtCore.Qt.DotLine)
legend.setFont(QtGui.QFont("Arial", 14, QtGui.QFont.Bold, True))
# set top-left position using scale coordinates:
legend.setOriginCoord(200.5, 600.32)
# or set top-left position using pixel coordinates:
legend.setOrigin(5, 10)
legend.repaint()
</programlisting>

Other frame styles available for legends are: <varname>Legend.Line</varname>, which draws a rectangle around the text
and <varname>Legend.None</varname> (no frame at all).

There is also a function allowing you to add an automatically built time stamp:
<programlisting>
timeStamp = l.addTimeStamp()
</programlisting>
</sect3>

<sect3 id="Python-Antialiasing">
<title>Antialiasing</title>
Antialiasing can be enabled/disabled for the drawing of the curves and other layer
objects, but it is a very resources consuming feature:<programlisting>
l.setAntialiasing(True, bool update = True)
</programlisting>
</sect3>

<sect3 id="Python-ResizingLayers">
<title>Resizing layers</title>
A layer can be resized using the methods below, where the first argument is the new width,
 the second is the new height and sizes are defined in pixels:
 <programlisting>
 l.resize(200, 200);
 l.resize(QSize(w, h))
 </programlisting>

 If you also need to reposition the layer, you can use the following functions, where the first two arguments
 specify the new position of the top left corner of the canvas:
 <programlisting>
 l.setGeometry(100, 100, 200, 200);
 l.setGeometry(QRect(x, y, w, h));
 </programlisting>

The default behavior of 2D plot layers, with respect to the resizing of the graph window
is to adapt the sizes of the fonts used for the various texts, to the new size
of the plot window. You can override this behavior and keep the size of the fonts unchanged:
<programlisting>
l.setAutoscaleFonts(False)
</programlisting>
</sect3>

<sect3 id="Python-Resizing">
<title>Resizing the drawing area</title>
 The drawing area of a layer (the canvas) can be resized using the methods below, where the first argument is the new width,
 the second is the new height and sizes are defined in pixels:
 <programlisting>
 l.setCanvasSize(200, 200);
 l.setCanvasSize(QSize(w, h))
 </programlisting>

 If you also need to reposition the canvas, you can use the following functions, where the first two arguments
 specify the new position of the top left corner of the canvas:
 <programlisting>
 l.setCanvasGeometry(100, 100, 200, 200);
 l.setCanvasGeometry(QRect(x, y, w, h));
 </programlisting>

Please keep in mind that the fonts of the layer are not rescaled when you resize the layer canvas using the above methods.
</sect3>
</sect2>

<sect2 id="Python-Curves">
<title>Working with 2D curves</title>
You can then add or remove curves to or from this layer:
<programlisting>
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()
</programlisting>

It is possible to change the order of the curves inserted in a layer using the following functions:
<programlisting>
l.changeCurveIndex(int oldIndex, int newIndex)
l.reverseCurveOrder()
</programlisting>

If the table column used to create a plot curve has empty cells,
you can choose whether the curve line is drawn connected across the missing data or not.
This behavior can be specified using:
<programlisting>
l.showMissingDataGap(on = True, replot = True)
</programlisting>

Sometimes, when performing data analysis, one might need the curve title. It is possible to obtain it using the method below:
<programlisting>
title = l.curveTitle(curveIndex)
</programlisting>

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:
<programlisting>
c = l.curve(curveIndex)
c = l.curve(curveTitle)
dc = l.dataCurve(curveIndex)
</programlisting>
<para>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.</para>

<para>Use the following function to change the axis attachment of a curve:</para>
<programlisting>
l.setCurveAxes(number, x-axis, y-axis)
</programlisting>
<para>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).</para>

In case you need the number of curves on a layer, you can get it with <programlisting>
l.numCurves()
</programlisting>

Once you have added a curve to a 2D plot, you can fully customize it's appearance:
<programlisting>
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)))
</programlisting>

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:
<programlisting>
c.setSkipSymbolsCount(3)
print c.skipSymbolsCount()
</programlisting>

An alternative way of customizing a curve is by using the functions below:
<programlisting>
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)
</programlisting>

You can also define a global color policy for the plot layer using the following
convenience functions:
<programlisting>
l.setGrayScale()
l.setIndexedColors() # uses the colors in the default QtiPlot color list: 0 = black, 1 = red, 2 = green, etc...
</programlisting>

You can display labels showing the y values for each data point in a DataCurve:
<programlisting>
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
</programlisting>

and, of course, you can disable them using:
<programlisting>
c.clearLabels()
l.replot() # redraw the plot layer object
</programlisting>

If you need to change the range of data points displayed in a DataCurve you can use
the following methods:
<programlisting>
c.setRowRange(int startRow, int endRow)
c.setFullRange()
</programlisting>

Also, you can hide/show a plot curve via:
<programlisting>
c.setVisible(bool on)
</programlisting>

In case you need to get information about the data stored in the curve,
you have at your disposal the functions below:
<programlisting>
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()
</programlisting>

<sect3 id = "Python-PlotSymbols">
<title>Curve symbols</title>

Here's how you can customize the plot symbol used for a 2D plot curve <varname>c</varname>:
<programlisting>
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
</programlisting>

The symbol styles available in QtiPlot are:
<variablelist spacing="compact">
			<varlistentry>
			  <term>0</term>

			  <listitem>
				<para>PlotSymbol.NoSymbol</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>1</term>

			  <listitem>
				<para>PlotSymbol.Ellipse</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>2</term>

			  <listitem>
				<para>PlotSymbol.Rect</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>3</term>

			  <listitem>
				<para>PlotSymbol.Diamond</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>4</term>

			  <listitem>
				<para>PlotSymbol.Triangle</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>5</term>

			  <listitem>
				<para>PlotSymbol.DTriangle</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>6</term>

			  <listitem>
				<para>PlotSymbol.UTriangle</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>7</term>

			  <listitem>
				<para>PlotSymbol.LTriangle</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>8</term>

			  <listitem>
				<para>PlotSymbol.RTriangle</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>9</term>

			  <listitem>
				<para>PlotSymbol.Cross</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>10</term>

			  <listitem>
				<para>PlotSymbol.XCross</para>
			  </listitem>
			</varlistentry>

			 <varlistentry>
			  <term>11</term>

			  <listitem>
				<para>PlotSymbol.HLine</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>12</term>

			  <listitem>
				<para>PlotSymbol.VLine</para>
			  </listitem>
			</varlistentry>
			<varlistentry>
			  <term>13</term>

			  <listitem>
				<para>PlotSymbol.Star1</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>14</term>
			<listitem>
				<para>PlotSymbol.Star2</para>
			  </listitem>
			</varlistentry>

			<varlistentry>
			  <term>15</term>
			<listitem>
				<para>PlotSymbol.Hexagon</para>
			  </listitem>
			</varlistentry>
		  </variablelist>

It is also possible to define a custom image as the plot symbol for a curve:
<programlisting>
g = newGraph().activeLayer()
c = g.addFunction("cos(x)", 0, 10, 20)
c.setSymbol(ImageSymbol("qtiplot/manual/html/icons/help.png"))
</programlisting>

Here's a short script showing how to draw a custom plot symbol and assign it to a curve:
<programlisting>
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))
</programlisting>
</sect3>
</sect2>

<sect2 id = "Python-AnalyticalFunctions">
<title>2D Analytical Functions</title>
You can also add analytical function curves to a plot layer:
<programlisting>
f = l.addFunction("x*sin(x)", 0, 3*pi, points = 100)
f.setTitle("x*sin(x)")
f.setPen(Qt.green)
f.setBrush(QtGui.QColor(0, 255, 0, 100))

l.addParametricFunction("cos(m)", "sin(m)", 0, 2*pi, points = 100, variableName = "m")
l.addPolarFunction("t", "t", 0, 2*pi, points = 100, variableName = "t")
</programlisting>

It is possible to get a reference to an analytical function curve on the layer l using it's index, like shown below:
<programlisting>
f = l.functionCurve(curveIndex)
</programlisting>

When dealing with analytical function curves, you can customize them using the following methods:
<programlisting>
f.setRange(0, 2*pi)
f.setVariable("t")
f.setFormulas("sin(t)", "cos(t)")
f.setFunctionType(FunctionCurve.Polar) # or c.setFunctionType(FunctionCurve.Parametric)
f.loadData(1000, xLog10Scale = False)

f.setFunctionType(FunctionCurve.Normal)
f.setFormula("cos(x)")
f.loadData()
</programlisting>

If you need to access the values and names of a function's parameters, you have at your disposal the following methods:
<programlisting>
i = f.parametersCount() # the number of parameters in your function formula
name = f.parameterName(index) # the name of the parameter of rang index as a QString
p1 = f.parameterValue(index) # the value of the parameter of rang index as a double
p2 = f.parameterValue(name) # the value of a parameter using its name string
</programlisting>

The abscissae range for which the function is calculated/displayed, can be obtained/modified via the methods below:
<programlisting>
x1 = f.startRange()
x2 = f.endRange()
f.setRange(0.5, 15.2)
</programlisting>
</sect2>

<sect2 id = "Python-ErrorBars">
<title>Error Bars</title>

Having a plot layer <emphasis>l</emphasis>, you can add error bars to a data curve <emphasis>c</emphasis>, named <emphasis>curveName</emphasis>, using the following methods:
<programlisting>
err1 = l.addErrorBars(c, Table *t, QString errColName, int type = 1, double width = 1, int capLength = 8, color = Qt.black, throughSymbol = True, minusSide = True, plusSide = True)
err2 = l.addErrorBars(curveName, Table *t, QString errColName, int type = 1, double width = 1, int capLength = 8, color = Qt.black, throughSymbol = True, minusSide = True, plusSide = True)
</programlisting>

Each data curve, <emphasis>c</emphasis>, can have attached a list of error bars:
<programlisting>
errors = c.errorBarsList()
</programlisting>

The properties of an error bar curve can be accesses, via the following methods:
<programlisting>
err = c.errorBarsList()[0]
for i in range(0, err.dataSize()):
	print err.errorValue(i)

err.capLength()
err.width()
err.color()
err.direction()
err.xErrors()
err.throughSymbol()
err.plusSide()
err.minusSide()
c = err.masterCurve() # reference to the master curve to which the error bars curve is attached.
err.detachFromMasterCurve() # equivalent to c.removeErrorBars(err)
</programlisting>

... and can be modified, via the following methods:
<programlisting>
err.setCapLength(12)
err.setWidth(3)
err.setColor(Qt.red)
err.setDirection(ErrorBarsCurve.Vertical)
err.setXErrors(True) # equivalent to err.setDirection(ErrorBarsCurve.Horizontal)
err.drawThroughSymbol(True)
err.drawPlusSide(True)
err.drawMinusSide(False)
err.setMasterCurve(c)
</programlisting>

You can remove all error bars attached to a curve using:
<programlisting>
c.clearErrorBars()
</programlisting>
</sect2>

<sect2 id = "Python-Spectrograms">
<title>Image and Contour Line Plots (Spectrograms)</title>

As you have seen in the previous section, it is possible create 2D plots from matrices.
Here's how you can do it in practice:
<programlisting>
m = importImage("C:/poze/adi/PIC00074.jpg")
g1 = plot(m, Layer.ColorMap)
g2 = plot(m, Layer.Contour)
g3 = plot(m, Layer.GrayScale)
</programlisting>

The plot functions above return a reference to the multilayer plot window. If you need a reference to the
spectrogram object itself, you can get it as shown in the example below:
<programlisting>
m = newMatrix("TestMatrix", 1000, 800)
m.setFormula("x*y")
m.calculate()
g = plot(m, Layer.ColorMap)
s = g.activeLayer().spectrogram(m)
s.setColorBarWidth(20)
</programlisting>

It is possible to fine tune the plots created from a matrix:

<programlisting>
m = newMatrix("TestMatrix", 1000, 800)
m.setFormula("x*y")
m.calculate()

s = newGraph().activeLayer().plotSpectrogram(m, Layer.ColorMap)
s.setContourLevels((20.0, 30.0, 60.0, 80.0))
s.setDefaultContourPen(QtGui.QPen(Qt.yellow)) # set global pen for the contour lines
s.setLabelsWhiteOut(True)
s.setLabelsColor(Qt.red)
s.setLabelsFont(QtGui.QFont("Arial", 14))
s.setLabelsRotation(45)
s.showColorScale(Layer.Top)
s.setColorBarWidth(20)
</programlisting>

As you have seen earlier, you can set a global pen for the contour lines, using:
<programlisting>
s.setDefaultContourPen(QtGui.QPen(Qt.yellow))
</programlisting>
You can also assign a specific pen for each contour line, using the function below:
<programlisting>
s.setContourLinePen(index, QPen)
</programlisting>
or you can automatically set pen colors defined by the color map of the spectrogram:
<programlisting>
s.setColorMapPen(bool on = True)
</programlisting>

You can also use any of the following functions:
<programlisting>
s.setMatrix(Matrix *, bool useFormula = False)
s.setUseMatrixFormula(bool useFormula = True)# calculate data to be drawn using matrix formula (if any)
s.setLevelsNumber(int)
s.showColorScale(int axis, bool on = True)
s.setGrayScale()
s.setDefaultColorMap()
s.setCustomColorMap(LinearColorMap map)
s.showContourLineLabels(bool show = True) # enable/disable contour line labels
s.setLabelsOffset(int x, int y) # offset values for all labels in % of the text size
s.updateData()
</programlisting>
</sect2>

<sect2 id = "Python-Histograms">
<title>Histograms</title>

As you have seen in the previous section, it is possible create 2D histograms from matrices or tables.
Here's a small script showing how to customize a histogram and how to get access to the
statistical information in the histogram (bin positions, counts, mean, standard deviation, etc...):
<programlisting>
m = newMatrix("TestHistogram", 1000, 800)
m.setFormula("x*y")
m.calculate()

g = newGraph().activeLayer()
h = g.addHistogram(m)
h.setBinning(10, 1, 90) # the bin size is set to 10, data range is set to [1, 90]
h.loadData() # update the histogram
g.replot() # update the display

# print histogram values:
for i in range (0, h.dataSize()):
	print i, "Bin start = ", h.x(i), "counts = ", h.y(i)

# print statistic information:
print "Standard deviation = ", h.standardDeviation()
print "Mean = ", h.mean()
</programlisting>

You can also enable autobinning (a default number of ten bins will be used):
<programlisting>
 h.setAutoBinning()
 </programlisting>
</sect2>

<sect2 id = "Python-BoxWhiskersPlos">
<title>Box and whiskers plots</title>
The following script shows how to create and customize a box and whiskers plot:
<programlisting>
g = newGraph().activeLayer()
g.plotBox(table("Table1"), ["2", "3", "4"])
for i in range (0, g.numCurves()):
		box = g.boxCurve(i)
		if (box):
			box.setBrush(QtGui.QBrush(Qt.red, Qt.BDiagPattern))
			s = PlotSymbol()
			s.setPen(QtGui.QPen(Qt.blue, 2))
			s.setSize(QtCore.QSize(10, 10))
			box.setSymbol(s)
			box.setMeanStyle(PlotSymbol.Cross)
			box.setBoxStyle(BoxCurve.WindBox)
			box.setBoxWidth(80)
			box.setWhiskersRange(BoxCurve.SD) # standard deviation
</programlisting>

The following functions give access to the statistics information for the data series displayed with a box and whiskers plot:
<programlisting>
s = box.statistics() # returns information as a string
m = box.median()
q = box.quantile(f) # f must be a fraction between 0 and 1
</programlisting>

For an exhaustive review of the methods giving access to the properties of a box plot, please consult the
<ulink url="http://soft.proindependent.com/doc/manual-en/Python-API/html/index.html">QtiPlot/Python API</ulink>.
</sect2>

<sect2 id = "Python-PieCurve">
<title>Pie Plots</title>
The following script shows how to create and customize a pie plot:
<programlisting>
g = newGraph().activeLayer()
pie = g.plotPie(table("Table1"), "2")
pie.setRadius(70)
pie.setViewAngle(40)
pie.setThickness(20)
pie.setStartAzimuth(45)
pie.setLabelsEdgeDistance(50)
pie.setCounterClockwise(True)
pie.setBrushStyle(Qt.Dense3Pattern)
pie.setFirstColor(3)
pie.setPen(QtGui.QPen(Qt.red, 2))
pie.setLabelValuesFormat(True)
</programlisting>

For an exhaustive review of the methods giving access to the properties of a pie plot, please consult the
<ulink url="http://soft.proindependent.com/doc/manual-en/Python-API/html/index.html">QtiPlot/Python API</ulink>.
</sect2>

<sect2 id = "Python-VectorsCurve">
<title>Vector Plots</title>
The following script shows how to create and customize a vector curve:
<programlisting>
g = newGraph().activeLayer()
v = g.plotVectors(table("Table1"), ["1", "2", "3", "4"], Layer.VectXYAM)
v.setVectorPen(Qt.red)
v.fillArrowHead(False)
v.setHeadAngle(15)
v.setHeadLength(20)
v.setPosition(VectorCurve.Middle)
</programlisting>

For an exhaustive review of the methods giving access to the properties of a vector curve, please consult the
<ulink url="http://soft.proindependent.com/doc/manual-en/Python-API/html/index.html">QtiPlot/Python API</ulink>.
</sect2>

<sect2 id="Python-Arrows">
<title>Adding arrows/lines to a plot layer</title>
<programlisting>
arrow = ArrowMarker()
arrow.setStart(10.5, 12.5)
arrow.setEnd(200, 400.51)
arrow.setStyle(QtCore.Qt.DashLine)
arrow.setColor(QtGui.QColor("red"))
arrow.setWidth(1)
arrow.drawStartArrow(False)
arrow.drawEndArrow(True)
arrow.setHeadLength(7)
arrow.setHeadAngle(35)
arrow.fillArrowHead(True)

l = newGraph().activeLayer()
arrow1 = l.addArrow(arrow)

arrow.setStart(120.5, 320.5)
arrow.setColor(QtGui.QColor("blue"))
arrow2 = l.addArrow(arrow)

l.remove(arrow1)
</programlisting>

<para>As you might notice from the sample code above, the <varname>addArrow</varname> function
returns a reference to a new arrow object that can be used later on to modify this
new arrow or to delete it with the <varname>remove</varname> function.</para>

<para>It is possible to modify the properties of all the lines/arrows in a plot layer, see the short example below:</para>
<programlisting>
g = graph("Graph1").activeLayer()
lst = g.arrowsList()
for i in range (0, g.numArrows()):
	lst[i].setColor(Qt.green)

g.replot()
</programlisting>

</sect2>

<sect2 id="Python-Images">
<title>Adding images to a layer</title>
<programlisting>
l = newGraph().activeLayer()
image = l.addImage("C:/poze/adi/PIC00074.jpg")
image.setCoordinates(200, 800, 800, 200)
image.setFrameStyle(Frame.Shadow)
image.setFrameColor(QtCore.Qt.green)
image.setFrameWidth(3)
l.replot()
</programlisting>

The <varname>setCoordinates</varname> function above can be used to set the geometry of the image using
scale coordinates. If you need to specify the image geometry in pixel coordinates, independently of
the plot axes values, you may use the following functions:
<programlisting>
image.setOrigin(x, y)
image.setSize(width, height)
image.setRect(x, y, width, height)
l.replot()
</programlisting>

You can remove an image using its reference:
<programlisting>
l.remove(image)
</programlisting>
</sect2>

<sect2 id="Python-Rectangles">
<title>Rectangles</title>
<programlisting>
l = newGraph().activeLayer()

r = Rectangle(l)
r.setSize(100, 100)
r.setOrigin(100, 200)
r.setBackgroundColor(QtCore.Qt.yellow)
r.setFrameColor(QtCore.Qt.red)
r.setFrameWidth(3)
r.setFrameLineStyle(QtCore.Qt.DotLine)
r.setBrush(QtGui.QBrush(QtCore.Qt.green, QtCore.Qt.FDiagPattern))

r1 = l.add(r)
</programlisting>

You can remove a rectangle using its reference:
<programlisting>
r2 = l.add(r)
r2.setOrigin(200, 200)
l.remove(r1)
</programlisting>
</sect2>

<sect2 id="Python-Ellipses">
<title>Circles/Ellipses</title>
<programlisting>
l = newGraph().activeLayer()

e = Ellipse(l)
e.setSize(100, 100)
e.setOrigin(100, 200)
e.setBackgroundColor(QtCore.Qt.yellow)
e.setFrameColor(QtCore.Qt.red)
e.setFrameWidth(0.8)
e.setFrameLineStyle(QtCore.Qt.DotLine)
e.setBrush(QtGui.QBrush(QtCore.Qt.green, QtCore.Qt.FDiagPattern))

l.add(e)
</programlisting>
</sect2>

<sect2 id="Python-Exporting-2DPlots">
<title>Exporting plots/layers to different image formats</title>
Layers and whole Graphs can be printed and exported from within Python.
The fastest way to export a plot/layer is the following: <programlisting>
l.export(fileName)
</programlisting>

This function uses some default parameters
for the properties of the image. If you need more control over the exported images you can use one
of the following specialized functions:<programlisting>
l.exportVector(fileName, dpi = 96, color = True, size = QtCore.QSizeF(), unit = Frame.Pixel, fontsFactor = 1.0)
l.exportImage(fileName, quality = 100, transparent = False, dpi = 0, size = QtCore.QSizeF(), unit = Frame.Pixel, fontsFactor = 1.0, compression = 0)
l.exportTex(fileName, color = True, escapeStrings = True, fontSizes = True, size = QtCore.QSizeF(), unit = Frame.Pixel, fontsFactor = 1.0)</programlisting>

<para>The function <varname>exportVector</varname> can export the plot/layer to the following vector formats:
.eps, .ps, .pdf.</para>

<para>The function <varname>exportImage</varname> can be used if you need to export to
one of the Qt supported raster image formats (.bmp, .png, .jpg, etc...). The <varname>transparent</varname>
option can only be used in conjunction with the file formats supporting transprency: .png and .tif (.tiff).
The <varname>quality</varname> parameter influences the size of the output file. The higher this value (maximum is 100),
the higher the quality of the image, but the larger the size of the resulting files.
The <varname>dpi</varname> parameter represents the export resolution in pixels per inch (the default is screen resolution),
<varname>size</varname> is the printed size of the image (the default is the size on screen) and
<varname>unit</varname> is the length unit used to express the custom size
and can take one of the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Inch</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Millimeter</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Centimeter</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>3.</term>
              <listitem>
                <para>Point: 1/72th of an inch</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>4.</term>
              <listitem>
                <para>Pixel</para>
              </listitem>
            </varlistentry>
          </variablelist>

The <varname>fontsFactor</varname> parameter represents a scaling factor
for the font sizes of all texts in the plot (the default is 1.0, meaning no scaling).
If you set this parameter to 0, the program will automatically try to calculate
a scale factor.

The <varname>compression</varname> parameter can be 0 (no compression) or 1 (LZW) and is only effectif for .tif/.tiff images.
It is neglected for all other raster image formats.
</para>

<para>
The function <varname>exportTex</varname> can be used if you need to export to
a TeX file. The <varname>escapeStrings</varname> parameter enables/disables the escaping of
special TeX characters like: $, {, }, ^, etc...
If <varname>True</varname>, the <varname>fontSizes</varname> parameter triggers the export of the original
font sizes in the plot layer.
Otherwise all exported text strings will use the font size specified in the preamble of
the TeX document.
</para>

<para>All the export functions rely on the file name suffix in order to choose the image format.</para>
</sect2>

<sect2 id="Python-MultiLayer">
      <title>Arranging Layers</title>
When you are working with many layers in a 2D plot window, setting the layout of these layers manually can
be a very tedious task. With the help of a simple Python script you can make this task very easy and
automatically manage the layout of the plot window.
For example, here's how you can create a two rows by two columns matrix of layers,
each plot layer having a canvas size (the drawing area) of 400 pixels wide and 300 pixels in height:
<programlisting>
g = newGraph("Test", 4, 2, 2)
g.setLayerCanvasSize(400, 300)
g.arrangeLayers(False, True)
</programlisting>

The <varname>arrangeLayers()</varname> function takes two parameters. The first one specifies
if the layers should be arranged automatically, using a best-layout algorithm, or if the
numbers of rows and columns is fixed by the user. If the value of the second parameter is
<varname>True</varname>, the size of the canvas is fixed by the user and the plot window
will be enlarged or shrunken, according to the user settings. Otherwise the size of the plot
window will be kept and the canvas area of each layer will be automatically adapted to fit this size.
Here's how you can modify the graph created in the previous example, in order to display a row of three
layers, while keeping the size of the plot window unchanged:
<programlisting>
g.setNumLayers(3)
g.setRows(1)
g.setCols(3)
g.arrangeLayers(False, False)
</programlisting>

By default, the space between two neighboring layers as well as the distance between the layers
and the borders of the plot window is set to five pixels. You can change the spacing between the
layers and the margins using the following functions:
<programlisting>
g.setSpacing (x, y)
g.setMargins (left, right, top, bottom)
</programlisting>

Another aspect of the layout management is the alignment of the layers. There are three alignment
flags that you can use for the horizontal alignment (HCenter, Left, Right) and another three for
the vertical alignment (VCenter, Top, Bottom) of the layers.
The following code line aligns the layers with the right edge of the window and centers them vertically in
the available space:
<programlisting>
g.setAlignement(Graph.Right, Graph.VCenter)
</programlisting>

The alignment of the layers can be done with respect to the drawing area between the axes (Graph.AlignCanvases) or with respect
to the whole layer widget (Graph.AlignLayers) and you can specify the alignment policy to use via the following method:
<programlisting>
g.setAlignPolicy(Graph.AlignCanvases)
</programlisting>

A very often needed layout is the one with shared layer axes having linked abscissae
(modifying the x scale for one layer will automatically adjust the scales for all plot layers).
Here's how you can simply create such a 2x2 layers grid, with only a few lines of code:
<programlisting>
g = newGraph("", 4, 2, 2)
g.setSpacing(0, 0)
g.setAlignPolicy(Graph.AlignCanvases)
g.setCommonLayerAxes()
g.arrangeLayers()
g.linkXLayerAxes(True)
</programlisting>

All the examples above suppose that the layers are arranged on a grid, but of course you can add layers
at any position in the plot window. In the examples below the x, y coordinates, in pixels,
refer to the position of the top-left corner of the layer.
The origin of the coordinates system coincides with the top-left corner of the plot window, the y
coordinate increasing towards the bottom of the window. If the width and height of the layer are not specified
they will be set to the default values. The last argument specifies if the default preferences, specified via the
<link linkend="fig-preferences-dialog-5">Preferences dialog</link>, will be used to customize the new layer
 (default value is <varname>False</varname>):
<programlisting>
g = newGraph()
l1 = g.addLayer()
l2 = g.addLayer(215, 20)
l3 = g.addLayer(10, 20, 200, 200)
l4 = g.addLayer(10, 20, 200, 200, True)
</programlisting>

You can remove a plot layer using:
<programlisting>
l = g.layer(num)
g.removeLayer(l)
g.removeActiveLayer()
</programlisting>

As you have already seen, in a plot window the active layer is, by default, the last layer added
to the plot, but you can change it programatically:
<programlisting>
l = g.layer(num)
g.setActiveLayer(l)
</programlisting>

In case you need to perform a repetitive task on all the layers in a plot window, you need to use a for loop
and of course you need to know the number of layers existing on the plot. Here's a small example showing how to
custom the titles of all the layers in the plot window:
<programlisting>
g = graph("Graph1")
layers = g.numLayers()
for i in range (1, layers+1):
	l = g.layer(i)
	l.setTitle("Layer"+QtCore.QString.number(i))
	l.setTitleColor(QtGui.QColor("red"))
	l.setTitleFont(QtGui.QFont("Arial", 14, QtGui.QFont.Bold, True))
	l.setTitleAlignment(QtCore.Qt.AlignLeft)
</programlisting>

Finally, sometimes it might be useful to be able to swap two layers. This can be done with the help of the
following function:
<programlisting>
g.swapLayers(layerNum1, layerNum2)
</programlisting>
</sect2>

<sect2 id="Python-WaterfallPlots">
      <title>Waterfall Plots</title>

The waterfall graph is ideal .  The graph has a pseudo-3D effect, enabling you to see variations in the Z direction.


Waterfall plots are ideal for comparing variations between multiple data sets created under similar conditions.
A pseudo 3D effect is generated by applying an offset to all the data curves in a 2D plot layer.
You can create and customize them using the functions below:
<programlisting>
g = waterfallPlot(table("Table1"), (2, 3, 4))
l = g.activeLayer()
l.setWaterfallOffset(50, 20)# x/y offsets as % of the layer drawing area width/height
l.setWaterfallSideLines(True) # draw side lines for all the data curves
l.setWaterfallFillColor(Qt.lightGray)
g.reverseWaterfallOrder() # reverse the order of the displayed curves
</programlisting>
</sect2>

<sect2 id="Python-Plots3D">
<title>3D Plots</title>
<sect3>
<title>Creating a 3D plot</title>
You can plot 3D analytical functions or parametric surfaces.
For the 3D functions, the only parameters allowed are <varname>x</varname> for the the abscissae values and <varname>y</varname> for the ordinates:
<programlisting>
g = plot3D("sin(x*y)", -10.0, 10.0, -10.0, 10.0, -2.0, 2.0)
</programlisting>
For the parametric surfaces the only parameters allowed are the latitude and the longitude: <varname>u</varname> and <varname>v</varname>. Here's, for example,
how you can plot a sphere:
<programlisting>
g = plot3D("cos(u)*cos(v)", "sin(u)*cos(v)", "sin(v)", -3.14, 3.14, -2, 2)
</programlisting>
You can also create 3D height maps using data from matrices and, of course, you can plot table columns:
<programlisting>
g = plot3D(matrix("Matrix1"), style = 5)
g = plot3D(table("Table1"), "3", style)
</programlisting>
In the case of 3D plots created from matrix data sources the <varname>style</varname> parameter can take
any integer value from 1 to 5, with the following signification:
<variablelist spacing="compact">
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Wireframe style</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Hidden Line style</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>3.</term>
              <listitem>
                <para>Color filled polygons without edges</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>4.</term>
              <listitem>
                <para>Color filled polygons with separately colored edges</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>5.</term>
              <listitem>
                <para>Scattered points (the default style)</para>
              </listitem>
            </varlistentry>
          </variablelist>

For 3D plots created from tables the <varname>style</varname> parameter can take
any integer value from 0 to 3 or the equivalent style values from the following list:

<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Graph3D.Scatter</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Graph3D.Trajectory</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Graph3D.Bars</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>3.</term>
              <listitem>
                <para>Graph3D.Ribbon</para>
              </listitem>
            </varlistentry>
          </variablelist>

An alternative method to create a 3D plot is to create an empty plot window and to assign a data source to it.
As you have already seen a data source can be an analytical function, a matrix or a table.
For large data sets you can increase the drawing speed by reducing the number of points
taken into account. The lower the resolution parameter, the higher the number of points used:
for an integer value of 1, all the data points are drawn.
<programlisting>
g = newPlot3D("test3D")
g.setTitle("My 3D Plot", QtGui.QColor("blue"), QtGui.QFont("Arial",14))
g.setResolution(2)
g.setFunction("sin(x*y)", -10.0, 10.0, -10.0, 10.0, -2.0, 2.0)
#or
g.setData(table("Table1"), "3")
#or
g.setMatrix(matrix("Matrix1"))
</programlisting>

Once a plot is created, you can modify the scales and set the data range to display, using, for example:
<programlisting>
g.setScales(-1.0, 1.0, -10.0, 11.0, -2.0, 3.0)
</programlisting>
</sect3>

<sect3 id="Python-3D-View">
<title>Customizing the view</title>
When a new 3D plot is created, the scene view parameters are set to default values.
Of course, QtiPlot provides functions to customize each aspect of the view.
For example, you can set rotation angles, in degrees, around the X, Y and Z axes, respectively, using:
<programlisting>
g.setRotation(45, 15, 35)
</programlisting>

The following function allows you to shift the plot along the world X, Y and Z axes, respectively:
<programlisting>
g.setShift(3.0, 7.0, -4.0)
</programlisting>

You can also zoom in/out the entire plot as a whole, or you can zoom along a particular axis:
<programlisting>
g.setZoom(10)
g.setScale(0.1, 0.05, 0.3)
</programlisting>

Also, you can automatically detect the zoom values that fit best with the size of the plot window:
<programlisting>
g.findBestLayout()
</programlisting>

You can enable/disable the perspective view mode or animate the view using:
<programlisting>
g.setOrthogonal(False)
g.animate(True)
</programlisting>
</sect3>

<sect3 id="Python-3D-Style">
<title>Plot Styles</title>
The style of the 3D plot can be set using the following functions:
<programlisting>
g.setPolygonStyle()
g.setFilledMeshStyle()
g.showLegend(True)
g.setHiddenLineStyle()
g.setWireframeStyle()
g.setAntialiasing(True)
g.setMeshLineWidth(0.7)
</programlisting>

For scatter plots using points you can specify the radius of the points and their shape:
circles if <varname>smooth</varname> is True, rectangles otherwise.
<programlisting>
g.setDotOptions(10, smooth = True)
g.setDotStyle()
</programlisting>

Other symbols available for scatter plots are: bars
<programlisting>
g.setBarRadius(0.01)
g.setBarLines(False)
g.setFilledBars(True)
g.setBarStyle()
</programlisting>
cones
<programlisting>
g.setConeOptions(radius, quality)
g.setConeStyle()
</programlisting>
and crosses (surrounded by a box frame, if <varname>boxed</varname> is set to True):
<programlisting>
g.setCrossOptions(radius, width, smooth, boxed)
g.setCrossStyle()
</programlisting>
</sect3>

<sect3 id="Python-3D-Projection">
<title>The 2D Projection</title>
By default the floor projection of the 3D surface plot is disabled. You can enable a full 2D projection
or only display the isolines using the following functions:
<programlisting>
g.showFloorProjection()
g.showFloorIsolines()
g.setEmptyFloor()
</programlisting>
</sect3>

<sect3 id="Python-3D-Coordinates">
<title>Customizing the Coordinates System</title>
The coordinates system around the surface plot can be customized to display all the twelve axes,
only three of them or none, respectively, with the help of the following functions:
<programlisting>
g.setBoxed()
g.setFramed()
g.setNoAxes()
</programlisting>

If the axes are enabled, you can set their legends and the distance between the legend and the axes via:
<programlisting>
g.setXAxisLabel("X axis legend")
g.setYAxisLabel("Y axis legend")
g.setZAxisLabel("Z axis legend")
g.setLabelsDistance(30)
</programlisting>

It is possible to set the numerical format and precision of the axes using the function below:
<programlisting>
g.setAxisNumericFormat(axis, format, precision)
</programlisting>
where the first parameter is the index of the axis: 0 for X, 1 for Y and 2 for Z, the second one is the numerical format:
<variablelist spacing="compact">
<varlistentry>
  <term>0.</term>
  <listitem>
	<para>Graph3D.Default: decimal or scientific, depending which is most compact</para>
  </listitem>
</varlistentry>
<varlistentry>
  <term>1.</term>
  <listitem>
	<para>Graph3D.Decimal: 10000.0</para>
  </listitem>
</varlistentry>
<varlistentry>
  <term>2.</term>
  <listitem>
	<para>Graph3D.Scientific: 1e4</para>
  </listitem>
</varlistentry>
<varlistentry>
  <term>3.</term>
  <listitem>
	<para>Graph3D.Engineering: 10k</para>
  </listitem>
</varlistentry>
</variablelist>

and the last parameter is the precision (the number of significant digits).

The following convenience functions are also provided, where you don't have to specify the index of the axis anymore:
<programlisting>
g.setXAxisNumericFormat(1, 3)
g.setYAxisNumericFormat(1, 3)
g.setZAxisNumericFormat(1, 3)
</programlisting>

Also, you can fix the length of the major and minor ticks of an axis:
<programlisting>
g.setXAxisTickLength(2.5, 1.5)
g.setYAxisTickLength(2.5, 1.5)
g.setZAxisTickLength(2.5, 1.5)
</programlisting>
</sect3>

<sect3 id="Python-3D-Grid">
<title>Grid</title>
If the coordinate system is displayed, you can also display a grid around the surface plot.
Each side of the grid can be shown/hidden:
<programlisting>
g.setLeftGrid(True)
g.setRightGrid()
g.setCeilGrid()
g.setFloorGrid()
g.setFrontGrid()
g.setBackGrid(False)
</programlisting>
</sect3>

<sect3 id="Python-3D-Colors">
<title>Customizing the Plot Colors</title>
The default color map of the plot is defined using two colors: red for the maximum data values and
blue for the minimum data values. You can change these default colors:

<programlisting>
g.setDataColors(QtCore.Qt.black, QtCore.Qt.green)
g.update()
</programlisting>

Of course, you can define more complex color maps, using <emphasis>LinearColorMap</emphasis> objects:
<programlisting>
map = LinearColorMap(QtCore.Qt.yellow, QtCore.Qt.blue)
map.setMode(LinearColorMap.FixedColors) # default mode is LinearColorMap.ScaledColors
map.addColorStop(0.2, QtCore.Qt.magenta)
map.addColorStop(0.7, QtCore.Qt.cyan)
g.setDataColorMap(map)
g.update()
</programlisting>

Also, you can use predefined color maps stored in .map files.
A .map file consists of a of 255 lines, each line defining a color coded as RGB values.
A set of predefined color map files can be downloaded from QtiPlot web site, in the "Miscellaneous"
section.
<programlisting>
g.setDataColorMap(fileName)
g.update()
</programlisting>

The colors of all the other plot elements can be customized as shown below. Don't forget to
update the plot in order to display the new colors:
<programlisting>
g.setMeshColor(QtGui.QColor("blue"))
g.setAxesColor(QtGui.QColor("green"))
g.setNumbersColor(QtGui.QColor("black"))
g.setLabelsColor(QtGui.QColor("darkRed"))
g.setBackgroundColor(QtGui.QColor("lightYellow"))
g.setGridColor(QtGui.QColor("grey"))
g.setDataColors(QtGui.QColor("red"), QtGui.QColor("orange"))
g.setOpacity(0.75)
g.update()
</programlisting>
</sect3>

<sect3 id="Python-3D-Export">
<title>Exporting</title>
In order to export a 3D plot you need to specify a file name containing a valid file format extension:
<programlisting>
g.export(fileName)
</programlisting>

This function uses some default export options. If you want to customize the exported image, you should use the
following function in order to export to raster image formats:
<programlisting>
g.exportImage(fileName, int quality = 100, bool transparent = False, dpi = 0, size = QSizeF(), unit = Frame.Pixel, fontsFactor = 1.0, compression = 0)
</programlisting>
where <varname>quality</varname> is a compression factor: the larger its value, the better the quality of the
exported image, but also the larger the file size.
The <varname>dpi</varname> parameter represents the export resolution in pixels per inch (the default is screen resolution),
<varname>size</varname> is the printed size of the image (the default is the size on screen) and
<varname>unit</varname> is the length unit used to express the custom size
and can take one of the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>Inch</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Millimeter</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Centimeter</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>3.</term>
              <listitem>
                <para>Point: 1/72th of an inch</para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>4.</term>
              <listitem>
                <para>Pixel</para>
              </listitem>
            </varlistentry>
          </variablelist>

The <varname>fontsFactor</varname> parameter represents a scaling factor
for the font sizes of all texts in the plot (the default is 1.0, meaning no scaling).
If you set this parameter to 0, the program will automatically try to calculate
a scale factor. The <varname>compression</varname> parameter can be 0 (no compression) or 1 (LZW) and is only effectif for .tif/.tiff images.
It is neglected for all other raster image formats.

<para>
3D plots can be exported to any of the following vector formats: .eps, .ps, .pdf, .pgf and .svg, using
the function below:
<programlisting>
g.exportVector(fileName, textMode = 0, sortMode = 1, size = QSizeF(), unit = Frame.Pixel, fontsFactor = 1.0)
</programlisting>
where <varname>textMode</varname> is an integer value, specifying how texts are handled. It can take
one of the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>All text will be converted to bitmap images (default).</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>Text output in the native output format.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>Text output in additional LaTeX file as an overlay.</para>
              </listitem>
            </varlistentry>
</variablelist>

The <varname>sortMode</varname> parameter is also an integer value and can take one of the following values:
<variablelist spacing="compact">
            <varlistentry>
              <term>0.</term>
              <listitem>
                <para>No sorting at all.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>1.</term>
              <listitem>
                <para>A simple, quick sort algorithm (default).</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>2.</term>
              <listitem>
                <para>BSP sort: best algorithm, but slow.</para>
              </listitem>
            </varlistentry>
</variablelist>

The other parameters have the same meaning as for the export of 2D plots.
</para>
</sect3>
</sect2>

<sect2 id="Python-DataAnalysis">
<title>Data Analysis</title>
<sect3 id="Python-GeneralFunctions">
<title>General Functions</title>
As you will see in the following subsections, the data analysis operations available
in QtiPlot are: convolution/deconvolution, correlation, differentiation, FFT, filtering,
smoothing, fitting and numerical integration of data sets.

Generally, you can declare/initialize an analysis operation using one of the following methods,
depending on the data source, which can be a 2D plot curve or a table:
<programlisting>
op = LogisticFit(graph("Graph1").activeLayer().curve(0), 15.2, 30.9)
op = FFTFilter(graph("Graph1").activeLayer(), "Table1_2", 1.5, 3.9)
op = LinearFit(table("Table1"), "colX", "colY", 10, 100)
</programlisting>

In the first example the data source is a curve <emphasis>Table1_2</emphasis>, plotted
in the active layer of the graph <emphasis>Graph1</emphasis> and the abscissae range is
chosen between 1.5 and 3.9.
In the second example the data source is a table <emphasis>Table1</emphasis>.
The abscissae of the data set are stored in the column called <emphasis>colX</emphasis>
and the ordinates in the column <emphasis>colY</emphasis>. The data range is
chosen between the 10th row and the row with the index 100. If you don't specify the row range,
by default the whole table will be used.

Not all operations support curves as data sources, like for example:
convolution/deconvolution and correlation. For these operations only table columns can be used
as data sources for the moment.

<para>Once you have initialized an operation, you can still change its input data via
the following functions:</para>
<programlisting>
op.setDataFromCurve(graph("Graph2").activeLayer().curve(1), 10.5, 20.1)
op.setDataFromCurve("Table1_energy", 10.5, 20.1, graph("Graph2").activeLayer())
op.setDataFromTable(table("Table1"), "colX", "colY", 10, 100)
</programlisting>

You don't have to specify a plot layer in the setDataFromCurve() function, if the analysis operation has
already been initialized by specifying a curve on an existing graph and you just want to treat another
curve from the same plot layer.

<para>Also, when performing analysis tasks via Python scripts, there are several utility functions that
can be called for all operations. For example you can disable any graphical output from an operation
or you can redirect the output to the plot layer of your choice: </para>
<programlisting>
op.enableGraphicsDisplay(False)
op.enableGraphicsDisplay(True, graph("Graph2").activeLayer())
</programlisting>

Let's assume that you need to perform a specific operation <varname>op</varname>,
which analyzes your data and at the end, displays a result curve.
For this kind of operations, you can customize the number of points in the resulting curve
and its color:
<programlisting>
op.setOutputPoints(int)
op.setColor(int)
op.setColor("green")
</programlisting>
Colors can be specified by their names or as integer values, from 0 to 23,
each integer corresponding to a predefined color: 0 - "black", 1 - "red", 2 - "green", 3 - "blue",
4 - "cyan", 5 - "magenta", 6 - "yellow", 7 - "darkYellow", 8 - "navy", 9 - "purple", etc ...

<para>Most of the time, a new table is also created as a result of a data analysis operation.
This table stores the data displayed by the result curve and is hidden by default,
but you can interact with it via the following function:
<programlisting>
t = op.resultTable()
</programlisting></para>

After the initialization of an analysis operation, which consists of setting the data source,
the data range and some other properties, like color, number of points, etc..., you can execute
it via a call to its run() function:
<programlisting>
op.run()
</programlisting>
For data fitting operations, there's an alias for the run() function which is: fit().
</sect3>

<sect3 id="Python-Correlation">
<title>Correlation, Convolution/Deconvolution</title>
Assuming you have a table named "Table1", here's how you can calculate the convolution of two of its columns,
"Table1_B" and "Table1_C":
<programlisting>
conv = Convolution(table("Table1"),  "B", "C")
conv.setColor("green")
conv.run()
</programlisting>
The deconvolution and the correlation of two data sets can be done using a similar syntax:
<programlisting>
dec = Deconvolution(table("Table1"),  "B", "C")
dec.run()

cor = Correlation(table("Table1"),  "B", "C", 10, 200)
cor.setColor("green")
cor.run()
</programlisting>
</sect3>

<sect3 id="Python-Differentiation">
<title>Differentiation</title>
Assuming you have a Graph named "Graph1" containing one curve
(on its active layer), here's how you can differentiate this curve within a defined x interval,
[2,10] in this case:
<programlisting>
diff = Differentiation(graph("Graph1").activeLayer().curve(0), 2, 10)
diff.run()
</programlisting>
The result of these code sequence would be a new plot window displaying the derivative of the initial curve.
The numerical derivative is calculated using a five terms formula.
</sect3>

<sect3 id="Python-FFT">
<title>FFT</title>
Assuming you have a graph named "Graph1" containing one curve on its active layer and having a
periodicity of 0.1 in the time domain,
a FFT will allow you to extract its characteristic frequencies.
The results will be stored in a hidden table named "FFT1".

<programlisting>
fft = FFT(graph("Graph1").activeLayer().curve(0))
fft.normalizeAmplitudes(False)
fft.shiftFrequencies(False)
fft.setSampling(0.1)
fft.run()
</programlisting>

By default the calculated amplitudes are normalized
and the corresponding frequencies are shifted in order to obtain a centered x-scale.
If we want to recover the initial curve with the help of the inverse transformation, we
mustn't modify the amplitudes and the frequencies. Also the sampling parameter must be set to
the inverse of the time period, that is 10. Here's how we can perform the inverse FFT, using the "FFT1" table,
in order to recover the original curve:

<programlisting>
ifft = FFT(table("FFT1"), "Real", "Imaginary")
ifft.setInverseFFT()
ifft.normalizeAmplitudes(False)
ifft.shiftFrequencies(False)
ifft.setSampling(10)
ifft.run()
</programlisting>

You can also perform 2D fast Fourrier transforms on matrices.
The FFT routine takes in this case the following parameters:
<emphasis>rm</emphasis> - specifies the real part input matrix,
<emphasis>im</emphasis> - specifies the imaginary part input matrix,
<emphasis>inverse</emphasis> - specifies the direction of the FFT,
<emphasis>DCShift</emphasis> - if this is true, the DC component will be put in the center of the result matrix,
otherwise, the DC component will locate at four corners of the result matrix,
<emphasis>norm</emphasis> - specifies whether or not to normalize the amplitudes to 1,
<emphasis>outputPower2Sizes</emphasis> - forces output matrices whose sizes are integer powers of 2 (zero padding is used to initialize the missing cells)
<programlisting>
fft = FFT(Matrix *rm, Matrix *im = NULL, bool inverse = False, bool DCShift = True, bool norm = False, bool outputPower2Sizes = True)
</programlisting>

Here's how you can perform the 2D FFT of a matrix called "Matrix1",
and the inverse FFT in order to recover the original image:

<programlisting>
from qti import *
m = matrix("Matrix1")
m.setViewType(Matrix.ImageView) # make sure the matrix is displayed as image

fft = FFT(m)
fft.run()
fft.amplitudesMatrix().resize(500, 400)

rMatrix = fft.realOutputMatrix()
rMatrix.hide()
iMatrix = fft.imaginaryOutputMatrix()
iMatrix.hide()

ifft = FFT(rMatrix, iMatrix, True)
ifft.run()
ifft.realOutputMatrix().hide()
ifft.imaginaryOutputMatrix().hide()
</programlisting>
</sect3>

<sect3 id="Python-Filtering">
<title>FFT Filters</title>
In this section, it will be assumed that you have a signal displayed in a graph ("Graph1", on its active layer).
This signal has a power spectrum with high and low frequencies.
You can filter some of these frequencies according to your needs, using a FFTFilter.
Here's how you can cut all the frequencies lower than 1 Hz:
<programlisting>
filter = FFTFilter(graph("Graph1").activeLayer().curve(0), FFTFilter.HighPass)
filter.setCutoff(1)
filter.run()
</programlisting>

Here's how you can cut all the frequencies lower than 1.5 Hz and higher than 3.5 Hz.
In the following example the continuous component of the signal is also removed:
<programlisting>
filter.setFilterType(FFTFilter.BandPass)
filter.enableOffset(False)
filter.setBand(1.5, 3.5)
filter.run()
</programlisting>

Other types of FFT filters available in QtiPlot are: low pass (<varname>FFTFilter.LowPass</varname>)
and band block (<varname>FFTFilter.BandBlock</varname>).
</sect3>
<sect3 id="Python-Fitting">
<title>Fitting</title>
        Assuming you have a graph named "Graph1" displaying a curve entitled "Table1_2" on its active layer,
        a minimal Fit example would be:
        <programlisting>
f = GaussFit(graph("Graph1").activeLayer().curve(0))
f.guessInitialValues()
f.fit()
	  </programlisting> This creates a new GaussFit object on the curve, lets it guess
        the start parameters and does the fit. The following fit types are
        supported: <itemizedlist>
            <listitem>
              <para>LinearFit(curve)</para>
            </listitem>

            <listitem>
              <para>PolynomialFit(curve, degree=2, legend=False)</para>
            </listitem>

            <listitem>
              <para>ExponentialFit(curve, growth=False)</para>
            </listitem>

            <listitem>
              <para>TwoExpFit(curve)</para>
            </listitem>

            <listitem>
              <para>ThreeExpFit(curve)</para>
            </listitem>

            <listitem>
              <para>GaussFit(curve)</para>
            </listitem>

            <listitem>
              <para>GaussAmpFit(curve)</para>
            </listitem>
            <listitem>
              <para>LorentzFit(curve)</para>
            </listitem>
			<listitem>
              <para>LogisticFit(curve)</para>
            </listitem>
            <listitem>
              <para>SigmoidalFit(curve)</para>
            </listitem>
            <listitem>
              <para>NonLinearFit(curve)</para>
		    <programlisting>
f = NonLinearFit(layer, curve)
f.setFormula(formula_string)
f.save(fileName)
		    </programlisting>
            </listitem>
            <listitem>
		    <para>PluginFit(curve)</para>
		    <programlisting>
f = PluginFit(curve)
f.load(pluginName)
		    </programlisting>
            </listitem>
          </itemizedlist> For each of these, you can optionally restrict the X
        range that will be used for the fit, like in <programlisting>
f = LinearFit(graph("Graph1").activeLayer().curve(0), 2, 7)
f.fit()
	  </programlisting>

You can also restrict the search range for any of the fit parameters:
<programlisting>
f = NonLinearFit(graph("Graph1").activeLayer().curve(0))
f.setFormula("a0+a1*x+a2*x*x")
f.setParameterRange(parameterIndex, start, end)
</programlisting>

All the settings of a non-linear fit can be saved to an XML file and restored later one, using this file,
for a faster editing process. Here's for example how you can save the above fit function:
<programlisting>
f.save("/fit_models/poly_fit.txt")
</programlisting>
and how you can use this file during another fitting session, later on:
<programlisting>
f = NonLinearFit(graph("Graph1").activeLayer(), "Table1_2")
f.load("/fit_models/poly_fit.txt")
f.fit()
</programlisting>

If your script relies on a specific numbering of the fit parameters use setParameters() before setting
the formula and switch of automatic detection of the fit parameters when the fit formula is set:
<programlisting>
f.setParameters("a2","a0","a1")
f.setFormula("a0+a1*x+a2*x*x",0)
</programlisting>
        <para>After creating the Fit object and before calling its fit()
        method, you can set a number of parameters that influence the fit:
        <programlisting>
f.setDataFromTable(table("Table4"), "w", "energy", 10, 200, True) <lineannotation>change data source (last parameter enables/disables data sorting)</lineannotation>
f.setDataFromCurve(curve)			<lineannotation>change data source</lineannotation>
f.setDataFromCurve(curveTitle, graph)		<lineannotation>change data source</lineannotation>
f.setDataFromCurve(curve, from, to)		<lineannotation>change data source</lineannotation>
f.setDataFromCurve(curveTitle, from, to, graph)	<lineannotation>change data source</lineannotation>
f.setInterval(from, to)				<lineannotation>change data range</lineannotation>
f.setInitialValue(number, value)
f.setInitialValues(value1, ...)
f.guessInitialValues()
f.setAlgorithm(algo) # algo = Fit.ScaledLevenbergMarquardt, Fit.UnscaledLevenbergMarquardt, Fit.NelderMeadSimplex
f.setWeightingData(method, colname) # method = Fit.NoWeighting, Fit.Instrumental, Fit.Statistical, Fit.Dataset, Fit.Direct
f.setTolerance(tolerance)
f.setOutputPrecision(precision)
f.setMaximumIterations(number)
f.scaleErrors(yes = True)
f.setColor("green")			<lineannotation>change the color of the result fit curve to green (default color is red)</lineannotation>
	  </programlisting></para>

After you've called fit(), you have a number of possibilities
for extracting the results: <programlisting>
f.results()
f.errors()
f.residuals()
f.dataSize()
f.numParameters()
f.parametersTable("params")
f.covarianceMatrix("cov")
</programlisting>

There are a number of statistical functions allowing you to test the goodness of the fit:
<programlisting>
f.chiSquare()
f.rSquare()
f.adjustedRSquare()
f.rmse() # Root Mean Squared Error
f.rss()  # Residual Sum of Squares
</programlisting>

Also you can display the confidence and the prediction limits for the fit, using
a custom confidence level:
<programlisting>
f.showPredictionLimits(0.95)
f.showConfidenceLimits(0.95)
</programlisting>

Confidence limits for individual fit parameters can be calculated using:
<programlisting>
f.lcl(parameterIndex, confidenceLevel)
f.ucl(parameterIndex, confidenceLevel)
</programlisting>
where <varname>parameterIndex</varname> is a value between zero and f.numParameters() - 1.

<para>It is important to know that QtiPlot can generate an analytical formula
for the resulting fit curve or a normal plot curve with data stored in a hidden table.
You can choose either of these two output options, before calling the fit() instruction, using:
<programlisting>
f.generateFunction(True, points=100)
</programlisting>
</para>

If the first parameter of the above function is set to True,
QtiPlot will generate an analytical function curve. If the <varname>points </varname> parameter
is not specified, by default the function will be estimated over 100 points.
You can get the analytical formula of the fit curve via a call to resultFormula():
<programlisting>
formula = f.resultFormula()
print(formula)
</programlisting>

If the first parameter of generateFunction() is set to False, QtiPlot will create a hidden data
table containing the same number of points as the data set/curve to be fitted (same abscissae).
You can interact with this table and extract the data points of the result fit curve using:
<programlisting>
t = f.resultTable()
</programlisting>
</sect3>

<sect3 id="Python-Integration">
<title>Integration</title>
With the same assumptions as above, here's how you can integrate a curve within a given interval:
<programlisting>
integral = Integration(graph("Graph1").activeLayer().curve(0), 2, 10)
integral.run()
result = integral.area()
</programlisting>

The script bellow shows how to perform an integration on a data set from a table:
<programlisting>
i = Integration(table("Table1"), "Table_1", "Table_2", 3, 20, True)# sorted data range from row 3 to 20
i.enableGraphicsDisplay(False)
i.run()
result = i.area()
</programlisting>

<para>As you can see from the above examples, the numerical value of the integral can be obtained
via the <varname>area()</varname> function.</para>
</sect3>

<sect3 id="Python-Interpolation">
<title>Interpolation</title>
The interpolation is used to generate a new data curve with a high number of points
from an existing data set. Here's an example:
<programlisting>
interpolation = Interpolation(graph("Graph1").activeLayer().curve(0), 2, 10, Interpolation.Linear)
interpolation.setOutputPoints(10000)
interpolation.setColor("green")
interpolation.run()
</programlisting>
The simplest interpolation method is the linear method. There are two other methods available:
<varname>Interpolation.Akima</varname> and <varname>Interpolation.Cubic</varname>.
You can choose the interpolation method using:
<programlisting>
interpolation.setMethod(Interpolation.Akima)
</programlisting>
</sect3>

<sect3 id="Python-Smooth">
<title>Smoothing</title>
Assuming you have a graph named "Graph1" with an irregular curve entitled
"Table1_2" (on its active layer). You can smooth this curve using a SmoothFilter:
<programlisting>
smooth = SmoothFilter(graph("Graph1").activeLayer().curve(0), SmoothFilter.Average)
smooth.setSmoothPoints(10)
smooth.run()
</programlisting>

The default smoothing method is the mowing window average. Other smoothing methods are the
<varname>SmoothFilter.FFT</varname>, <varname>SmoothFilter.Lowess</varname> and <varname>SmoothFilter.SavitzkyGolay</varname>. Here's an example
of how to use the last two methods:
<programlisting>
smooth.setMethod(SmoothFilter.Lowess)
smooth.setLowessParameter(0.2, 2)
smooth.run()
</programlisting>
<programlisting>
smooth.setSmoothPoints(5,5)
smooth.setMethod(SmoothFilter.SavitzkyGolay)
smooth.setPolynomOrder(9)
smooth.run()
</programlisting>
</sect3>
</sect2>

<sect2 id="Python-Statistics">
<title>Statistics</title>

<sect3 id="Python-DescriptiveStatistics">
<title>Descriptive Statistics</title>
<programlisting>
stats = Statistics("Table1_2")
stats.run()

print stats.mean()
print stats.variance()
print stats.standardDeviation()
print stats.standardError()
</programlisting>
</sect3>

For all the statistic test below, once you have created a test object, you can use the following methods:

<programlisting>
test.showResultsLog(False) # disable the logging of the results
test.showDescriptiveStatistics(False) # disable the display of the descriptive statistics results
test.run()

print test.statistic()
print test.pValue()
print test.logInfo()

t = test.resultTable("MyResultTable") # Returns a pointer to the table created to display the results (the table name is optional)
</programlisting>

<sect3 id="Python-tTest">
<title>Hypothesis Testing - Student's t-Test</title>
<programlisting>
test = tTest(15.2, 0.05, "Table1_2") # One sample test, test mean = 15.2, significance level = 0.05
test.run()

test.setTestValue(15.0)
test.setSignificanceLevel(0.5)
test.setTail(tTest.Left) # or tTest.Right, or tTest.Both (default value)
test.run()

print test.t() # same as test.statistic()
print test.dof() # degrees of freedom
print test.power(0.5)
print test.power(0.5, 50) # alternative sample size = 50
print test.pValue()
print test.lcl(90) # lower confidence limit for mean
print test.ucl(90) # upper confidence limit for mean

test = tTest(15.2, 0.05, "Table1_1", "Table1_2", True) # Two sample paired test
print test.logInfo()

test = tTest(15.2, 0.05, "Table1_1", "Table1_2") # Two sample independent test
test.run()

test.setSample1("Table2_1")
test.setSample2("Table3_2", True) # Two sample paired test
test.run()
</programlisting>
</sect3>

<sect3 id="Python-ChiSquareTest">
<title>One Sample Test for Variance (Chi-Square Test)</title>
<programlisting>
test = ChiSquareTest(88.2, 0.05, "Table1_2") # Test variance = 88.2, significance level = 0.05
test.run()

print test.chiSquare() # same as test.statistic()
print test.pValue()
print test.logInfo()
</programlisting>
</sect3>

<sect3 id="Python-ShapiroWilkTest">
<title>Normality Test (Shapiro - Wilk)</title>
<programlisting>
test = ShapiroWilkTest("Table3_1")
test.setSignificanceLevel(0.1)
test.run()

print test.w() # same as test.statistic()
print test.pValue()
print test.logInfo()
</programlisting>
</sect3>

<sect3 id="Python-OneWayANOVA">
<title>One-Way ANOVA</title>
Please read the
<ulink url="http://www.stat.tamu.edu/~aredd/tamuanova/tamu_anova.pdf">documentation of the TAMUANOVA library</ulink>
 for more details.

<programlisting>
test = Anova()
test.setSignificanceLevel(0.1) # default level is 0.05
test.addSample("Table1_1");
test.addSample("Table1_2");
test.addSample("Table1_3");
test.run()

print test.fStat() # F statistic = ssm/sse (same as test.statistic())
print test.pValue()
print test.ssm() # "between-group" sum of squares
print test.sse() # "within-group" sum of squares
print test.sst() # total sum of squares

test.showDescriptiveStatistics(False)
print test.logInfo()
</programlisting>
</sect3>

<sect3 id="Python-TwoWayANOVA">
<title>Two-Way ANOVA</title>
Please read the
<ulink url="http://www.stat.tamu.edu/~aredd/tamuanova/tamu_anova.pdf">documentation of the TAMUANOVA library</ulink>
 for more details.

<programlisting>
test = Anova(True)
test.addSample("Table1_1", 1, 1) # Level factor A = 1, level factor B = 1
test.addSample("Table1_2", 1, 2) # Level factor A = 1, level factor B = 2
test.addSample("Table1_3", 2, 1) # Level factor A = 2, level factor B = 1
test.addSample("Table1_4", 2, 2) # Level factor A = 2, level factor B = 2
test.setAnovaTwoWayModel(2) # Fixed model = 0, Random model = 1, Mixed model = 2
test.run()

print test.fStatA() # F statistic for factor A
print test.fStatB() # F statistic for factor B
print test.fStatAB() # F statistic for the interaction
print test.pValueA() # P value for factor A
print test.pValueB() # P value for factor B
print test.pValueAB() # P value for the interaction
print test.ssa() # sum of squares for factor A
print test.ssb() # sum of squares for factor B
print test.ssab() # sum of squares for the interaction
print test.msa() # mean square value for factor A
print test.msb() # mean square value for factor B
print test.msab() # mean square value for the interaction

print test.logInfo()
</programlisting>
</sect3>
</sect2>

<sect2 id = "Python-Notes">
<title>Working with Notes</title>
<para>
The following functions are available when dealing with multi-tab notes:
</para>

<programlisting>
setAutoexec(on = True)

text()
setText(text)

exportPDF(fileName)
saveAs(fileName)
importASCII(fileName)

showLineNumbers(on = True)

setFont(QFont f)
setTabStopWidth(int length)

tabs()
addTab()
removeTab(tabIndex)
renameTab(tabIndex, title)

e = editor(int index)
e = currentEditor()
</programlisting>
</sect2>

<sect2 id="Python-QtDialogs">
<title>Using Qt's dialogs and classes</title>
Let's assume that you have a lot of ASCII data files to analyze.
Furthermore, let's suppose that these files were created
during several series of measurements, each measurement generating a set
of files identified by a certain string in the file name, like for example: "disper1".
In order to analyze these files, you need first of all to import them into tables.
The following code snippet shows how to automate this task using Qt dialogs and convenience classes:

<programlisting>
# Pop-up a file dialog allowing to chose the working folder:
dirPath = QtGui.QFileDialog.getExistingDirectory(qti.app, "Choose Working Folder", "/test/")

# Create a folder object using Qt's QDir class:
folder = QtCore.QDir(dirPath)

# Pop-up a text input dialog allowing to chose the file naming pattern:
namePattern = QtGui.QInputDialog.getText(qti.app, "Enter Pattern", "Text: ", QtGui.QLineEdit.Normal, "disper1")

# Get the list of file names in the working directory containing the above pattern:
fileNames = folder.entryList (QtCore.QStringList ("*_" + namePattern[0] + "*.dat"))

# Import each file into a new project table:
for i in range (0, lst.count()):
    t = newTable()
    t.importASCII(dirPath + fileNames[i], " ", 0, False, True, True)
</programlisting>
For a detailed description of all the dialogs and utility classes provided by Qt/PyQt
please take a look at the
<ulink url="http://www.riverbankcomputing.com/static/Docs/PyQt4/html/classes.html">PyQt documentation</ulink>.
</sect2>

<sect2 id="Python-QtDesigner">
<title>Using Qt Designer for easy creation of custom user dialogs</title>
Writing and designing user dialogs can be a very complicated task.
The QtDesigner application provided by the Qt framework makes it easy and very pleasant.
It allows you to design widgets, dialogs or complete main windows using on-screen forms and a simple drag-and-drop interface.
Qt Designer uses XML .ui files to store designs.
Once you have finished the design process you can load and use an .ui file in your Python scripts
with the help of the <varname>uic</varname> module.

<para>
As an example, suppose that we have created a test dialog containing an input QDoubleSpinBox called "valueBox"
and a QPushButton called "okButton". On pressing this button, we would like to create a new table displaying
the input value in its first cell. We have saved this dialog to a file called "myDialog.ui".
A minimalistic approach is shown in the small script below:
</para>

<programlisting>
from PyQt4 import uic

def createTable():
	t = newTable()
	t.setCell(1, 1, ui.valueBox.value())

ui = uic.loadUi("myDialog.ui")
ui.connect(ui.okButton, QtCore.SIGNAL("clicked()"),  createTable)
ui.show()
</programlisting>

For more details about how to use .ui files in your Python scripts please read the
<ulink url="http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/pyqt4ref.html#using-the-generated-code">PyQt4 documentation</ulink>.
</sect2>

<sect2 id="Python-AutomationExample">
<title>Task automation example</title>
Below you can find a detailed example showing how to completely automatize tasks in QtiPlot.
It can be used in order to verify the accuracy of the curve fitting algorithms in QtiPlot. The data used
in this example is retrieved from the <ulink url="http://www.itl.nist.gov/div898/strd/">
Statistical Reference Datasets Project of the National Institute of Standards and Technology (NIST)</ulink>.

In order to run this example, you need an internet connection, since the script will try to download all the
<ulink url="http://www.itl.nist.gov/div898/strd/nls/nls_main.shtml">nonlinear regression test files </ulink> from the Statistical Reference Datasets Project.

<programlisting>
import urllib, re, sys

# Pop-up a file dialog allowing to chose a destination folder:
dirPath = QtGui.QFileDialog.getExistingDirectory(qti.app, "Choose Destination Folder")

saveout = sys.stdout
# create a log file in the destination folder
fsock = open(dirPath + "/" + "results.txt", "w")
sys.stdout = fsock

# on Unix systems you can redirect the output directly to a console by uncommenting the line below:
#sys.stdout = sys.__stdout__

# make sure that the decimal separator is the dot character
qti.app.setLocale(QtCore.QLocale.c())

host = "http://www.itl.nist.gov/div898/strd/nls/data/LINKS/DATA/"
url = urllib.urlopen(host)
url_string = url.read()
p = re.compile( '\w{,}.dat">' )
iterator = p.finditer( url_string )
for m in iterator:
	name = (m.group()).replace("\">", "")
	if (name == "Nelson.dat"):
		continue

	url = host + name
	print  "\nRetrieving file: " + url
	path = dirPath + "/" + name
	urllib.urlretrieve( url, path ) # retrieve .dat file to specified location

	file = QtCore.QFile(path)
	if file.open(QtCore.QIODevice.ReadOnly):
		ts = QtCore.QTextStream(file)
		name = name.replace(".dat", "")
		changeFolder(addFolder(name)) #create a new folder and move to it
		formula = ""
		parameters = 0
		initValues = list()
		certifiedValues = list()
		standardDevValues = list()
		xLabel = "X"
		yLabel = "Y"

		while (ts.atEnd() == False):
			s = ts.readLine().simplified()

			if (s.contains("(y = ")):
				lst = s.split("=")
				yLabel = lst[1].remove(")")

			if (s.contains("(x = ")):
				lst = s.split("=")
				xLabel = lst[1].remove(")")

			if (s.contains("Model:")):
				s = ts.readLine().simplified()
				lst = s.split(QtCore.QRegExp("\\s"))
				s = lst[0]
				parameters = s.toInt()[0]
				ts.readLine()
				if (name == "Roszman1"):
					ts.readLine()
					formula = ts.readLine().simplified()
				else:
					formula = (ts.readLine() + ts.readLine() + ts.readLine()).simplified()
				formula.remove("+ e").remove("y =").replace("[", "(").replace("]", ")")
				formula.replace("**", "^").replace("arctan", "atan")

			if (s.contains("Starting")):
				ts.readLine()
				ts.readLine()
				for i in range (1, parameters + 1):
					s = ts.readLine().simplified()
					lst = s.split(" = ")
					s = lst[1].simplified()
					lst = s.split(QtCore.QRegExp("\\s"))
					initValues.append(lst[1])
					certifiedValues.append(lst[2])
					standardDevValues.append(lst[3])

			if (s.contains("Data: y")):
				row = 0
				t = newTable(name, 300, 2)
				t.setColName(1, "y")
				t.setColumnRole(1, Table.Y)
				t.setColName(2, "x")
				t.setColumnRole(2, Table.X)
				while (ts.atEnd() == False):
					row = row + 1
					s = ts.readLine().simplified()
					lst = s.split(QtCore.QRegExp("\\s"))
					t.setText(1, row, lst[0])
					t.setText(2, row, lst[1])

				g = plot(t, t.colName(1), Layer.Scatter).activeLayer()
				g.setTitle("Data set: " + name + ".dat")
				g.setAxisTitle(Layer.Bottom, xLabel)
				g.setAxisTitle(Layer.Left, yLabel)

				f = NonLinearFit(g, name + "_" + t.colName(1))
				if (f.setFormula(formula) == False) :
					file.close()
					changeFolder(rootFolder())
					continue

				f.scaleErrors()
				for i in range (0, parameters):
					f.setInitialValue(i, initValues[i].toDouble()[0])
				f.fit()
				g.removeLegend()
				f.showLegend()
				print  "QtiPlot Results:\n" + f.legendInfo()

				print  "\nCertified Values:"
				paramNames = f.parameterNames()
				for i in range (0, parameters):
					print  '%s = %s +/- %s' % (paramNames[i], certifiedValues[i], standardDevValues[i])

				print  "\nDifference with QtiPlot results:"
				results = f.results()
				for i in range (0, parameters):
					diff = fabs(results[i] - certifiedValues[i].toDouble()[0])
					print  'db%d = %6g' % (i+1, diff)

				file.close()
				changeFolder(rootFolder())

newNote("ResultsLog").importASCII(dirPath + "/" + "results.txt")
saveProjectAs(dirPath + "/" + "StRD_NIST.qti")
sys.stdout = saveout
fsock.close()
</programlisting>
</sect2>

<sect2 id="Python-Scope-Changes">
<title>Scope Changes</title>
<para>In recent versions the scope rules were changed to match standard Python:
  <itemizedlist>
    <listitem>The keyword "global" refers to the module, e.g. a particular script window or column script.
    Outside of any function, this is the default namespace, so "global x" has no effect.  Inside a function,
    "global x" refers to <varname>x</varname> in the module namespace.
    Previously, "global" referred to QtiPlot's global variables, and module-level variables were inaccessible
    from inside a function, unless marked global.</listitem>
    <listitem>To read and write QtiPlot's global variables, use the new special variable <varname>globals</varname>:<programlisting
      width="40">
globals.myvar = 5
print globals.myvar
      </programlisting><varname>globals</varname> is shared among all modules.</listitem>
  </itemizedlist>
</para><para>If a script has any "global" declaration outside of a function, QtiPlot uses the old scope rules.
Existing scripts should keep working, but for best results, update your scripts:
  <itemizedlist>
    <listitem>If a "global" variable <varname>x</varname> is used only within one script, delete any "global x"
   that is outside of a function.</listitem>
    <listitem>If a "global" variable needs to be accessed outside the script that defined it, change<programlisting
      width="40">
global x
x = 5
      </programlisting>to<programlisting>
globals.x = 5
   </programlisting>and replace all references to <varname>x</varname> with <varname>globals.x</varname></listitem>
  </itemizedlist>
</para>
</sect2>

<sect2 id="QtiPlot-Python-API">
<title>QtiPlot/Python API</title>
The complete QtiPlot/Python API can be consulted
<ulink url="http://soft.proindependent.com/doc/manual-en/Python-API/html/index.html">here</ulink>.
</sect2>

<sect2 id="PyQt-Class-Reference">
<title>PyQt Class Reference</title>
The complete PyQt class reference can be consulted
<ulink url="http://www.riverbankcomputing.com/static/Docs/PyQt4/html/classes.html">here</ulink>.
</sect2>
</sect1>
