[med-svn] [pyscanfcs] 01/04: Imported Upstream version 0.2.3

Alex Mestiashvili malex-guest at moszumanska.debian.org
Thu Feb 19 16:35:58 UTC 2015


This is an automated email from the git hooks/post-receive script.

malex-guest pushed a commit to branch master
in repository pyscanfcs.

commit ac037db790a61474cc501b8855eae9a71aa9a8ce
Author: Alexandre Mestiashvili <alex at biotec.tu-dresden.de>
Date:   Wed Feb 18 13:35:03 2015 +0100

    Imported Upstream version 0.2.3
---
 ChangeLog.txt                                      |    8 +
 MANIFEST.in                                        |    2 +-
 PyScanFCS_doc.pdf                                  |  Bin 452087 -> 0 bytes
 README.md                                          |    2 +-
 bin/pyscanfcs                                      |   22 +-
 doc/Bibliography.bib                               |    5 +-
 doc/PyScanFCS_doc_content.tex                      |   29 +-
 .../PyScanFCS.icns                                 |  Bin
 .../PyScanFCS.ico                                  |  Bin
 .../PyScanFCS_linux.spec                           |   11 +-
 .../PyScanFCS_mac.spec                             |    7 +-
 freeze_pyinstaller/PyScanFCS_win7.spec             |   63 +
 freeze_pyinstaller/README.md                       |   22 +
 freeze_pyinstaller/debian_ubuntu_bundle_script.sh  |   84 +
 .../macOSx_script_starter.sh                       |    0
 freeze_pyinstaller/win7_32bit_bundle_script.bat    |    5 +
 freeze_pyinstaller/win7_innosetup.iss.dummy        |  113 ++
 misc/MakeTestDat_SFCS.py                           |   23 +-
 pyinstaller-howto/PyScanFCS_win.spec               |   21 -
 pyinstaller-howto/README.md                        |   22 -
 pyinstaller-howto/macOSx_10.6.8_bundle_script.sh   |   24 -
 .../ubuntu12.04_amd64_bundle_script.sh             |   42 -
 .../windowsXP_32bit_bundle_script.bat              |    4 -
 pyscanfcs/PyScanFCS.py                             | 2123 +-------------------
 pyscanfcs/SFCSnumeric.pyx                          |  261 ++-
 pyscanfcs/__init__.py                              |   12 +-
 pyscanfcs/__main__.py                              |    6 +-
 pyscanfcs/doc.py                                   |   77 +-
 pyscanfcs/{PyScanFCS.py => main.py}                |  226 ++-
 pyscanfcs/misc.py                                  |  218 +-
 pyscanfcs/uilayer.py                               |  560 ++++++
 setup.py                                           |   14 +-
 32 files changed, 1500 insertions(+), 2506 deletions(-)

diff --git a/ChangeLog.txt b/ChangeLog.txt
old mode 100755
new mode 100644
index ec5bdc9..eca64bf
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,11 @@
+0.2.3
+ - New tool to create artificial .dat files for testing
+ - A couple of minor bug fixes
+ - Exceptions are now handled by wxPython
+ - Under the hood:
+   - Updated repository structure
+   - Relative imports
+   - Build machine is now Windows 7
 0.2.2
  - Added button 'full time interval'
  - This is the first version that uses the external module `multipletau`
diff --git a/MANIFEST.in b/MANIFEST.in
index 963e634..b40faed 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,7 +1,7 @@
 include doc/*.tex
 include doc/*.bib
+include doc/*.pdf
 include pyscanfcs/*.pyx
 include doc/Images/*
 include Readme.txt
 include ChangeLog.txt
-include PyScanFCS_doc.pdf
diff --git a/PyScanFCS_doc.pdf b/PyScanFCS_doc.pdf
deleted file mode 100644
index db50648..0000000
Binary files a/PyScanFCS_doc.pdf and /dev/null differ
diff --git a/README.md b/README.md
index 66425f8..53b0c47 100644
--- a/README.md
+++ b/README.md
@@ -21,5 +21,5 @@ For further information, please visit the PyScanFCS homepage at
 [http://pyscanfcs.craban.de](http://pyscanfcs.craban.de).
 
 - [Download the latest version](https://github.com/paulmueller/PyScanFCS/releases)
-- [Documentation](https://github.com/paulmueller/PyScanFCS/raw/master/PyScanFCS_doc.pdf)
+- [Documentation](https://github.com/paulmueller/PyScanFCS/wiki/PyScanFCS_doc.pdf)
 - [Using Cython on Windows XP](https://github.com/paulmueller/PyScanFCS/wiki/Using-Cython-on-Windows-XP)
diff --git a/bin/pyscanfcs b/bin/pyscanfcs
index f1be3df..d3ef63c 100755
--- a/bin/pyscanfcs
+++ b/bin/pyscanfcs
@@ -1,18 +1,4 @@
-#!/bin/sh
-# go to script directory (necessary for relative paths with pip)
-cd $(dirname "$0")
-# debian
-if [ -f "/usr/share/pyshared/pyscanfcs/PyScanFCS.py" ]
-then
-    python /usr/share/pyshared/pyscanfcs/PyScanFCS.py
-elif [ -f "/usr/local/lib/python2.7/dist-packages/pyscanfcs/PyScanFCS.py" ]
-# pip
-then
-    python /usr/local/lib/python2.7/dist-packages/pyscanfcs/PyScanFCS.py
-# pip and virtualenv
-elif [ -f "../lib/python2.7/site-packages/pyscanfcs/PyScanFCS.py" ]
-then
-    python ../lib/python2.7/site-packages/pyscanfcs/PyScanFCS.py
-else
-    echo "Could not find PyScanFCS. Please notify the author."
-fi
+#!/bin/bash
+# go to this directory to prevent execution of a git checkout
+cd "$(dirname "$0")"
+python -m pyscanfcs
diff --git a/doc/Bibliography.bib b/doc/Bibliography.bib
index 8a3aa6f..1b16380 100644
--- a/doc/Bibliography.bib
+++ b/doc/Bibliography.bib
@@ -1,4 +1,4 @@
-% This file was created with JabRef 2.10b2.
+% This file was created with JabRef 2.10.
 % Encoding: UTF-8
 
 
@@ -42,10 +42,9 @@ paul.mueller at biotec.tu-dresden.de and weidemann at biochem.mpg.de
 Supplementary information:
 Supplementary information and a documentation are available at the PyCorrFit web page.},
   Doi                      = {10.1093/bioinformatics/btu328},
-  Eprint                   = {http://bioinformatics.oxfordjournals.org/content/early/2014/05/13/bioinformatics.btu328.full.pdf+html},
   Owner                    = {paul},
   Timestamp                = {2014.05.14},
-  Url                      = {pycorrfit.craban.de}
+  Url                      = {http://pycorrfit.craban.de}
 }
 
 @Article{Ries2009,
diff --git a/doc/PyScanFCS_doc_content.tex b/doc/PyScanFCS_doc_content.tex
index de6262e..c0a83f1 100755
--- a/doc/PyScanFCS_doc_content.tex
+++ b/doc/PyScanFCS_doc_content.tex
@@ -11,7 +11,7 @@ by the Free Software Foundation, either version 2 of the License,
 or (at your option) any later version.
 \\
 \\
-An exemplary usage of PyScanFCS - delivering a proof of principle from calibration to data fitting - was shown in \cite{Mueller2014}.
+An exemplary usage of PyScanFCS - delivering a proof of principle from calibration to data fitting - was shown in \cite{Mueller2014} (Authors manuscript available at \url{pyscanfcs.craban.de}.
 
 \subsection{Prerequisites}
 In order to use the PyScanFCS software, the following equipment is needed:
@@ -29,7 +29,7 @@ In order to use the PyScanFCS software, the following equipment is needed:
 PyScanFCS can be downloaded from \url{http://pyscanfcs.craban.de}.
 \begin{itemize}
 \item \textbf{Windows}
-For Windows XP or Windows 7, stand-alone binary executables are available from the download page. 
+For Windows, stand-alone binary executables are available from the download page. 
 \item \textbf{Linux}
 There are executable binaries for widely used distributions (e.g. Ubuntu).
 \item \textbf{Sources}
@@ -45,12 +45,12 @@ python-wxgtk2.8 (2.8.12.1) \\
 }
 \\
 There are two ways to make PyScanFCS run from source.\\
-\textbf{Recommended way:} Install via pip
-\texttt{ pip install pyscanfcs}
+\textbf{install from PyPI:}
+\texttt{pip install pyscanfcs}
 and run the package directly
 \texttt{python -m pyscanfcs}.
 \\
-\textbf{Second way:}
+\textbf{clone from GitHub:}
 Obtain the source directly from GitHub (\url{https://github.com/paulmueller/PyScanFCS}).
 
 
@@ -67,26 +67,19 @@ python-dev}
 \item[ ] \textbf{MacOS}. Use Apple's XCode, available from \url{http://developer.apple.com}.
 \end{itemize}
 Cython can be obtained from \url{http://www.cython.org/}. After unpacking of the archive, Cython is installed by executing \texttt{python setup.py install} within the unpacked directory\footnote{Cython can also be installed via PyPI with \texttt{pip install cython} (\url{http://pypi.python.org/pypi}).}.
-
-For older version of Ubuntu, some of the above package versions are not listed in the package repository. To enable the use of PyScanFCS on those systems, the following packages need to be installed separately:
-
-\begin{itemize}
-\item[ ] \textbf{matplotlib}. The tukss-ppa includes version 1.0.1. After adding the repository (\texttt{apt-add-repository ppa:tukss/ppa}), matplotlib can be installed as usual.
-\item[ ] \textbf{numpy}. The package from a later version of Ubuntu can be installed: \url{https://launchpad.net/ubuntu/+source/python-numpy/}
-\item[ ] \textbf{scipy}. The package from a later version of Ubuntu can be installed: \url{https://launchpad.net/ubuntu/+source/python-scipy/}
-\end{itemize}
-
 \end{itemize}
 
-Correlation curves created by PyScanFCS can be processed using \texttt{PyCorrFit}\footnote{\url{http://pycorrfit.craban.de}}.
+Correlation curves created by PyScanFCS can be processed using \texttt{PyCorrFit}\footnote{\url{http://pycorrfit.craban.de}} \cite{Mueller2014a}.
 
+\newpage
 \section{Data acquisition modes}
-\begin{figure}[t]
+
+In order to achieve all possible measurement modes depicted in \hyref{figure}{fig:scanmodi}, the CLSM needs to be set up properly. The scan paths should be checked for straightness e.g. by bleaching a layer of eGFP\footnote{Often, hysteresis effects occur during high speed scanning and scan paths are not straight. Switching to slower bidirectional scanning or setting up a ``multitrack mode'' might solve these problems.}. In 2fSFCS, the distance between the lines can be determined in a si [...]
+\begin{figure}[h]
 \centering
 \includegraphics[width=0.8\linewidth]{SFCSmodi.pdf}
  \mycaption{acquisition modes in PyScanFCS}{The six figures \textbf{a-f} show possible scenarios for scan path and excitation settings. The alignment of the scan paths (black) is shown for membrane of a giant unilamellar vesicle (red). The arrow tips define the different colors used for each scan (blue excitation, green excitation, or both at the same time). Multiple arrow tips indicate the sequential scanning of one line with two colors. The time necessary to perform a complete scan in  [...]
 \end{figure}
-In order to achieve all possible measurement modes depicted in \hyref{figure}{fig:scanmodi}, the CLSM needs to be set up properly. The scan paths should be checked for straightness e.g. by bleaching a layer of eGFP\footnote{Often, hysteresis effects occur during high speed scanning and scan paths are not straight. Switching to slower bidirectional scanning or setting up a ``multitrack mode'' might solve these problems.}. In 2fSFCS, the distance between the lines can be determined in a si [...]
 \begin{figure}[]
 \centering
 % 2012-08-27-SFCS_DiO-DOPC-GUVs --> GUV5b
@@ -171,7 +164,7 @@ Possible correlations (2 foci): $AC_{A1}$, $AC_{B2}$, $CC_{A1B2}$, $CC_{B2A1}$
 \end{figure}
 \hyref{Figure}{fig:SFCSMain} shows the main user interface with the following content:
 \begin{itemize}
-\item The \textbf{menu bar} with standard operations, such as loading or saving a file. The \textbf{cache menu} is a convenience tool. It displays all previously binned \mytilde .dat files.
+\item The \textbf{menu bar} with standard operations, such as loading or saving a file. The \textbf{cache menu} displays all previously binned \mytilde .dat files. The file menu contains a method to create artificial \mytilde .dat files for testing.
 
 \item \textbf{Pre-binning}: This sets up all parameters that are used to bin a \mytilde .dat file:
 	\begin{itemize}
diff --git a/pyinstaller-howto/PyScanFCS.icns b/freeze_pyinstaller/PyScanFCS.icns
similarity index 100%
rename from pyinstaller-howto/PyScanFCS.icns
rename to freeze_pyinstaller/PyScanFCS.icns
diff --git a/pyinstaller-howto/PyScanFCS.ico b/freeze_pyinstaller/PyScanFCS.ico
similarity index 100%
rename from pyinstaller-howto/PyScanFCS.ico
rename to freeze_pyinstaller/PyScanFCS.ico
diff --git a/pyinstaller-howto/PyScanFCS_linux.spec b/freeze_pyinstaller/PyScanFCS_linux.spec
similarity index 54%
rename from pyinstaller-howto/PyScanFCS_linux.spec
rename to freeze_pyinstaller/PyScanFCS_linux.spec
index 3e5c658..0b29a6f 100644
--- a/pyinstaller-howto/PyScanFCS_linux.spec
+++ b/freeze_pyinstaller/PyScanFCS_linux.spec
@@ -1,10 +1,10 @@
 # -*- mode: python -*-
-a = Analysis(['PyScanFCS/pyscanfcs/PyScanFCS.py'],
-             pathex=['pyinstaller-2.0'],
+a = Analysis(['pyscanfcs/PyScanFCS.py'],
+             pathex=[],
              hiddenimports=[],
              hookspath=None)
-a.datas += [('doc/ChangeLog.txt', 'PyScanFCS/ChangeLog.txt', 'DATA'),
-            ('doc/PyScanFCS_doc.pdf', 'PyScanFCS/PyScanFCS_doc.pdf', 'DATA')]
+a.datas += [('doc/ChangeLog.txt', 'ChangeLog.txt', 'DATA'),
+            ('doc/PyScanFCS_doc.pdf', 'doc/PyScanFCS_doc.pdf', 'DATA')]
 pyz = PYZ(a.pure)
 exe = EXE(pyz,
           a.scripts,
@@ -15,4 +15,5 @@ exe = EXE(pyz,
           debug=False,
           strip=None,
           upx=True,
-          console=True )
+          console=False
+         )
diff --git a/pyinstaller-howto/PyScanFCS_mac.spec b/freeze_pyinstaller/PyScanFCS_mac.spec
similarity index 73%
rename from pyinstaller-howto/PyScanFCS_mac.spec
rename to freeze_pyinstaller/PyScanFCS_mac.spec
index fdfb388..b77e3c4 100644
--- a/pyinstaller-howto/PyScanFCS_mac.spec
+++ b/freeze_pyinstaller/PyScanFCS_mac.spec
@@ -1,9 +1,8 @@
 # -*- mode: python -*-
 a = Analysis(['pyscanfcs/PyScanFCS.py'],
-             pathex=['PyInstaller-2.1'],
              hookspath=None)
 a.datas += [('doc/ChangeLog.txt', 'ChangeLog.txt', 'DATA'),
-            ('doc/PyScanFCS_doc.pdf', 'PyScanFCS_doc.pdf', 'DATA')]
+            ('doc/PyScanFCS_doc.pdf', 'doc/PyScanFCS_doc.pdf', 'DATA')]
 pyz = PYZ(a.pure)
 exe = EXE(pyz,
           a.scripts,
@@ -21,5 +20,5 @@ coll = COLLECT(exe,
                upx=True,
                name='PyScanFCS')
 app = BUNDLE(coll,
-             name='PyScanFCS.app',
-             icon='pyinstaller-howto/PyScanFCS.icns')
+             name='dist/PyScanFCS.app',
+             icon='freeze_pyinstaller/PyScanFCS.icns')
diff --git a/freeze_pyinstaller/PyScanFCS_win7.spec b/freeze_pyinstaller/PyScanFCS_win7.spec
new file mode 100644
index 0000000..1a04671
--- /dev/null
+++ b/freeze_pyinstaller/PyScanFCS_win7.spec
@@ -0,0 +1,63 @@
+# -*- mode: python -*-
+import codecs
+import os
+import sys
+
+if not os.path.exists("freeze_pyinstaller"):
+    raise Exception("Please go to `PyScanFCS` directory.")
+
+    
+name = "PyScanFCS"
+DIR = os.path.realpath(".")
+PyInstDir = os.path.join(DIR, "freeze_pyinstaller")
+PCFDIR = os.path.join(DIR, "pyscanfcs")
+ProgPy = os.path.join(PCFDIR,"PyScanFCS.py")
+ChLog = os.path.join(DIR,"ChangeLog.txt")
+DocPDF = os.path.join(DIR,"doc/PyScanFCS_doc.pdf")
+ICO = os.path.join(PyInstDir,"PyScanFCS.ico")
+
+sys.path.append(DIR)
+
+## Create inno setup .iss file
+import pyscanfcs
+version = pyscanfcs.__version__
+issfile = codecs.open(os.path.join(PyInstDir,"win7_innosetup.iss.dummy"), 'r', "utf-8")
+iss = issfile.readlines()
+issfile.close()
+for i in range(len(iss)):
+    if iss[i].strip().startswith("#define MyAppVersion"):
+        iss[i] = '#define MyAppVersion "{:s}"\n'.format(version)
+nissfile = codecs.open("win7_innosetup.iss", 'wb', "utf-8")
+nissfile.write(u"\ufeff")
+nissfile.writelines(iss)
+nissfile.close()
+
+
+a = Analysis([ProgPy],
+             pathex=[DIR],
+             hiddenimports=["sympy.assumptions.handlers", # sympy
+                            "sympy.assumptions.handlers.common",
+                            "scipy.special._ufuncs_cxx"],
+             hookspath=None)
+a.datas += [('doc\\ChangeLog.txt', ChLog, 'DATA'),
+            ('doc\\PyScanFCS_doc.pdf', DocPDF, 'DATA')]
+
+pyz = PYZ(a.pure)
+
+exe = EXE(pyz,
+          a.scripts,
+          exclude_binaries=True,
+          name=name+'.exe',
+          debug=False,
+          strip=None,
+          upx=True,
+          icon=ICO,
+          console=False )
+
+coll = COLLECT(exe,
+               a.binaries,
+               a.zipfiles,
+               a.datas,
+               strip=None,
+               upx=True,
+               name=name)
diff --git a/freeze_pyinstaller/README.md b/freeze_pyinstaller/README.md
new file mode 100644
index 0000000..cfaa47f
--- /dev/null
+++ b/freeze_pyinstaller/README.md
@@ -0,0 +1,22 @@
+PyScanFCS - creating binaries with PyInstaller
+=========
+
+Usage
+-------------------
+
+All cython (~.pyx) files must be compiled before scripts in this directory
+can be run. In the PyScanFCS/ directory execute:
+
+    python setup.py build_ext --inplace
+
+Download PyInstaller from http://www.pyinstaller.org/ ([Working revision](https://github.com/pyinstaller/pyinstaller/commit/779d07b236a943a4bf9d2b1a0ae3e0ebcc914798)).
+To create a single binary file, go to the unpacked pyinstaller directory and execute
+
+    python pyinstaller.py /Path/To/PyScanFCS.py
+
+Alternatively, there are ~.spec files and scripts for Windows / Mac / Debian  in this directory for bundling binary files.
+
+Note
+-------------------
+
+For more details, consult [PyCorrFit/freeze_pyinstaller](https://github.com/paulmueller/PyCorrFit/tree/master/freeze_pyinstaller).
diff --git a/freeze_pyinstaller/debian_ubuntu_bundle_script.sh b/freeze_pyinstaller/debian_ubuntu_bundle_script.sh
new file mode 100755
index 0000000..eaf835c
--- /dev/null
+++ b/freeze_pyinstaller/debian_ubuntu_bundle_script.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+Progname="PyScanFCS"
+# Go to base dir of repo
+BASEDIR=$(dirname $0)
+cd $BASEDIR
+BASEDIR=$(pwd)
+cd "../"
+StartDir=$(pwd)"/"
+Progdir=${StartDir}"/"
+# We require a Progname_doc.tex in the source-doc directory
+DocDir=${StartDir}"/doc/"
+Docname=${DocDir}${Progname}"_doc.pdf"
+Changelogname="ChangeLog.txt"
+Specfile=${BASEDIR}"/"${Progname}"_linux.spec"
+codename=$(lsb_release -c | awk 'BEGIN { FS = "\t" }; { print $2 }')
+distrib=$(lsb_release -i | awk 'BEGIN { FS = "\t" }; { print $2 }')
+version=$(head -n1 ./ChangeLog.txt | tr -d "\r\n")
+#Binname="dist/"${Progname}_${distrib}_${codename}_$(uname -r)".bin"
+Zipname="dist/"${Progname}_${version}_${distrib}_${codename}_$(uname -r)".zip"
+Env="env_${Progname}"
+
+echo $Specfile
+
+cd $StartDir
+
+echo "############"
+echo "Checking pip"
+echo "############"
+# Check if pip is installed
+if [ 1 -ne $(dpkg -s python-pip | grep -c "Status: install ok installed") ]; then
+    echo "Please install package `python-pip`"
+    exit
+fi
+if ! [ -e $Env ]; then
+    virtualenv --system-site-packages $Env
+    if [ $? -ne 0 ]; then
+        echo "Error - Aborting"
+        exit
+    fi
+    source $Env"/bin/activate"
+    # Pyinstaller
+    pip install git+git://github.com/pyinstaller/pyinstaller.git@779d07b236a943a4bf9d2b1a0ae3e0ebcc914798
+    # PyFITS
+    pip install pyfits
+fi
+source $Env"/bin/activate"
+
+
+
+echo "###################"
+echo "Building Extensions"
+echo "###################"
+rm -f $Docname
+python setup.py build_ext --inplace
+if [ $? -ne 0 ]; then
+    echo "Error - Aborting"
+    exit
+fi
+
+
+echo "############################"
+echo "Removing old build directory"
+echo "############################"
+rm -rf build
+if [ $? -ne 0 ]; then
+    echo "Error - Aborting"
+    exit
+fi
+
+
+echo "###################"
+echo "Running Pyinstaller"
+echo "###################"
+pyinstaller -F $Specfile
+if [ $? -ne 0 ]; then
+    echo "Error - Aborting"
+    exit
+fi
+
+
+echo "############"
+echo "Creating Zip"
+echo "############"
+zip -j ${Zipname} "dist/"${Progname} ${Docname} ${Changelogname}
diff --git a/pyinstaller-howto/macOSx_script_starter.sh b/freeze_pyinstaller/macOSx_script_starter.sh
similarity index 100%
rename from pyinstaller-howto/macOSx_script_starter.sh
rename to freeze_pyinstaller/macOSx_script_starter.sh
diff --git a/freeze_pyinstaller/win7_32bit_bundle_script.bat b/freeze_pyinstaller/win7_32bit_bundle_script.bat
new file mode 100644
index 0000000..3aa1d24
--- /dev/null
+++ b/freeze_pyinstaller/win7_32bit_bundle_script.bat
@@ -0,0 +1,5 @@
+cd %~dp0
+cd ..
+DEL /F /Q .\doc\PyScanFCS_doc.pdf
+
+pyinstaller -y .\freeze_pyinstaller\PyScanFCS_win7.spec
diff --git a/freeze_pyinstaller/win7_innosetup.iss.dummy b/freeze_pyinstaller/win7_innosetup.iss.dummy
new file mode 100644
index 0000000..2860449
--- /dev/null
+++ b/freeze_pyinstaller/win7_innosetup.iss.dummy
@@ -0,0 +1,113 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define MyAppName "PyScanFCS"
+#define MyAppVersion "0.2.2"
+#define MyAppPublisher "Paul Müller"
+#define MyAppURL "http://pyscanfcs.craban.de"
+#define MyAppExeName "PyScanFCS.exe"
+#define MyAppDir = "C:\Users\Paul\Desktop\PyScanFCS\dist\PyScanFCS\"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{10078D61-1BFE-505A-C57D-57BCC20B8360}
+AppName={#MyAppName}
+AppVersion={#MyAppVersion}
+;AppVerName={#MyAppName} {#MyAppVersion}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+DefaultDirName={pf}\{#MyAppName}
+DisableDirPage=yes
+DefaultGroupName={#MyAppName}
+AllowNoIcons=yes
+OutputBaseFilename={#MyAppName}_{#MyAppVersion}_setup
+Compression=lzma
+SolidCompression=yes
+ChangesAssociations=yes
+
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Files]
+Source: "{#MyAppDir}{#MyAppName}.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: "{#MyAppDir}*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Icons]
+Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{group}\Documentation"; Filename: "{app}\doc\{#MyAppName}_doc.pdf"
+Name: "{group}\Changelog"; Filename: "{app}\doc\Changelog.txt"
+Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
+Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+
+[Run]
+Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
+
+[Code]
+/////////////////////////////////////////////////////////////////////
+function GetUninstallString(): String;
+var
+  sUnInstPath: String;
+  sUnInstallString: String;
+begin
+  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
+  sUnInstallString := '';
+  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
+    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
+  Result := sUnInstallString;
+end;
+
+
+/////////////////////////////////////////////////////////////////////
+function IsUpgrade(): Boolean;
+begin
+  Result := (GetUninstallString() <> '');
+end;
+
+
+/////////////////////////////////////////////////////////////////////
+function UnInstallOldVersion(): Integer;
+var
+  sUnInstallString: String;
+  iResultCode: Integer;
+begin
+// Return Values:
+// 1 - uninstall string is empty
+// 2 - error executing the UnInstallString
+// 3 - successfully executed the UnInstallString
+
+  // default return value
+  Result := 0;
+
+  // get the uninstall string of the old app
+  sUnInstallString := GetUninstallString();
+  if sUnInstallString <> '' then begin
+    sUnInstallString := RemoveQuotes(sUnInstallString);
+    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
+      Result := 3
+    else
+      Result := 2;
+  end else
+    Result := 1;
+end;
+
+/////////////////////////////////////////////////////////////////////
+procedure CurStepChanged(CurStep: TSetupStep);
+begin
+  if (CurStep=ssInstall) then
+  begin
+    if (IsUpgrade()) then
+    begin
+      UnInstallOldVersion();
+    end;
+  end;
+end;
diff --git a/misc/MakeTestDat_SFCS.py b/misc/MakeTestDat_SFCS.py
index e18dfdc..a3f3f35 100755
--- a/misc/MakeTestDat_SFCS.py
+++ b/misc/MakeTestDat_SFCS.py
@@ -31,22 +31,24 @@ def MakeDat(linetime, noisearray, dtype, filename):
     # Create matrix. Each line is a scan.
     data = list()
     timeticks = linetime*newclock*1e6 # 60MHz
+    half1 = np.ceil(timeticks/2)
+    half2 = np.floor(timeticks/2)
     for i in np.arange(len(noisearray)):
         # Create a line
         N = noisearray[i]
         if N == 0:
             line=np.zeros(1, dtype=dtype)
             # Only one event at the far corner
-            line[0] = 2*timeticks
+            line[0] = timeticks
             line.tofile(NewFile)
         else:
             line = np.ones(N+1, dtype=dtype)
             # events are included between two far events
-            line[0] = line[-1] = timeticks-int(len(line)/2)
+            line[0] = half1-len(line)
+            line[-1] = half2
             line.tofile(NewFile)
     NewFile.close()
 
-
 def OnSaveDat(filename, data):
     # Save the Data
     """
@@ -78,7 +80,7 @@ def GenerateExpNoise(N, taud=20., variance=1., deltat=1.):
     """
     # length of mean0 trace
     N_steps = N
-    dt = int(deltat)
+    dt = deltat
     # time trace
     t = np.arange(N_steps)
     # AR-1 processes - what does that mean?
@@ -169,22 +171,23 @@ def SaveCSV(G, trace, filename):
 
     openedfile.close()
 
-# Line time to be ound by SFCS analyzation software
-linetime = 0.000714
+# Line time to be found by SFCS analyzation software
+linetime = 0.714 # in ms
 # Time of exponentially correlated noise
 taudiff = 7. # in ms
 
-noisearray = GenerateExpNoise(200000, taud=taudiff/linetime/1e3)
+noisearray = GenerateExpNoise(200000, taud=taudiff/linetime)
 noisearray += np.abs(np.min(noisearray))
 noisearray *= 30./np.max(noisearray)
 noisearray = np.uint32(noisearray)
 
+
 # Create 32bit and 16bit binary .dat files
-data = MakeDat(linetime/2, noisearray, np.uint16, "test_"+str(taudiff)+"ms_16bit.dat")
-data = MakeDat(linetime/2, noisearray, np.uint32, "test_"+str(taudiff)+"ms_32bit.dat")
+data = MakeDat(linetime/1000, noisearray, np.uint16, "test_"+str(taudiff)+"ms_16bit.dat")
+data = MakeDat(linetime/1000, noisearray, np.uint32, "test_"+str(taudiff)+"ms_32bit.dat")
 
 # Create reference .csv file to check results
-G = multipletau.autocorrelate(noisearray, deltat=linetime, normalize=True)
+G = multipletau.autocorrelate(noisearray, deltat=linetime/1000, normalize=True)
 newtrace = ReduceTrace(noisearray, deltat=linetime, length=500)
 SaveCSV(G, newtrace, "test_"+str(taudiff)+"ms_reference.csv")
 
diff --git a/pyinstaller-howto/PyScanFCS_win.spec b/pyinstaller-howto/PyScanFCS_win.spec
deleted file mode 100644
index 9ed128b..0000000
--- a/pyinstaller-howto/PyScanFCS_win.spec
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- mode: python -*-
-a = Analysis(['C:\\Python27\\PyScanFCS\\pyscanfcs\\PyScanFCS.py'],
-             pathex=['C:\\Python27\\pyinstaller-pyinstaller-6ca4af8'],
-             hiddenimports=[],
-             hookspath=None)
-a.datas += [('doc\\ChangeLog.txt', 'C:\\Python27\\PyScanFCS\\ChangeLog.txt', 'DATA'),
-            ('doc\\PyScanFCS_doc.pdf', 'C:\\Python27\\PyScanFCS\\PyScanFCS_doc.pdf', 'DATA')]
-pyz = PYZ(a.pure)
-exe = EXE(pyz,
-          a.scripts,
-          a.binaries,
-          a.zipfiles,
-          a.datas,
-          name=os.path.join('dist', 'PyScanFCS.exe'),
-          debug=False,
-          strip=None,
-          upx=True,
-          icon='C:\\Python27\\PyScanFCS\\pyinstaller-howto\\PyScanFCS.ico',
-#          console=False )
-          console=True )
-
diff --git a/pyinstaller-howto/README.md b/pyinstaller-howto/README.md
deleted file mode 100644
index 8a7302f..0000000
--- a/pyinstaller-howto/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-PyScanFCS - creating binaries with PyInstaller
-=========
-
-Usage
--------------------
-
-All cython (~.pyx) files must be compiled before scripts in this directory
-can be run. In the PyScanFCS/src/ directory execute:
-
-    python compile\_cython.py build\_ext --inplace
-
-Download PyInstaller v.2.0 from http://www.pyinstaller.org/
-To create a single binary file, go to the unpacked pyinstaller directory and execute
-
-    python pyinstaller.py /Path/To/PyCorrFit.py
-
-Alternatively, there are ~.spec files and scripts for Windows XP / Ubuntu12.04 in this directory for bundling binary files.
-
-Note
--------------------
-
-For more details, consult [PyCorrFit/pyinstaller-howto](https://github.com/paulmueller/PyCorrFit/tree/master/pyinstaller-howto).
diff --git a/pyinstaller-howto/macOSx_10.6.8_bundle_script.sh b/pyinstaller-howto/macOSx_10.6.8_bundle_script.sh
deleted file mode 100755
index 418446b..0000000
--- a/pyinstaller-howto/macOSx_10.6.8_bundle_script.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-BASEDIR=$(dirname $BASH_SOURCE)
-cd $BASEDIR
-BASEDIR=$(pwd)
-cd "../"
-
-# We need to run PyScanFCS in a separate Terminal to prevent this error
-# from occuring:
-#
-# UnicodeDecodeError: 'ascii' codec can't decode byte 0xcf
-# in position 0: ordinal not in range(128)
-#
-# tags: pyinstaller app bundling wxpython
-
-python ./Pyinstaller-2.1/pyinstaller.py -y ./pyinstaller-howto/PyScanFCS_mac.spec
-
-# move aside the binary and replace with script
-
-mv ./dist/PyScanFCS.app/Contents/MacOS/PyScanFCS ./dist/PyScanFCS.app/Contents/MacOS/PyScanFCS.bin
-
-cp ./pyinstaller-howto/macOSx_script_starter.sh ./dist/PyScanFCS.app/Contents/MacOS/PyScanFCS
-
-chmod +x ./dist/PyScanFCS.app/Contents/MacOS/PyScanFCS
diff --git a/pyinstaller-howto/ubuntu12.04_amd64_bundle_script.sh b/pyinstaller-howto/ubuntu12.04_amd64_bundle_script.sh
deleted file mode 100755
index 1c77f23..0000000
--- a/pyinstaller-howto/ubuntu12.04_amd64_bundle_script.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-
-# **************** Change Variables Here ************
-# Directory structure:
-# ./PyScanFCS           # git repository
-# ./pyinstaller-2.0/    # Pyinstaller files
-# ./Uploads             # Binary and zip files
-PyInstaller="pyinstaller-2.0/"
-Uploads="Uploads/"
-# Progname.py should be in the Progdir
-Progname="PyScanFCS"
-# We require a ChangeLog.txt and a source directory in the Progdir
-# BASEDIR/PyScanFCS/pyinstaller-howto
-BASEDIR=$(dirname $BASH_SOURCE)
-cd $BASEDIR
-BASEDIR=$(pwd)
-cd "../../"
-StartDir=$(pwd)"/"
-Progdir=${StartDir}${Progname}"/"
-# We require a Progname_doc.tex in the source-doc directory
-DocDir=${StartDir}${Progname}"/doc/"
-PyInstallerDir=${Progdir}${PyInstaller}
-Specfile=${BASEDIR}"/"${Progname}"_linux.spec"
-echo $Specfile
-
-echo "********************************"
-echo "* Creating "${Progname}" binary *"
-echo "********************************"
-
-cd $StartDir
-
-if [ -f $Specfile ]
-then
-    # added following line (remove build directory beforehand!)
-    # a.datas += [('doc/ChangeLog.txt', '/PATH/TO/PyCorrFit/ChangeLog.txt', 'DATA')]
-    python ${PyInstallerDir}pyinstaller.py -F $Specfile
-else
-    python ${PyInstallerDir}pyinstaller.py -F ${Progdir}"src/"${Progname}".py"
-fi
-
-# make executable
-chmod +x ${Progdir}"pyinstaller-howto/dist/"${Progname}
diff --git a/pyinstaller-howto/windowsXP_32bit_bundle_script.bat b/pyinstaller-howto/windowsXP_32bit_bundle_script.bat
deleted file mode 100644
index c2c0754..0000000
--- a/pyinstaller-howto/windowsXP_32bit_bundle_script.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-cd C:\Python27\pyinstaller*
-del /q /s ..\PyScanFCS\pyinstaller-howto\build
-del /q /s ..\PyScanFCS\pyinstaller-howto\dist
-python pyinstaller.py ..\PyScanFCS\pyinstaller-howto\PyScanFCS_win.spec
diff --git a/pyscanfcs/PyScanFCS.py b/pyscanfcs/PyScanFCS.py
old mode 100755
new mode 100644
index 9d5f8fb..dc888c2
--- a/pyscanfcs/PyScanFCS.py
+++ b/pyscanfcs/PyScanFCS.py
@@ -1,2123 +1,10 @@
-#!/usr/bin/python
 # -*- coding: utf-8 -*-
-""" 
-    PyScanFCS
-
-    Data processing for perpendicular line scanning FCS.
-
-    (C) 2012 Paul Müller
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License 
-    along with this program. If not, see <http://www.gnu.org/licenses/>.
+""" PyScanFCS loader
 """
+from os.path import dirname, join, abspath, split
 
-# Generic modules
-import tempfile
-import zipfile
-import csv
 import sys
-import webbrowser
-
-## On Windows XP I had problems with the unicode Characters.
-# I found this at 
-# http://stackoverflow.com/questions/5419/python-unicode-and-the-windows-console
-# and it helped (needs to be done before import of matplotlib):
-import platform
-reload(sys)
-sys.setdefaultencoding('utf-8')
-
-import os
-import wx                               # GUI interface wxPython
-#import wx.lib.agw.pyprogress as PBusy   # Busy Dialog
-
-import matplotlib
-matplotlib.use('WXAgg')
-
-import matplotlib.cm as cm              # Color maps for plotting
-from matplotlib.figure import Figure
-from matplotlib.backends.backend_wxagg import \
-    FigureCanvasWxAgg as FigureCanvas, \
-    NavigationToolbar2WxAgg as NavigationToolbar
-
-from matplotlib.widgets import RectangleSelector, Button
-from matplotlib.patches import Rectangle
-
-import matplotlib.pyplot as plt
-
-from wx.lib.agw import floatspin        # Float numbers in spin fields
-
-#import wxmplot                          # wxmplot-0.9.7.zip (PyPI)
-
-import numpy as np                            # NumPy
-import pyfits
-from scipy.fftpack import fft
-from scipy.fftpack import fftfreq
-#import struct
-
-import edclasses
-import misc
-# SFCSnumeric needs scipy.optimize
-# We import it here, so that pyinstaller packs it into the executable.
-# Pyinstaller does not neccessarily know that SFCSnumeric needs it.
-from scipy import optimize
-import SFCSnumeric
-import multipletau
-
-import doc      # Documentation/some texts
-
-class plotarea(wx.Panel):
-    def __init__(self, parent, grandparent):
-        wx.Panel.__init__(self, parent, -1, size=(500,500))
-        # plotting area
-        self.grandparent = grandparent
-        self.figure = Figure()
-        self.canvas = FigureCanvas(self, -1, self.figure)
-        self.axes = self.figure.add_subplot(111)
-        #self.canvas.mpl_connect('button_press_event', self.on_pick)
-        self.pdata = np.linspace(0,100,100)
-        self.pdata.shape = (10,10)
-        self.image = self.axes.imshow(self.pdata, interpolation='nearest',
-                                      cmap=cm.gray, vmin=0, vmax=100)
-        self.colorbar = self.figure.colorbar(self.image)
-        #self.colorbar.set_ticks(np.arange(np.max(self.pdata)+1))
-        self.colorbar.set_label("Photon events", size=16)
-        self.toolbar = NavigationToolbar(self.canvas)
-        # Set selector:
-        self.rs = None
-        self.UseLineSelector()
-        # Layout:
-        self.vbox = wx.BoxSizer(wx.VERTICAL)
-        self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
-        self.vbox.Add(self.toolbar, 0, wx.EXPAND)
-        self.SetSizer(self.vbox)
-        self.vbox.Fit(self)
-        
-        # Labels
-        self.axes.set_ylabel("Scan cycle time [ms]",size=16)
-        self.axes.set_xlabel("Measurement time [s]",size=16)
-
-        
-
-    def OnSelectPlot(self, eclick, erelease):
-        self.grandparent.OnSelectPlot(eclick, erelease)
-
-    
-    def UseLineSelector(self):
-        lineprops = dict(color='red', linestyle='-',
-                         linewidth = 2, alpha=0.5)
-        del self.rs
-        self.rs = RectangleSelector(self.axes, self.OnSelectPlot, drawtype='line',
-                                    lineprops=lineprops)
-    def UseRectangleSelector(self):
-        del self.rs
-        rectprops = dict(facecolor='white', edgecolor = 'red',
-                       alpha=0.2, fill=True)
-        self.rs = RectangleSelector(self.axes, self.OnSelectPlot, drawtype='box',
-                                    rectprops=rectprops)
-        
-
-
-
-
-class FFTmaxDialog(wx.Dialog):
-    def __init__(
-            self, parent, frequency, amplitude, size=wx.DefaultSize, pos=wx.DefaultPosition, 
-            style=wx.DEFAULT_DIALOG_STYLE,
-            useMetal=False,
-            ):
-        title="Find maximum of Fourier Transform"
-        wx.Dialog.__init__(self, parent, -1, title, pos, size, style)
-
-        # Dialog conent
-        # Text result
-        self.pnt = parent
-        self.ampl = amplitude/np.max(amplitude)
-        self.freq = frequency*self.pnt.system_clock*1e3
-        self.label = wx.StaticText(self, 
-        label=" Click into the plot twice to define the interval where to search for the \
-maximum. \n The data achieved will automatically be updated within the main program.\
-\n You may close this window, when you are finished.")
-        # plotting area
-        self.figure = Figure()
-        self.canvas = FigureCanvas(self, -1, self.figure)
-        self.axes = self.figure.add_subplot(111)
-
-
-        self.axes.set_xlabel('Scan cycle [ms]')
-        self.axes.set_ylabel('FFT signal')
-        # We need x to be like that, because it represents the index of self.ampl
-        #x = np.arange(len(self.ampl))
-        self.freq[0]=1
-        x = 1/self.freq
-
-        self.image = self.axes.plot(x, self.ampl, '.', color="black")
-        self.axes.set_xscale('log')
-        self.axes.grid(True, which="major")
-        self.axes.grid(True, which="minor")
-        self.axes.yaxis.grid(False)
-        self.toolbar = NavigationToolbar(self.canvas)
-        self.canvas.mpl_connect('button_press_event', self.on_pick)
-        
-        #ipshell()
-        #self.image.set_extent((self.freq[0], self.freq[1], np.min(self.ampl), np.max(self.ampl)))
-        # Make the square or else we would not see much
-        #self.plotarea.axes.set_aspect(1.*Tx/Ty)
-
-
-        # Layout:
-        self.vbox = wx.BoxSizer(wx.VERTICAL)
-        self.vbox.Add(self.label, 0, wx.EXPAND)
-        self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
-        self.vbox.Add(self.toolbar, 0, wx.EXPAND)
-        self.SetSizer(self.vbox)
-        self.vbox.Fit(self)
-
-        self.counter = 0
-        self.ymax = np.max(self.ampl)
-        self.ymin = np.min(self.ampl)
-        self.interval = [0, 0]
-        self.red = False
-
-        # Set window icon
-        try:
-            self.MainIcon = doc.getMainIcon()
-            wx.Frame.SetIcon(self, self.MainIcon)
-        except:
-            self.MainIcon = None
-
-
-    def on_pick(self, event):
-        if ( event.inaxes == self.axes and
-             self.toolbar.mode == "" ):
-            # Let us draw some lines
-            if self.counter == 0:
-                self.line1 = self.axes.vlines(event.xdata, self.ymin, 
-                                              self.ymax, color='black')
-                self.canvas.draw()
-                self.counter = 1
-            elif self.counter == 1:
-                self.line2 = self.axes.vlines(event.xdata, self.ymin, 
-                                              self.ymax, color='black')
-                self.canvas.draw()
-                self.counter = 2
-            elif self.counter == 2:
-                self.line1._visible = False
-                self.line1 = self.axes.vlines(event.xdata, self.ymin, 
-                                              self.ymax, color='black')
-                self.canvas.draw()
-                self.counter = 3
-            elif self.counter == 3:
-                self.line2._visible = False
-                self.line2 = self.axes.vlines(event.xdata, self.ymin, 
-                                              self.ymax, color='black')
-                self.canvas.draw()
-                self.counter = 2
-            # Transform time domain xdata to index for self.ampl
-            newborder = 1/event.xdata
-            # The time domain should have large enough discretization.
-            self.interval[0] = np.argwhere(
-              (self.freq >= newborder)*(newborder > np.roll(self.freq,1)))[0][0]
-            self.interval[0], self.interval[1] = self.interval[1], self.interval[0]
-
-            if self.counter >= 2:
-            # Calculate maximum interval
-                if self.red == True:                    
-                    self.redline._visible = False
-                    self.canvas.draw()
-                self.red = True
-                [start, stop] = [int(np.min(self.interval))-1, int(np.max(self.interval))+1]
-                idx = np.argmax(self.ampl[start:stop])+start
-                # We now have the maximum, but we actually want to have some
-                # kind of a weighted maximum. For that we take k data points next
-                # to the maximum and weigth them with their relative amplitude.
-                k = 10
-                timeweights = list()
-                timeweights.append(1/self.freq[idx])
-                Pie = 1
-                for i in np.arange(k):
-                    weighta = 1.*self.ampl[idx+i+1]/self.ampl[idx]
-                    weightb = 1.*self.ampl[idx-i-1]/self.ampl[idx]
-                    timeweights.append(weighta/self.freq[idx+i+1])
-                    timeweights.append(weightb/self.freq[idx-i-1])
-                    Pie = Pie + weighta + weightb
-                    print sum(np.array(timeweights))/Pie, weighta, weightb
-
-                timeweights = np.array(timeweights)
-                #print timeweights
-                ltime = sum(timeweights)/Pie
-
-                self.pnt.t_linescan = ltime*self.pnt.system_clock*1e3
-
-                #amplitudes = self.ampl[idx-k:idx+k]
-                #frequencies = self.freq[idx-k:idx+k]
-                self.redline = self.axes.vlines(ltime, self.ymin, self.ymax, color='red')
-
-
-                ### Tried with gaussian fit
-                #amplitudes = self.ampl[start:stop]
-                #frequencies = self.freq[start:stop]
-                #argmax = np.argmax(amplitudes)
-                ## Get gaussian function and optimal parameters
-                ## popt = [freq, ampl, sigma]
-                ## gauss(popt, frequencies)
-                #popt, gauss = SFCSnumeric.FitGaussian(amplitudes, frequencies, argmax)
-                #self.pnt.t_linescan = 1./popt[0]
-                #lenplot = 1000
-                #ids_plot = np.linspace(start,stop,lenplot, endpoint=False)
-                #freq_plot = np.linspace(frequencies[0],frequencies[-1],lenplot, endpoint=False)
-                #a = np.argmax(gauss(popt, freq_plot))
-                #self.pnt.t_linescan = 1./freq_plot[a]
-                #self.redline =  self.axes.plot(ids_plot, gauss(popt, freq_plot), '-', color='red')
-
-
-                self.canvas.draw()
-                # Plot the results
-                # Set check box to True: "use cycle time"
-                self.pnt.BoxPrebin[6].SetValue(True)
-                self.pnt.Update()
-                self.pnt.OnBinning_Prebin()   
-
-
-class MyFrame(wx.Frame):
-    def __init__(self, parent, id, version):
-        self.version = version
-        wx.Frame.__init__(self, parent, id, "PyScanFCS " + self.version)
-        self.CreateStatusBar() # A Statusbar in the bottom of the window
-
-        ## Properties of the Frame
-        if sys.platform == "darwin":
-            initial_size = (1036,622)
-        else:
-            initial_size = (1024,595)
-        #initial_size = (1024,768)
-        self.SetSize(initial_size)
-        self.SetMinSize(initial_size)
-
-        # Set this, so we know in which directory we are working in.
-        # This will change, when we load a data file.
-        self.dirname = os.curdir
-        self.filename = ''
-
-        self.MakeMenu()
-
-        ## Create the initial windows
-        # When the user opens a file via file menu, the first 1e+6 datapoints
-        # will be generated (binned) and plotted. We do not need to do this, 
-        # but it makes the program more transparent. Then we will need to find
-        # the repetition time (time needed to scan one line) and bin the whole
-        # thing accordingly and plot again.
-
-        self.sp = wx.SplitterWindow(self, style=wx.SP_3DSASH)
-        self.buttonarea = wx.Panel(self.sp)
-        self.plotarea = plotarea(self.sp, self)
-        self.pdata = np.linspace(0,1,100)
-        self.pdata.shape = (10,10)
-        #self.plotarea = wxmplot.ImagePanel(self.sp)
-        #self.plotarea.display(self.pdata)
-
-        self.sp.SplitVertically(self.buttonarea, self.plotarea, 450)
-
-        self.MakeButtons()
-
-        self.Layout()
-
-        self.Show()
-
-        # Initial data values:
-        # Time values are system clock ticks
-        # System clock in MHz
-        self.system_clock = None
-        self.T_total = None
-        self.t_linescan = None
-        self.t_bin = None
-        self.datData = None
-        self.intData = None
-        self.bins_per_line = None
-        self.percent = 0. # correction factor for cycle time
-
-        # A square displayed upon selection:
-        self.square = None
-        self.squareB = None
-        # Coordinates of the square [(x1, x2), (y1,y2)]
-        self.XY_Trace_square = [ (None, None), (None, None) ]
-        self.XY_Trace_squareB = [ (None, None), (None, None) ]
-
-        # List of absolute filenames that contain bleaching info
-        self.file_bleach_profile = list()
-        
-        # We try to work with a cache to save time.
-        self.cache = dict()
-        # Each element of the cache is a filename connected to some data
-        # cachetest = self.cache["testA.dat"] = dict()
-        # cachetest["bins_per_line"] = self.bins_per_line
-        # cachetest["linetime"] = self.t_linescan
-        # cachetest["data"] = self.intData
-        self.Update()
-        # Set window icon
-        try:
-            self.MainIcon = doc.getMainIcon()
-            wx.Frame.SetIcon(self, self.MainIcon)
-        except:
-            self.MainIcon = None
-
-
-    def AddToCache(self, Data, cachename, background=False):
-        if self.cache.keys().count(cachename) == 0:
-            # Add the menu entry
-            menu = self.cachemenu.Append(wx.ID_ANY, cachename, kind=wx.ITEM_RADIO)
-            if background == False:
-                # If True, do not activate new menu.
-                menu.Check(True)
-            # OnSelectCache plots the selected Cache element
-            self.Bind(wx.EVT_MENU, self.OnSelectCache, menu)
-        acache = dict()
-        acache["data"] = 1*Data
-        acache["bins_per_line"] = self.bins_per_line
-        acache["linetime"] = self.t_linescan
-        acache["dirname"] = self.dirname
-        self.cache[cachename] = acache
-
-
-    def Bin_All_Photon_Events(self, Data):
-        """ Bin all photon events according to a binsize t_bin.
-        """
-        eb = self.BoxPrebin[10].GetValue()  # 10 spin: bin shift
-        # Now show an informing dialog
-        style=wx.PD_REMAINING_TIME|wx.PD_SMOOTH|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT
-        dlg = wx.ProgressDialog("Binning Data", "Counting photon events..."
-        , maximum = 100, parent=self, style=style)
-
-        # The box contains bins per line
-        self.bins_per_line = int(self.BoxPrebin[8].GetValue())
-        # t_bin in clock ticks
-        t_bin = self.t_linescan/self.bins_per_line
-        dtype = np.uint16
-        filename = "Binned_total.int"
-        SFCSnumeric.BinPhotonEvents(Data, t_bin, filename, dtype, dlg, binshift=eb)
-
-        binneddata = np.fromfile(filename, dtype=dtype)
-        if np.max(binneddata) < 256:
-            binneddata = np.uint8(binneddata)
-
-        return binneddata
-
-
-    def Bin_Photon_Events(self, n_events=None, t_bin=None):
-        """
-        Given an array of time differences *Data* [µs] between photon events, 
-        calculate the photon events that take place every *t_bin* in system 
-        clocks, where n_events is the number of events to use.
-        """
-        eb = self.BoxPrebin[10].GetValue()  # 10 spin: bin shift
-
-        self.t_bin = t_bin
-        # Now show an informing dialog
-        style=wx.PD_REMAINING_TIME|wx.PD_SMOOTH|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT
-        dlg = wx.ProgressDialog("Binning Data", "Counting photon events..."
-        , maximum = 100, parent=self, style=style)
-        Data = self.datData[:n_events]
-
-        # The box contains bins per line
-        self.bins_per_line = int(self.BoxPrebin[8].GetValue())
-
-        dtype = np.uint16
-        filename = "Binned_partial.int"
-        retval = SFCSnumeric.BinPhotonEvents(Data, t_bin, filename, dtype, dlg, binshift=eb)
-
-        binneddata = np.fromfile(filename, dtype=dtype)
-        if np.max(binneddata) < 256:
-            binneddata = np.uint8(binneddata)
-
-        return binneddata
-
-
-    def CorrectLineTime(self, event):
-        percent = np.float(self.linespin.GetValue())    
-        if self.t_linescan is not None:
-            # Set the new linetime
-            self.t_linescan = np.float(self.t_linescan)*(1.+percent/100.)
-            self.percent = percent
-            self.UpdateInfo()
-
-
-
-    def GetTotalTime(self):
-        """ 
-        Sums over self.datData to find out the total time of the measurement.
-        Sets variable self.T_total
-        """ 
-        # Need to set float variable here, because uint32 are not
-        # large enough. T_total in system clocks.
-        self.T_total = np.sum(self.datData, dtype="float")
-        self.Update()
-
-
-    def GetTraceFromIntData(self, intData, coords, title="Trace"):
-        """
-            region is a number describing the region the trace comes from (1 or 2)
-        """
-        ## Get the data
-        # Make sure we have the corners of the square
-        for atuple in coords:
-            if atuple[0] is None or atuple[1] is None:
-                return
-        [(x1,x2), (y1,y2)] = coords
-
-        # Convert times to positions in 2D array
-        x1 = np.floor(x1/self.t_linescan)
-        x2 = np.ceil(x2/self.t_linescan)
-        y1 = np.floor(y1/self.t_bin)
-        y2 = np.ceil(y2/self.t_bin)
-        bins_in_col = y2-y1
-        bins_in_row = x2-x1
-
-        ## Get some needed data
-        # bin time for on line in s (used for multiple tau algorithm)
-        bintime = self.t_linescan/self.system_clock/1e6
-        # Number of bins next to the maximum to use for the trace
-        num_next_max = self.Spinnumax.GetValue()
-
-        # We have to swap x and y, because we want to access
-        # the array linewise later.
-        traceData = np.zeros((bins_in_row, bins_in_col))
-
-        # We start from x1 (lowest time available) and
-        # successively fill the traceData array:
-        pos = x1*self.bins_per_line
-        for i in np.arange(len(traceData)):
-            traceData[i] = intData[pos+y1:pos+y2]
-            pos = pos + self.bins_per_line
-
-        ## Get the actual trace
-        # Calculate trace from maximum
-        traceDataMaxids = np.argmax(traceData, axis=1)
-        newtraceData = np.zeros((len(traceDataMaxids), num_next_max*2+1))
-
-        for i in np.arange(len(traceData)):
-            # We add to the new trace data array, such that the maximum of
-            # each line is at the center of the array.
-            maid = traceDataMaxids[i]
-            # The array to be written to newtraceData
-            nsli = np.zeros(num_next_max*2+1)
-            nsli[num_next_max] = traceData[i][maid]
-            for k in np.arange(num_next_max)+1:
-                if maid+1-k >= 0:
-                    nsli[num_next_max-k] = traceData[i][maid-k]
-                if maid+1+k <= len(traceData[i]):
-                    nsli[num_next_max+k] = traceData[i][maid+k]
-            newtraceData[i] = nsli
-        del traceDataMaxids
-
-
-        if self.CheckBoxCountrateFilter.GetValue() is True:
-            # "temporal detection profile"
-            # We use this to find out how much time we spent in the membrane
-            detprof = np.sum(newtraceData, axis=0)
-
-            # Countrate correction:
-            x = np.linspace(-num_next_max, +num_next_max, len(detprof))
-            popt, gauss = SFCSnumeric.FitGaussian(detprof, x, np.argmax(detprof))
-            # Time in bins, that the focus effectively was inside the membrane:
-            # Go two sigmas in each direction. This way we have an averaged
-            # cpp in the end.
-            MembraneBins = 4*popt[2]
-            LinetimeBins = self.bins_per_line
-
-            #tracemean = np.mean(newtraceData)
-            self.TraceCorrectionFactor=LinetimeBins/MembraneBins
-
-            if self.MenuVerbose.IsChecked():
-                x2 = np.linspace(popt[0]-4*popt[2], popt[0]+4*popt[2], 100)
-                plt.figure()
-                plt.subplot(111)
-                plt.plot(x, detprof, "-", label="Measured profile")
-                plt.plot(x2, gauss(popt,x2), "-", label="Gaussian fit")
-                plt.legend()
-                text = "sigma = "+str(popt[2])+ " bins\n" +\
-                       "residence time in bins: "+str(MembraneBins)+"\n" +\
-                       u"residence time [µs]: "+str(MembraneBins*bintime*1e6/
-                                                    self.bins_per_line)
-                coords = (MembraneBins, np.max(detprof)/2.)
-                plt.text(coords[0],coords[1],text)
-                plt.xlabel("Bin position relative to maximum in cycle time")
-                plt.ylabel("Sum of counted photons (whole trace)")
-                plt.title(title + " - Determination of residence time in membrane")
-                plt.show()
-        else:
-            self.TraceCorrectionFactor=1.
-
-
-        # We could multiply newtraceData with self.TraceCorrectionFactor right
-        # here, but we are not doing it, because it might introduce numerical
-        # errors. This does not change statistics. In order to get the correct
-        # countrate, we correct the traces, when they are binned for saving
-        # in .csv files.
-        newtraceData = np.sum(newtraceData, axis=1)
-        traceData = newtraceData
-
-
-        # Bleach filter?
-        if self.CheckBoxBleachFilter.GetValue() is True:
-            ltrb = len(traceData)
-            ## Perform bleaching correction
-            # fitted function:
-            # f_i = f_0 * exp(-t_i/t_0) + offset
-            # parms = [f_0, t_0, offset]
-            # Corrected function:
-            # F_c = F_i/(f_0*exp(-ti/(2*t_0))) + f_0*(1-f_0*exp(-t_i/(2*t_0)))
-            # We don't want to subtract an offset from the trace?
-            # The offset is actually background signal.
-            popt, expfunc = SFCSnumeric.FitExp(np.arange(len(traceData)),
-                                               traceData)
-            [f_0, t_0] = popt
-
-            newtrace = SFCSnumeric.ReduceTrace(traceData, bintime,
-                                               length=500)
-
-            # Full trace:
-            ti = np.arange(ltrb)
-            expfull = np.exp(-ti/(2*t_0))
-            # see formula above:
-            traceData = traceData/expfull + f_0*(1-expfull)
-
-            #### TODO:
-            # Does this do anything?
-            newtracecorr = SFCSnumeric.ReduceTrace(traceData, bintime,
-                                                   length=500)
-            
-            fitfuncdata = expfunc(popt, np.arange(ltrb))
-            newtracefit = SFCSnumeric.ReduceTrace(fitfuncdata,
-                                                  bintime, length=500)
-
-            # Bleaching profile to temporary file
-            # Create a temporary file and open it
-            filename = tempfile.mktemp(".csv",
-                                  "PyScanFCS_bleach_profile_{}_".format(
-                                               title.replace(" ", "_")))
-            outfile = open(filename, 'wb')
-            outfile.write("# This is not correlation data.\r\n")
-            outfile.write("# {} - bleaching correction\r\n".format(title))
-            outfile.write("# I = ({:.2e})*exp[-t / (2*({:.2e})) ]\r\n".format(f_0,t_0))
-            outfile.write("# {}\t{}\t{}\t{}\r\n".format(u"Time t [s]",
-                    u"Measured trace [kHz]", u"Exponential fit I [kHz]",
-                    u"Corrected trace [kHz]"))
-            dataWriter = csv.writer(outfile, delimiter='\t')
-            # we will write
-            xexp = newtrace[:,0]
-            yexp = newtrace[:,1]*self.TraceCorrectionFactor
-            yfit = newtracefit[:,1]*self.TraceCorrectionFactor
-            ycorr = newtracecorr[:,1]*self.TraceCorrectionFactor
-            data = [xexp, yexp, yfit, ycorr]
-            for i in np.arange(len(data[0])):
-                # row-wise, data may have more than two elements per row
-                datarow = list()
-                for j in np.arange(len(data)):
-                    rowcoli = str("%.10e") % data[j][i]
-                    datarow.append(rowcoli)
-                dataWriter.writerow(datarow)
-            outfile.close()
-            self.file_bleach_profile.append(filename)
-
-            if self.MenuVerbose.IsChecked():
-                def view_bleach_profile(e=None):
-                    ## Open the file
-                    if platform.system().lower() == 'windows':
-                        os.system("start /b "+filename)
-                    elif platform.system().lower() == 'linux':
-                        os.system("xdg-open "+filename+" &")
-                    elif platform.system().lower() == 'darwin':
-                        os.system("open "+filename+" &")
-                    else:
-                        # defaults to linux style:
-                        os.system("xdg-open "+filename+" &")
-                # Show a plot
-
-                #fig, ax = plt.figure()
-                #ax = plt.subplot(111)
-                fig, ax = plt.subplots()
-                plt.subplots_adjust(bottom=0.2)
-                plt.title(title + " - bleaching correction")
-                plt.xlabel("Measurement time t [s]")
-                plt.ylabel("approx. Intensity I [kHz]")
-                plt.plot(xexp, yexp, '-', 
-                         label = "Measured trace", color="gray")
-                plt.plot(xexp, yfit, '-', 
-                         label = "Exponential fit", color="red")
-                plt.plot(xexp, ycorr, '-', 
-                         label = "Corrected trace", color="blue")
-                xt = np.min(xexp)
-                yt = np.min(yexp)
-                text = "I = ({:.2e})*exp[-t / (2*({:.2e})) ]".format(f_0,t_0)
-                plt.text(xt,yt,text, size=12)
-                plt.legend()
-                plt.show()
-                
-                # We would like to have a button for the view_bleach_profile
-                # function. Unfortunately, this does not work:
-                #axgb = plt.axes([0.75, 0.05, 0.15, 0.05])
-                #buttonbleach = Button(axgb, 'view data')
-                #buttonbleach.on_clicked(view_bleach_data)
-                view_bleach_profile()
-        return traceData
-
-
-    def MakeButtons(self):
-        minsize = (150,-1)
-        dropminsize = (175,-1)
-        ## Pre-binning
-        prebox = wx.StaticBox(self.buttonarea, label="Pre-binning")
-        presizer = wx.StaticBoxSizer(prebox, wx.VERTICAL)
-        # Checkbox for later using the cycle time
-        precheck = wx.CheckBox(self.buttonarea, label="Use cycle time")
-        precheck.Bind(wx.EVT_CHECKBOX, self.Update)
-        precheck.IsChecked = False
-        presizer.Add(precheck)
-        # Text bins per line
-        prebplt = wx.StaticText(self.buttonarea, -1, "Bins per scan cycle:")
-        presizer.Add(prebplt)  
-        # Bins per line
-        self.prebpl = wx.SpinCtrl(self.buttonarea, -1, min=1, max=50000,
-                                  value="70")
-        self.prebpl.SetMinSize(minsize)
-        presizer.Add(self.prebpl)  
-        # Text bins
-        pretext = wx.StaticText(self.buttonarea, -1, "No. of events to use:")
-        presizer.Add(pretext)  
-        # Spin bins
-        prespin = wx.SpinCtrl(self.buttonarea, -1, min=100,
-                              max=500000000, value="1000")
-        prespin.SetMinSize(minsize)
-        presizer.Add(prespin)    
-        # Text tbin
-        pretextt = wx.StaticText(self.buttonarea, -1, u"Bin width [µs]:")
-        presizer.Add(pretextt)
-        # Spin tbin
-        prespint = edclasses.FloatSpin(self.buttonarea, value="5.0")
-        prespint.SetMinSize(minsize)
-        presizer.Add(prespint)  
-        # Text binfshift
-        preshifttextt = wx.StaticText(self.buttonarea, -1, "Bin shift:")
-        presizer.Add(preshifttextt)   
-        # Spin shift bins
-        prespinshift = wx.SpinCtrl(self.buttonarea, -1, min=0,
-                                   max=500000000, value="0")
-        prespinshift.SetMinSize(minsize)
-        presizer.Add(prespinshift)   
-        # Button
-        prebutt = wx.Button(self.buttonarea, label="Calculate and plot")
-        self.Bind(wx.EVT_BUTTON, self.OnBinning_Prebin, prebutt)
-        presizer.Add(prebutt)
-        self.BoxPrebin = list()
-        self.BoxPrebin.append(prebox)       # 0 box
-        self.BoxPrebin.append(pretext)      # 1 text: enter # events to use
-        self.BoxPrebin.append(prespin)      # 2 spin: how many bins to bin
-        self.BoxPrebin.append(pretextt)     # 3 text: enter bind width 
-        self.BoxPrebin.append(prespint)     # 4 spin: bin time
-        self.BoxPrebin.append(prebutt)      # 5 button
-        self.BoxPrebin.append(precheck)     # 6 checkbox: use linetime
-        self.BoxPrebin.append(prebplt)      # 7 text: bins per line
-        self.BoxPrebin.append(self.prebpl)  # 8 spin: bins per line
-        self.BoxPrebin.append(preshifttextt)  # 9 text: bin shift
-        self.BoxPrebin.append(prespinshift)  # 10 spin: bin shift
-
-
-        ## Total-binning
-        binbox = wx.StaticBox(self.buttonarea, label="Total-binning")
-        binsizer = wx.StaticBoxSizer(binbox, wx.VERTICAL)
-        # Some informative text
-        bintext = wx.StaticText(self.buttonarea, -1, "Bin entire file.")
-        binsizer.Add(bintext)
-        # OK button
-        binbutt = wx.Button(self.buttonarea, label="Calculate and plot all")
-        self.Bind(wx.EVT_BUTTON, self.OnBinning_Total, binbutt)
-        binsizer.Add(binbutt)
-        self.BoxBinTotal = [binbox, bintext, binbutt]
-
-
-        ## Mode
-        modebox = wx.StaticBox(self.buttonarea, label="Mode")
-        modesizer = wx.StaticBoxSizer(modebox, wx.VERTICAL)
-        # Some informative text
-        bintext = wx.StaticText(self.buttonarea, -1, "Type of measurement.")
-        modesizer.Add(bintext)
-        # Dropdown mode selection
-        Modelist = ["1 colour 1 focus", "2 colours 1 focus", "1 colour 2 foci",
-                    "2 colours 2 foci", "Alternating excitation"] 
-        self.ModeDropDown = wx.ComboBox(self.buttonarea, -1, "", (15, 30),
-                         wx.DefaultSize, Modelist, wx.CB_DROPDOWN)
-        self.ModeDropDown.SetMinSize(dropminsize)
-        self.ModeDropDown.SetSelection(0)
-        self.Bind(wx.EVT_COMBOBOX, self.Update, self.ModeDropDown)
-        modesizer.Add(self.ModeDropDown)
-        # Save trace checkbox
-        self.CheckBoxSaveTrace = wx.CheckBox(self.buttonarea, -1,
-             label="Save raw traces")
-        self.CheckBoxSaveTrace.SetValue(False)
-        modesizer.Add(self.CheckBoxSaveTrace)
-        
-        
-        ## Data
-        infobox = wx.StaticBox(self.buttonarea, label="Data")
-        insizer = wx.StaticBoxSizer(infobox, wx.VERTICAL)
-        sclock = wx.StaticText(self.buttonarea, -1,
-                               "System clock [MHz]: \t \t")
-        insizer.Add(sclock)
-        totalt = wx.StaticText(self.buttonarea, -1,
-                               "Total time [s]:  \t \t")
-        insizer.Add(totalt)
-        linet = wx.StaticText(self.buttonarea, -1, "Scan cycle [ms]:")
-        insizer.Add(linet)
-        linetdropdown = wx.ComboBox(self.buttonarea, -1, "", (15, 30),
-                         wx.DefaultSize, [], wx.CB_DROPDOWN)
-        linetdropdown.SetMinSize(dropminsize)
-        insizer.Add(linetdropdown)
-        self.Bind(wx.EVT_COMBOBOX, self.OnLinetimeSelected,
-                  linetdropdown)
-        self.Bind(wx.EVT_TEXT, self.OnLinetimeSelected, linetdropdown)
-        # Do not change order of BoxInfo!!
-        self.BoxInfo = [sclock, totalt, linetdropdown, infobox, linet]
-        
-        
-        ## Scan cycle periodicity
-        lscanbox = wx.StaticBox(self.buttonarea,
-                                label="Scan cycle periodicity")
-        lscansizer = wx.StaticBoxSizer(lscanbox, wx.VERTICAL)
-        # Magic checkbox
-        lscanmagic = wx.CheckBox(self.buttonarea,
-                                 label="Find automagically")
-        lscanmagic.SetValue(True)
-        lscansizer.Add(lscanmagic)
-        # OK button
-        lscanbutt = wx.Button(self.buttonarea,
-                              label="Find periodicity (FFT)")
-        self.Bind(wx.EVT_BUTTON, self.OnFindLineScanTime, lscanbutt)
-        lscansizer.Add(lscanbutt)
-        self.BoxLineScan = [lscanbox, lscanmagic, lscanbutt]
-
-
-        ## Image selection
-        # Add radio buttons that change behavior of mouse in Plot
-        userbox = wx.StaticBox(self.buttonarea, label="Image selection")
-        usizer = wx.StaticBoxSizer(userbox, wx.VERTICAL)
-        self.RbtnLinet = wx.RadioButton (self.buttonarea, -1,
-                   'Scan cycle correction % +/-: ', style = wx.RB_GROUP)
-        self.linespin = floatspin.FloatSpin(self.buttonarea, digits=10,
-                                      increment=.001)
-        self.linespin.SetMinSize(minsize)
-        self.linespin.Bind(wx.EVT_SPINCTRL, self.CorrectLineTime)
-        self.RbtnSelect = wx.RadioButton (self.buttonarea, -1,
-                                          'Select region 1')
-        self.RbtnSelectB = wx.RadioButton (self.buttonarea, -1,
-                                           'Select region 2')
-        self.RbtnLinet.SetValue(True)
-        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelector,
-                  self.RbtnSelect)
-        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelector,
-                  self.RbtnSelectB)
-        self.Bind(wx.EVT_RADIOBUTTON, self.OnRadioSelector,
-                  self.RbtnLinet)
-        # version 0.2.2: Add button "full measurement time"
-        fullmeasbutt = wx.Button(self.buttonarea,
-                              label="Full measurement time")
-        self.Bind(wx.EVT_BUTTON, self.OnSetFullMeasTime, fullmeasbutt)
-        usizer.Add(self.RbtnLinet)
-        usizer.Add(self.linespin)
-        usizer.Add(self.RbtnSelect)
-        usizer.Add(self.RbtnSelectB)
-        usizer.Add(fullmeasbutt)
-        self.BoxImageSelection = [userbox, self.RbtnLinet,
-         self.linespin, self.RbtnSelect, self.RbtnSelectB, fullmeasbutt]
-
-
-        ## Correlation
-        corrbox = wx.StaticBox(self.buttonarea, label="Correlation")
-        corrsizer = wx.StaticBoxSizer(corrbox, wx.VERTICAL)
-        # Add switch for 
-        # how many bins next to a maximum should be used for the trace
-        corrsizerText1 = wx.StaticText(self.buttonarea, 
-                     label="Span +/-:")
-        corrsizer.Add(corrsizerText1)
-        self.Spinnumax = wx.SpinCtrl(self.buttonarea, -1, min=0,
-                                     max=50000, value="3")
-        self.Spinnumax.SetMinSize(minsize)
-        corrsizer.Add(self.Spinnumax)
-        # Add switch for slicing of trace
-        corrsizerText3 = wx.StaticText(self.buttonarea, 
-                     label="No. of trace slices:")
-        corrsizer.Add(corrsizerText3)
-        self.Spinslice = wx.SpinCtrl(self.buttonarea, -1, min=1,
-                                     max=50000, value="10")
-        self.Spinslice.SetMinSize(minsize)
-        corrsizer.Add(self.Spinslice)
-        # Trace
-        # Switch for bleaching correction
-        self.CheckBoxBleachFilter = wx.CheckBox(self.buttonarea, -1,
-             label="Bleach filter")
-        self.CheckBoxBleachFilter.SetValue(True)
-        corrsizer.Add(self.CheckBoxBleachFilter)
-        # Switch for countrate correction
-        self.CheckBoxCountrateFilter = wx.CheckBox(self.buttonarea, -1,
-             label="Countrate filter")
-        self.CheckBoxCountrateFilter.SetValue(False)
-        corrsizer.Add(self.CheckBoxCountrateFilter)
-        # Add switch for m
-        # m is the parameter that defines the number of channels
-        # after which the the intensity trace is binned (neighboring
-        # pixels are combined) for calculation of the
-        # correlation function on a semi-logarithmic scale. 
-        corrsizerText2 = wx.StaticText(self.buttonarea, 
-                     label=u"M.-τ parameter m:")
-        corrsizer.Add(corrsizerText2)
-        self.Spinm = wx.SpinCtrl(self.buttonarea, -1, min=16, max=50000,
-                                 value="16")
-        self.Spinm.SetMinSize(minsize)
-        corrsizer.Add(self.Spinm)
-        ## Multiple Tau
-        # Get Autocorrelation function
-        taubutt = wx.Button(self.buttonarea, label="Get correlation")
-        self.Bind(wx.EVT_BUTTON, self.OnMultipleTau, taubutt)
-        corrsizer.Add(taubutt)
-        self.BoxMultipleTau = [self.CheckBoxBleachFilter, corrbox,
-              corrsizerText3, corrsizerText1, self.Spinnumax,
-              corrsizerText2, self.Spinm, self.Spinslice, taubutt,
-              self.CheckBoxCountrateFilter]
-
-
-        ## Set sizes
-        firlist = [presizer, binsizer, modesizer]
-        firmin = 100
-        for abox in firlist:
-            firmin = max(abox.GetMinSize()[0], firmin)
-        for abox in firlist:
-            abox.SetMinSize((firmin, -1))
-        seclist = [corrsizer, usizer, lscansizer, insizer]
-        secmin = 100
-        for abox in seclist:
-            secmin = max(abox.GetMinSize()[0], secmin)
-        for abox in seclist:
-            abox.SetMinSize((secmin, -1))
-
-
-        ## Put everything together
-        self.firvert = wx.BoxSizer(wx.VERTICAL)
-        self.firvert.Add(presizer)
-        self.firvert.AddSpacer(5)
-        self.firvert.Add(binsizer)
-        self.firvert.AddSpacer(5)
-        self.firvert.Add(modesizer)
-        self.secvert = wx.BoxSizer(wx.VERTICAL)
-        self.secvert.Add(insizer)
-        self.secvert.AddSpacer(5)
-        self.secvert.Add(lscansizer)
-        self.secvert.AddSpacer(5)
-        self.secvert.Add(usizer)
-        self.secvert.AddSpacer(5)
-        self.secvert.Add(corrsizer)
-        self.firhorz = wx.BoxSizer(wx.HORIZONTAL)
-        self.firhorz.AddSpacer(5)
-        self.firhorz.Add(self.firvert)
-        self.firhorz.AddSpacer(5)
-        self.firhorz.Add(self.secvert)
-        self.buttonarea.SetSizer(self.firhorz)
-
-
-    def MakeMenu(self):
-        ## Setting up the menus.
-        filemenu = wx.Menu()
-        self.cachemenu = wx.Menu()
-        prefmenu = wx.Menu()
-        helpmenu = wx.Menu()
-
-        # wx.ID_ABOUT and wx.ID_EXIT are standard IDs provided by wxWidgets.
-        # filemenu
-        menuOpenDat = filemenu.Append(wx.ID_OPEN, "&Open photon events .dat file", 
- "Opens a correlator file (.dat) that contains photon arrival time differences")
-        menuOpenFits = filemenu.Append(wx.ID_ANY, "Open .&fits file", 
-                              "Opens a previously binned intensity file (.fits)")
-        self.menuSaveDat = filemenu.Append(wx.ID_ANY, "&Save 32 bit .dat file", 
-              "Saves photon arrival time difference data in 32 bit file format")
-        self.menuSaveFits = filemenu.Append(wx.ID_SAVE, "&Save .fits file", 
-                                 "Saves binned intensity data into a .fits file")
-        filemenu.AppendSeparator()
-        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit", "Terminate the program")
-
-        # prefmenu
-        self.MenuVerbose = prefmenu.Append(wx.ID_ANY, "Verbose mode",
-                            "Enables/Disables output of additional information.",
-                            kind=wx.ITEM_CHECK)
-        # Check by default
-        self.MenuVerbose.Check()
-
-        menuDocu = helpmenu.Append(wx.ID_ANY, "&Documentation",
-                                    "PyCorrFit documentation")
-        menuWiki = helpmenu.Append(wx.ID_ANY, "&Wiki",
-                          "PyCorrFit wiki pages by users for users (online)")
-        menuUpdate = helpmenu.Append(wx.ID_ANY, "&Update",
-                                    "Check for new version"+
-                                     " (Web access required)")
-        helpmenu.AppendSeparator()
-        menuSoftw = helpmenu.Append(wx.ID_ANY, "&Software used",
-                                    "Information about software used by this program")
-        menuAbout = helpmenu.Append(wx.ID_ABOUT, "&About",
-                                    "Information about this program")
-
-        # Creating the menubar.
-        self.menuBar = wx.MenuBar()
-        self.menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
-        self.menuBar.Append(self.cachemenu,"&Cache") 
-        self.menuBar.Append(prefmenu,"&Preferences")
-        self.menuBar.Append(helpmenu,"&Help")
-
-        self.SetMenuBar(self.menuBar)  # Adding the MenuBar to the Frame content.
-        
-        ## Set events
-        #File
-        self.Bind(wx.EVT_MENU, self.OnMenuExit, menuExit)
-        self.Bind(wx.EVT_MENU, self.OnOpenDat, menuOpenDat)
-        self.Bind(wx.EVT_MENU, self.OnOpenFits, menuOpenFits)
-        self.Bind(wx.EVT_MENU, self.OnSaveDat, self.menuSaveDat)
-        self.Bind(wx.EVT_MENU, self.OnSaveFits, self.menuSaveFits)
-
-        # Help
-        self.Bind(wx.EVT_MENU, self.OnMenuAbout, menuAbout)
-        self.Bind(wx.EVT_MENU, self.OnMenuUpdate, menuUpdate)
-        self.Bind(wx.EVT_MENU, self.OnMenuSoftware, menuSoftw)
-        self.Bind(wx.EVT_MENU, self.OnMenuDocumentation, menuDocu)
-        self.Bind(wx.EVT_MENU, self.OnMenuWiki, menuWiki)
-
-
-
-
-    def OnBinning_Prebin(self, event=None):
-        """ Do prebinngin using *Bin_Photon_Events()* """
-        n_events = self.BoxPrebin[2].GetValue()
-        if self.BoxPrebin[6].GetValue() == False:
-            # from µs tp system clock ticks
-            t_bin = self.BoxPrebin[4].GetValue() * self.system_clock
-            ## If, reset previously achieved things. # - Why?
-            # self.t_linescan = None
-            self.Update()
-        else:
-            # Calculate t_bin through number of bins per line and cycle time
-            self.bins_per_line = self.BoxPrebin[8].GetValue()
-            t_bin = 1.0 * self.t_linescan / self.bins_per_line
-        # First we need to reset the linetime correction to zero
-        self.linespin.SetValue(0)
-        # Calculate binned data
-        self.intData = self.Bin_Photon_Events(n_events=n_events, t_bin=t_bin)
-
-        # Add to cache
-        self.AddToCache(self.intData, self.filename)
-
-
-        # Then Plot the data somehow
-        self.Update()
-        self.PlotImage()    
-
-
-    def OnBinning_Total(self, event=None):
-        if self.BoxPrebin[6].GetValue() == False:
-            # from µs to system clock ticks
-            t_bin = self.BoxPrebin[4].GetValue() * self.system_clock
-            # If, reset previously achieved things
-            self.t_linescan = None
-            self.Update()
-        else:
-            # Calculate t_bin through number of bins per line and cycle time
-            self.bins_per_line = self.BoxPrebin[8].GetValue()
-            t_bin = 1.0 * self.t_linescan / self.bins_per_line
-        self.t_bin = t_bin
-        # First we need to reset the linetime correction to zero
-        self.linespin.SetValue(0)
-        # Calculate binned data
-        self.intData = self.Bin_All_Photon_Events(self.datData)
-
-        # Add to cache
-        self.AddToCache(self.intData, self.filename)
-
-        # Then Plot the data somehow
-        self.PlotImage()
-
-
-    def OnFindLineScanTime(self, event):
-        """
-        Find the time that the confocal microscope uses to capture a line
-        of data. This is done via FFT.
-        """
-        # Fourier Transform
-        cnData = fft(self.intData)
-        N = len(cnData)
-        # We only need positive/negative frequencies
-        amplitude = np.abs(cnData[0:N/2]*np.conjugate(cnData[0:N/2]))
-        #n_bins = len(self.intData)
-
-        # Calculate the correct frequencies
-        rate = 1./self.t_bin
-        frequency = fftfreq(N)[0:N/2] * rate
-
-        if self.BoxLineScan[1].GetValue() == True:
-            # Find it automagically
-            # The first big maximum is usually the second maximum
-            idx = np.argmax(amplitude[10:])+10
-            # The first maximum is what we want ERROR
-            idx2 = np.argmax(amplitude[10:idx-30])+10
-            # Sometimes the first one was ok.
-            if 0.1*amplitude[idx] > amplitude[idx2]:
-                idx2 = idx
-            # We now have the maximum, but we actually want to have some
-            # kind of a weighted maximum. For that we take k data points next
-            # to the maximum and weigth them with their relative amplitude.
-            k = 10
-            timeweights = list()
-            timeweights.append(1/frequency[idx2])
-            Pie = 1
-            for i in np.arange(k):
-                weighta = amplitude[idx2+i+1]/amplitude[idx2]
-                weightb = amplitude[idx2-i-1]/amplitude[idx2]
-                timeweights.append(weighta/frequency[idx2+i+1])
-                timeweights.append(weightb/frequency[idx2-i-1])
-                Pie = Pie + weighta + weightb
-
-            timeweights = np.array(timeweights)
-            ltime = np.sum(timeweights, dtype="float")/Pie
-            self.t_linescan = ltime
-            # Plot the results (not anymore, we do a low_prebin)
-            #self.PlotImage()
-            # Set Checkbox value to True: "use cycle time"
-            self.BoxPrebin[6].SetValue(True)
-            self.Update()
-            self.OnBinning_Prebin()
-        else:
-            # Pop up a dialog with the fourier transform of the function
-            # (log -plot) and let user decide which maximum to use.
-            dlg = FFTmaxDialog(self, frequency, amplitude)
-            dlg.Show()
-
-
-    def OnLinetimeSelected(self, e=None):
-        Dropdown = self.BoxInfo[2]
-        Text = Dropdown.GetValue()
-        test = Text.split(".", 1)
-        for item in test:
-            if not item.isdigit():
-                return
-        Value = np.float(Text)
-        #sel = Dropdown.GetSelection()
-        elements = list()
-        for factor in [0.25, 0.5, 1.0, 2.0, 4]:
-            elements.append(str(np.float(Value*factor)))
-        Dropdown.SetItems(elements)
-        Dropdown.SetSelection(2)
-        #self.dropdown.SetSelection(0)
-        # Translate selected time to clockticks
-        # Value = self.t_linescan*1e-3/self.system_clock
-        if self.system_clock is None:
-            sysclck = 60
-        else:
-            sysclck = self.system_clock
-        # Avoid making str to float conversion errors?
-        # Use the second element, which is in the middle. (!!)
-        self.t_linescan = np.float(elements[2])*1e3*sysclck
-        self.BoxPrebin[6].Enable()
-        #self.Update()
-
-
-    def OnMenuAbout(self, event):
-        # Show About Information
-        description = doc.description()
-        licence = doc.licence()
-        info = wx.AboutDialogInfo()
-        #info.SetIcon(wx.Icon('hunter.png', wx.BITMAP_TYPE_PNG))
-        info.SetName('PyScanFCS')
-        info.SetVersion(self.version)
-        info.SetDescription(description)
-        info.SetCopyright('(C) 2012 Paul Müller')
-        info.SetWebSite('http://pyscanfcs.craban.de')
-        info.SetLicence(licence)
-        info.AddDeveloper('Paul Müller')
-        info.AddDocWriter('Paul Müller')
-        wx.AboutBox(info)
-
-
-    def OnMenuDocumentation(self, e=None):
-        """ Get the documentation and view it with browser"""
-        filename = doc.GetLocationOfDocumentation()
-        if filename is None:
-            # Now we have to tell the user that there is no documentation
-            self.StatusBar.SetStatusText("...documentation not found.")
-        else:
-            self.StatusBar.SetStatusText("...documentation: "+filename)
-            if platform.system().lower() == 'windows':
-                os.system("start /b "+filename)
-            elif platform.system().lower() == 'linux':
-                os.system("xdg-open "+filename+" &")
-            elif platform.system().lower() == 'darwin':
-                os.system("open "+filename+" &")
-            else:
-                # defaults to linux style:
-                os.system("xdg-open "+filename+" &")
-
-
-    def OnMenuExit(self,e):
-        # Exit the Program
-        self.Close(True)  # Close the frame.
-
-
-    def OnMenuSoftware(self, event):
-        # Show About Information
-        text = doc.SoftwareUsed()
-        wx.MessageBox(text, 'Software', wx.OK | wx.ICON_INFORMATION)
-
-
-    def OnMenuUpdate(self, event):
-        misc.Update(self)
-
-
-    def OnMenuWiki(self, e=None):
-        """ Go to the GitHub Wiki page"""
-        webbrowser.open(doc.GitWiki)
-
-    def OnMultipleTau(self, e=None):
-        """ Perform a multiple tau algorithm.
-            We sneak in a plt.plot here and there
-            so the user can take a look at the results.
-        """
-        # Reset the bleaching profile
-        self.file_bleach_profile = list()
-        wx.BeginBusyCursor()
-        ## Dirty, but makes it shorter. We need the namespace:
-        def SaveAC(Gtype, traceData):
-            for i in np.arange(num_traces):
-                usedTrace = traceData[i*NM:(i+1)*NM]
-                # Get the tail for the last trace
-                if i == num_traces -1:
-                    usedTrace = traceData[i*NM:]
-                # Calculate AC function and trace with human readable length
-                G = multipletau.autocorrelate(usedTrace,
-                                    m=m, deltat=bintime, normalize=True)
-                if self.MenuVerbose.IsChecked():
-                    plt.figure(0)
-                    plt.plot(G[:,0], G[:,1], "-")
-                ## Correction that finds the correct countrate
-                # self.TraceCorrectionFactor is 1.0, if the user
-                # did not check the "countrate filter"
-                usedTrace = usedTrace*self.TraceCorrectionFactor
-                trace = SFCSnumeric.ReduceTrace(usedTrace,
-                                                bintime, length=700)
-                # Save Correlation function
-                csvfile = filenamedummy+"_"+Gtype+"_"+str(i+1)+".csv"
-                self.SaveCSVFile(G, trace, csvfile, i+1, num_traces, Type=Gtype)
-                Arc.write(csvfile)
-                os.remove(csvfile)
-
-        def SaveCC(Gtype, tracea, traceb, swaptraces):
-            for i in np.arange(num_traces):
-                usedTa = tracea[i*NM:(i+1)*NM]
-                usedTb = traceb[i*NM:(i+1)*NM]
-                # Get the tail for the last trace
-                if i == num_traces -1:
-                    usedTa = tracea[i*NM:]
-                    usedTb = traceb[i*NM:]
-                G = multipletau.correlate(usedTa, usedTb,
-                                    m=m, deltat=bintime, normalize=True)
-                if self.MenuVerbose.IsChecked():
-                    plt.figure(0)
-                    plt.plot(G[:,0], G[:,1], "--")
-                ## Correction that finds the correct countrate
-                # self.TraceCorrectionFactor is 1.0, if the user
-                # did not check the "countrate filter"
-                usedTa = usedTa*self.TraceCorrectionFactor
-                usedTb = usedTb*self.TraceCorrectionFactor
-                tra = SFCSnumeric.ReduceTrace(usedTa,
-                                              bintime, length=700)
-                trb = SFCSnumeric.ReduceTrace(usedTb,
-                                              bintime, length=700)
-                # In order to keep trace1 trace1 and trace2 trace2, we
-                # need to swap here:
-                if swaptraces == True:
-                    tra, trb = trb, tra
-                # Save Correlation function
-                csvfile = filenamedummy+"_"+Gtype+"_"+str(i+1)+".csv"
-                self.SaveCSVFile(G, tra, csvfile, i+1, num_traces, 
-                                 Type=Gtype, secondtrace=trb)
-                Arc.write(csvfile)
-                os.remove(csvfile)
-
-
-        ## Get some needed data
-        # bin time in s (for the correlation function)
-        bintime = self.t_linescan/self.system_clock/1e6
-        # m value for multiple tau algorithm
-        m = self.Spinm.GetValue()
-        # Number of traces to slice the big trace into
-        num_traces = self.Spinslice.GetValue()
-        # Number of bins next to the maximum to use for the trace
-        num_next_max = self.Spinnumax.GetValue()
-        # Whether full traces should be saved in separate files
-        save_trace = self.CheckBoxSaveTrace.GetValue()
-
-        # Define zip file name
-        # filenamedummy is a non-wildcard filename
-        wildcards = ["A.dat", ".dat", "A.fits", ".fits"]
-        filenamedummy = self.filename
-        for card in wildcards:
-            lwc = len(card)
-            if self.filename[-lwc:] == card:
-                filenamedummy = self.filename[:-lwc]
-        zipfilename = os.path.join(self.dirname, filenamedummy)+".zip"
-
-        OURMODE = self.ModeDropDown.GetSelection()
-        # 0: 1 colour 1 focus   A
-        # 1: 2 colours 1 focus  A+B
-        # 2: 1 colour 1 foci    A
-        # 3: Quad               A+B
-        # 4: Pie                A+B
-
-        if OURMODE != 0 and OURMODE != 2:
-            # Bin the second file or check for a .fits file
-            if self.filename[-6:] == "A.fits":
-                # Open fits file and load second intData
-                filename = self.filename[:-6]+"B.fits"
-                fits = pyfits.open(os.path.join(self.dirname, filename))
-                series = fits[0]
-                intData2 = series.data
-                # Set proper 1D shape for intdata
-                length = self.intData2.shape[0] * self.intData2.shape[1]
-                intData2.shape = length
-            elif self.filename[-5:] == "A.dat":
-                # Check if we have B.dat in the cache
-                # 
-                # Open B.dat file
-                filename = self.filename[:-5]+"B.dat"
-                try:
-                    bcache = self.cache[filename]
-                    if (bcache["dirname"] != self.dirname or 
-                        bcache["bins_per_line"] != self.bins_per_line or 
-                        bcache["linetime"] != self.t_linescan):
-                        # We are in the wrong directory
-                        raise KeyError
-                except KeyError:
-                    # Open B.dat and add to cache
-                    filenames = os.path.join(self.dirname, filename)
-                    style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME|wx.PD_CAN_ABORT
-                    dlg2 = wx.ProgressDialog("Processing 2nd file", 
-                           "Finding 32 bit events...", parent=self, style=style)
-                    system_clock, datData2 = SFCSnumeric.OpenDat(filenames, dlg2)
-                    dlg2.Destroy()
-                    # Bin to obtain intData2
-                    intData2 = self.Bin_All_Photon_Events(datData2)
-                    # Add to cache
-                    self.AddToCache(intData2, filename, background=True)
-                else:
-                    intData2 = 1*bcache["data"]
-                    
-            else:
-                # We should not be here.
-                print "No A.dat or A.fits file opened. Aborting."
-                return
-
-        # Start plotting?
-        if self.MenuVerbose.IsChecked():
-            plt.figure(0)
-            axc = plt.subplot(111)
-
-        # Create .zip archive
-        Arc = zipfile.ZipFile(zipfilename, mode='w')
-        returnWD = os.getcwd()
-        tempdir = tempfile.mkdtemp()
-        os.chdir(tempdir)
-
-        ### 1 color 1 focus
-        if self.ModeDropDown.GetSelection() == 0:
-            traceData = self.GetTraceFromIntData(self.intData, self.XY_Trace_square)
-            # Variable *SaveAC* will need.
-            NM = int(np.floor(len(traceData)/num_traces))
-            traces = [traceData]
-            ## Get autocorrelation functions of splitted trace
-            Gtype = "AC_A1"
-            SaveAC(Gtype, traceData)
-
-        ### 2 colour 1 focus
-        elif self.ModeDropDown.GetSelection() == 1:
-            traceData1 = self.GetTraceFromIntData(self.intData, 
-                                        self.XY_Trace_square, title="Region A1")
-            NM = int(np.floor(len(traceData1)/num_traces))
-            traceData2 = self.GetTraceFromIntData(intData2,
-                                        self.XY_Trace_square, title="Region B1")
-            ## Get autocorrelation functions of splitted trace
-            traces = [traceData1, traceData2]
-            # Save Autocorrelation
-            for j in np.arange(len(traces)):
-                traceData = traces[j]
-                if j == 0:
-                    Gtype = "AC_A1"
-                else: # j==1
-                    Gtype = "AC_B1"
-                SaveAC(Gtype, traceData)
-            # Save Cross correlation
-            for j in np.arange(len(traces)):
-                if j == 0:
-                    Gtype = "CC_A1B1"
-                    tracea = traces[0]
-                    traceb = traces[1]
-                    swaptraces = False
-                else: # j==1
-                    Gtype = "CC_B1A1"
-                    tracea = traces[1]
-                    traceb = traces[0]
-                    swaptraces = True
-                SaveCC(Gtype, tracea, traceb, swaptraces)
-
-
-        ## 1 Colour 2 Foci
-        elif self.ModeDropDown.GetSelection() == 2:
-            traceData1 = self.GetTraceFromIntData(self.intData, 
-                                        self.XY_Trace_square, title="Region A1")
-            NM = int(np.floor(len(traceData1)/num_traces))
-            traceData2 = self.GetTraceFromIntData(self.intData,
-                                       self.XY_Trace_squareB, title="Region A2")
-            ## Get autocorrelation functions of splitted trace
-            traces = [traceData1, traceData2]
-            # Save Autocorrelation
-            for j in np.arange(len(traces)):
-                traceData = traces[j]
-                if j == 0:
-                    Gtype = "AC_A1"
-                else: # j==1
-                    Gtype = "AC_A2"
-                SaveAC(Gtype, traceData)
-
-            # Save Cross correlation
-            for j in np.arange(len(traces)):
-                if j == 0:
-                    Gtype = "CC_A1A2"
-                    tracea = traces[0]
-                    traceb = traces[1]
-                    swaptraces = False
-                else: # j==1
-                    Gtype = "CC_A2A1"
-                    tracea = traces[1]
-                    traceb = traces[0]
-                    swaptraces = True
-                SaveCC(Gtype, tracea, traceb, swaptraces)
-
-        ## Quad
-        elif self.ModeDropDown.GetSelection() == 3:
-            traceData1 = self.GetTraceFromIntData(self.intData,
-                                       self.XY_Trace_square, title="Region A1")
-            NM = int(np.floor(len(traceData1)/num_traces))
-            traceData2 = self.GetTraceFromIntData(self.intData,
-                                       self.XY_Trace_squareB, title="Region A2")
-            traceData3 = self.GetTraceFromIntData(intData2,
-                                       self.XY_Trace_square, title="Region B1")
-            traceData4 = self.GetTraceFromIntData(intData2,
-                                       self.XY_Trace_squareB, title="Region B2")
-            ## Get autocorrelation functions of splitted trace
-            traces = [traceData1, traceData2, traceData3, traceData4]
-            Gtypes = ["AC_A1", "AC_A2", "AC_B1", "AC_B2"]
-            # Save Autocorrelation
-            for j in np.arange(len(traces)):
-                traceData = traces[j]
-                Gtype = Gtypes[j]
-                SaveAC(Gtype, traceData)
-
-            # Save Cross correlation
-            Gtypes = ["A1", "A2", "B1", "B2"]
-            for j in np.arange(4):
-                for k in np.arange(4):
-                    if j != k:
-                        Gtype = "CC_"+Gtypes[j]+Gtypes[k]
-                        tracea = traces[j]
-                        traceb = traces[k]
-                        if j < k:
-                            swaptraces = False
-                        else:
-                            swaptraces = True
-                        SaveCC(Gtype, tracea, traceb, swaptraces)
-
-        ## PIE
-        elif self.ModeDropDown.GetSelection() == 4:
-            traceData1 = self.GetTraceFromIntData(self.intData,
-                                       self.XY_Trace_square, title="Region A1")
-            NM = int(np.floor(len(traceData1)/num_traces))
-            traceData2 = self.GetTraceFromIntData(intData2,
-                                       self.XY_Trace_squareB, title="Region B2")
-            ## Get autocorrelation functions of splitted trace
-            traces = [traceData1, traceData2]
-            # Save Autocorrelation
-            for j in np.arange(len(traces)):
-                traceData = traces[j]
-                if j == 0:
-                    Gtype = "AC_A1"
-                else: # j==1
-                    Gtype = "AC_B2"
-                SaveAC(Gtype, traceData)
-
-            # Save Cross correlation
-            for j in np.arange(len(traces)):
-                if j == 0:
-                    Gtype = "CC_A1B2"
-                    tracea = traces[0]
-                    traceb = traces[1]
-                    swaptraces = False
-                else: # j==1
-                    Gtype = "CC_B2A1"
-                    tracea = traces[1]
-                    traceb = traces[0]
-                    swaptraces = True
-                SaveCC(Gtype, tracea, traceb, swaptraces)
-
-        # Add bleaching profile files
-
-        for bleach_file in self.file_bleach_profile:
-            olddir = os.getcwd()
-            os.chdir(os.path.dirname(bleach_file))
-            try:
-                Arc.write(os.path.basename(bleach_file))
-            except:
-                pass
-            os.chdir(olddir)
-        
-        os.chdir(returnWD)
-        os.removedirs(tempdir)
-        Arc.close()
-
-        if self.MenuVerbose.IsChecked():
-            plt.figure(0)
-            plt.semilogx()
-            plt.ylabel('Correlation')
-            plt.xlabel('Lag time [s]')
-            plt.show()
-
-        ## Save all the traces
-        if save_trace == True:
-            for i in np.arange(len(traces)):
-                filename = filenamedummy + "_"+str(i)+".txt"
-                filename = os.path.join(self.dirname, filename)
-                openedfile = open(filename, 'wb')
-                openedfile.write('# This file was created using PyScanFCS v.'+\
-                                  self.version+"\r\n")
-                openedfile.write("# Source file: "+filenamedummy+"\r\n")
-                openedfile.write("# linetime [s]: "+str(bintime)+"\r\n")
-                openedfile.write("# bins per line: "+
-                                  str(self.bins_per_line)+"\r\n")
-                openedfile.write("# bins used per line: "+
-                                  str(2*num_next_max+1)+"\r\n")
-                for j in np.arange(len(traces[i])):
-                    openedfile.write(str(traces[i][j])+"\r\n")
-
-        wx.EndBusyCursor()
-
-          
-
-    def OnOpenFits(self,e):
-        # Open a data file
-        """Import experimental data from a file."""
-        dlg = wx.FileDialog(self, "Choose a fits file", self.dirname, "", 
-              "FITS files (*.fits)|*.Fits;*.FITS;*.fits",
-              wx.OPEN)
-        # user cannot do anything until he clicks "OK"
-        if dlg.ShowModal() == wx.ID_OK:
-        
-            # Workaround for Ubuntu 12.10 since 0.2.0
-            (self.dirname, self.filename) = os.path.split(dlg.GetPath())
-            #self.filename = dlg.GetFilename()
-            #self.dirname = dlg.GetDirectory()
-     
-            fits = pyfits.open(os.path.join(self.dirname, self.filename))
-            series = fits[0]
-            self.imgData = None
-            self.intData = series.data
-            self.datData = None
-
-
-            # Set all variables
-            head = series.header
-
-            self.system_clock = head['SysClck']
-            try:
-                self.T_total = head['Total']
-            except KeyError:
-                self.T_total = None
-            try:
-                self.t_linescan = head['Tline']
-            except KeyError:
-                # Old "line scanning time" has new name: "scan cycle time"
-                self.t_linescan = head['Tcycle']
-            self.t_bin = head['Tbin']
-            try:
-                eb = head['Binshift']
-            except KeyError:
-                pass
-            else:
-                self.BoxPrebin[10].SetValue(eb)
-
-            self.bins_per_line = len(self.intData[0])
-            self.prebpl.SetValue(self.bins_per_line)
-
-            # Plot
-            # Set proper 1D shape for intdata
-            length = self.intData.shape[0] * self.intData.shape[1]
-            self.intData.shape = length
-            self.Update()
-            self.PlotImage()
-
-
-
-    #Current
-    def OnOpenDat(self,e):
-        # Open a data file
-        """
-        We open a .dat file as produced by the "Flex02-12D" correlator in photon
-        history recorder mode.
-        The file contains the time differences between single photon events.
-
-        Returns:
-        This function makes the filename publicly available, bins a couple
-        of events to get 1e+6 points and plots them into the plotting area
-        (self.plotarea), using the Bin_Photon_Events() function.
-
-        Raw data file format (taken from manual):
-         1. The file records the difference in system clock ticks (1/60 us)
-            between photon event.
-         2. The first byte identifies the format of the file 8 : 8 bit, 16: 16 bit
-         3. The second byte identifies the system clock. 60MHz.
-         4. The time unit is 1/system clock.
-         5. 16 bit format. Each WORD (2 bytes) represents a photon event, 
-            time = WORD/system clock, unless the value is 0xFFFF, in which case, 
-            the following four bytes represent a photon event.
-         6. 8 bit format: Each BYTE represents a photon event unless the value is 
-            0xFF, in which case, the BYTE means 255 clock ticks passed without a 
-            photon event. For example 0A 0B FF 08 means there are three
-            photon events. The time series are 0x0A+1, 0x0B+1, 0xFF+8+1.
-
-        """
-        # File Dialog
-        dlg = wx.FileDialog(self, "Choose a data file", self.dirname, "", 
-              "DAT files (*.dat)|*.dat;*.daT;*.dAt;*.dAT;*.Dat;*.DaT;*.DAt;*.DAT",
-              wx.OPEN)
-        # user cannot do anything until he clicks "OK"
-        if dlg.ShowModal() == wx.ID_OK:
-            # Workaround for Ubuntu 12.10 since 0.2.0
-            (self.dirname, self.filename) = os.path.split(dlg.GetPath())
-            #self.filename = dlg.GetFilename()
-            #self.dirname = dlg.GetDirectory()
-            filename = os.path.join(self.dirname, self.filename)
-            style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME|wx.PD_CAN_ABORT
-            dlg2 = wx.ProgressDialog("Processing file", "Finding 32 bit events..."
-            , parent=self, style=style)
-            self.system_clock, self.datData = SFCSnumeric.OpenDat(filename, dlg2)
-            dlg2.Destroy()
-            self.GetTotalTime()
-            self.Update()
-
-
-    def OnRadioSelector(self, e=None):
-        # Define what style of selector will be used in plot.
-        if self.RbtnLinet.Value == True:
-            self.plotarea.UseLineSelector()
-        else:
-            self.plotarea.UseRectangleSelector()
-        self.Update()
-
-
-    def OnSaveFits(self,e):
-        # Save the Data
-        """ Save binned data as a 2d array (image) """
-        if self.filename[-4:] == ".dat":
-            newfilename = self.filename[:-4]+".fits"
-        else:
-            newfilename = ""
-        dlg = wx.FileDialog(self, "Choose a data file", self.dirname, newfilename, 
-              "FITS files (*.fits)|*.Fits;*.FITS;*.fits",
-           wx.SAVE|wx.FD_OVERWRITE_PROMPT)
-        # user cannot do anything until he clicks "OK"
-        if dlg.ShowModal() == wx.ID_OK:
-            # Workaround for Ubuntu 12.10 since 0.2.0
-            (self.dirname, newfilename) = os.path.split(dlg.GetPath())
-            #newfilename = dlg.GetFilename()
-            #self.dirname = dlg.GetDirectory()
-            # Creating image array
-            M = len(self.intData)
-            Ny = self.bins_per_line 
-            Nx = int(M/Ny)+1
-            # Plotting data will have some zeros at the end
-            plotdata = np.zeros(Nx*Ny)
-            # Check for maximum in self.intData
-            maxint = np.max(self.intData)
-            if maxint < 256:
-                plotdata = np.uint8(plotdata)
-                plotdata[0:M] = np.uint8(self.intData)
-            else:
-                plotdata[0:M] = self.intData
-            plotdata.shape = (Nx,Ny)
-            hdu = pyfits.PrimaryHDU(plotdata)
-            hdulist = pyfits.HDUList([hdu])
-            header = hdulist[0].header
-            # Add some constants:
-            cards = []
-            cards.append(pyfits.Card('SysClck', self.system_clock,
-                                "System clock [MHz]"))
-            if self.T_total is not None:
-                cards.append(pyfits.Card('Total', self.T_total,
-                               "Total time in system clock ticks"))
-            if self.t_linescan is not None:
-                t_linescan = self.t_linescan
-            else:
-                t_linescan = self.t_bin*len(self.imgData)
-
-            cards.append(pyfits.Card('Tcycle', t_linescan,
-                               "Time for each linescan in system clock ticks"))
-            cards.append(pyfits.Card('Tbin', self.t_bin,
-                               "Time for each bin in system clock ticks"))
-            eb = self.BoxPrebin[10].GetValue()
-            cards.append(pyfits.Card('Binshift', eb,
-                               "Empty bins before actual binning of data"))            
-  
-            for c in cards:
-                c.verify()
-                header.update(c.key, c.value, c.comment)
-            # clobber=True: Overwrites file.
-            hdulist.writeto(os.path.join(self.dirname, newfilename), clobber=True)
-
-
-    def OnSaveDat(self,e):
-        # Save the Data
-        """
-        Save experimental data as 32bit format.
-
-        Raw data file format:
-         1. The file records the difference in system clock ticks (1/60 us)
-            between photon events.
-         2. The first byte identifies the format of the file: 32 bit
-         3. The second byte identifies the system clock: usually 60MHz.
-         4. The time unit is 1/system clock.
-         5. 32 bit format. 4 bytes represent a photon event, 
-            time = 4 bytes/system clock
-        """
-        # Make a reasonable 32bit filename
-        if self.filename[-5:] == "A.dat":
-            newfilename = self.filename[:-5]+"_32bit_A.dat"
-        elif self.filename[-5:] == "B.dat":
-            newfilename = self.filename[:-5]+"_32bit_B.dat"
-        else:
-            newfilename = self.filename[:-4]+"_32bit.dat"
-        dlg = wx.FileDialog(self, "Choose a data file", self.dirname, newfilename, 
-              "DAT files (*.dat)|*.dat;*.daT;*.dAt;*.dAT;*.Dat;*.DaT;*.DAt;*.DAT",
-           wx.SAVE|wx.FD_OVERWRITE_PROMPT)
-        # user cannot do anything until he clicks "OK"
-        if dlg.ShowModal() == wx.ID_OK:
-            # Workaround for Ubuntu 12.10 since 0.2.0
-            (self.dirname, newfilename) = os.path.split(dlg.GetPath())
-            #newfilename = dlg.GetFilename()
-            #self.dirname = dlg.GetDirectory()
-            NewFile = open(os.path.join(self.dirname, newfilename), 'wb')
-            newformat = np.uint8(32)
-            newclock = np.uint8(self.system_clock)
-            NewFile.write(newformat)
-            NewFile.write(newclock)
-            self.datData.tofile(NewFile)
-            NewFile.close()
-
-
-    def OnSelectPlot(self, eclick, erelease):
-        # Define what will happen upon clicking on the plot.
-        if self.RbtnLinet.Value == True:
-            self.OnSelectLineTime(eclick, erelease)
-        else:
-            self.OnSelectRegion(eclick, erelease)
-        self.Update()
-
-
-
-    def OnSelectCache(self, e=None):
-        for item in self.cachemenu.GetMenuItems():
-            if item.IsChecked():
-                cachename = item.GetLabel()
-        cache=self.cache[cachename]
-        self.BoxPrebin[8].SetValue(cache["bins_per_line"])
-        self.bins_per_line = cache["bins_per_line"]
-        linetime = cache["linetime"]
-        if linetime is not None:
-            self.BoxInfo[2].SetValue(str(linetime/self.system_clock/1e3))
-        self.t_linescan = linetime
-        self.intData = 1*cache["data"]
-        self.filename = cachename
-        self.dirname = cache["dirname"]
-        filename = os.path.join(self.dirname, self.filename)
-        style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME|wx.PD_CAN_ABORT
-        dlg2 = wx.ProgressDialog("Processing file", "Finding 32 bit events..."
-        , parent=self, style=style)
-        self.system_clock, self.datData = SFCSnumeric.OpenDat(filename, dlg2)
-        dlg2.Destroy()
-        self.GetTotalTime()
-        self.Update()
-        self.PlotImage()
-
-
-    def OnSelectLineTime(self, eclick, erelease):
-
-        y1 = eclick.ydata
-        y2 = erelease.ydata
-        Tx1 = eclick.xdata
-        Tx2 = erelease.xdata
-
-        if Tx1 == Tx2:
-            return
-
-        # Since x and y ahve different scales, we need to
-        # multiply the y-part with 1e3 to get ms instead of s.
-        #
-        # See in PlotImage below:
-        #Tx = self.t_bin*Nx/self.system_clock/1e3
-        #Ty = Tx*Ny/1e3
-        #
-        x1 = 1e3*Tx1
-        x2 = 1e3*Tx2
-
-
-        if x1 > x2:
-            y2, y1 = y1, y2
-            x1, x2 = x2, x1
-
-        # Calculate correction factor
-        delta = (y2-y1)/(x2-x1)
-        # Calculate how much percent that is
-        percent = delta*100.
-
-        self.linespin.SetValue(np.float(percent))
-        self.percent = percent
-        self.CorrectLineTime(event=None)
-
-
-    def OnSelectRegion(self, eclick=None, erelease=None, fullMT=False):
-        """ Internally sets the region in the kymograph
-            
-            `eclick` and `erelease` are matplotlib events on a plot
-            
-            if `fulMT` is True and `eclick` and `erelease` are None,
-            then the x-values are overridden and old y-values are used.
-        """
-
-        if eclick is None and erelease is None and fullMT is True:
-            # try to get data from two sources:
-            if self.RbtnSelect.Value == True:
-                try:
-                    (y1,y2) = self.XY_Trace_square[1]
-                    # Line_time [ms] - convert to ms from (us and clock ticks)
-                    y1 /= 1e3 * self.system_clock
-                    y2 /= 1e3 * self.system_clock
-                except:
-                    pass
-            else:
-                try:
-                    (y1,y2) = self.XY_Trace_squareB[1]
-                    # Line_time [ms] - convert to ms from (us and clock ticks)
-                    y1 /= 1e3 * self.system_clock
-                    y2 /= 1e3 * self.system_clock
-                except:
-                    pass
-            if (y1, y2) == (None, None):
-                (y1, y2) = self.plotarea.axes.get_ylim()
-            # Get absolute x values
-            (x1, x2) = self.plotarea.axes.get_xlim()
-        else:
-            x1 = eclick.xdata
-            x2 = erelease.xdata
-            y1 = eclick.ydata
-            y2 = erelease.ydata
-
-        # Sort values
-        if x1 > x2:
-            x1, x2 = x2, x1
-        elif x1 == x2:
-            x2 = x1+1
-        if y1 > y2:
-            y1, y2 = y2, y1
-        elif y1 == y2:
-            y2 = y1+1
-
-        # Set the values of the corresponding spin controls
-        # To Do
-
-        # We have to distinguish between yellow and cyan square.
-        # self.square: yellow square
-        # self.square2: cyan square
-        if self.RbtnSelect.Value == True:
-            square = self.square
-            oldsquare = self.squareB
-            square_color = "yellow"
-            oldsquare_color = "cyan"
-            oldcoords = self.XY_Trace_squareB
-        else:
-            square = self.squareB
-            oldsquare = self.square
-            square_color = "cyan"
-            oldsquare_color = "yellow"
-            oldcoords = self.XY_Trace_square
-
-        # We should also plot it
-        if square is not None:
-            # Remove the old same coloured square
-            square.remove()
-        square = Rectangle( (x1,y1), abs(x2-x1), abs(y2-y1), 
-                                alpha = 0.1, color=square_color)
-        self.plotarea.axes.add_patch(square)
-
-
-        # Adjust the old square:
-        if oldsquare is not None:
-            oldsquare.remove()
-            oldsquare = None
-        if oldcoords[1] == (None,None):
-            (yn1, yn2) = (y1, y2)
-        else:
-            (yn1, yn2) = oldcoords[1]
-            yn1 *= 1e-3/self.system_clock
-            yn2 *= 1e-3/self.system_clock
-        
-        if self.ModeDropDown.GetSelection() > 1:
-
-            oldsquare = Rectangle( (x1,yn1), abs(x2-x1), abs(yn2-yn1), 
-                                alpha = 0.1, color=oldsquare_color)
-            self.plotarea.axes.add_patch(oldsquare)
-
-        self.plotarea.canvas.draw()
-
-        # Convert values to array indices and make public.
-        # Total_time [s] (convert to us and then to clock ticks)
-        x1 = (x1*1e6 * self.system_clock) 
-        x2 = (x2*1e6 * self.system_clock)
-        # Line_time [ms] (convert to us and then to clock ticks)
-        y1 = (y1*1e3 * self.system_clock) 
-        y2 = (y2*1e3 * self.system_clock)
-
-
-        if self.RbtnSelect.Value == True:
-            self.square = square
-            self.XY_Trace_square = [ (x1, x2), (y1,y2) ]
-            self.squareB = oldsquare
-            if oldsquare is not None:
-                self.XY_Trace_squareB[0] = (x1, x2)
-            
-        else:
-            self.squareB = square
-            self.XY_Trace_squareB = [ (x1, x2), (y1,y2) ]
-            self.square = oldsquare
-            if oldsquare is not None:
-                self.XY_Trace_square[0] = (x1, x2)
-
-
-    def OnSetFullMeasTime(self, e=None):
-        """ Sets the full range of the measurement time
-        """
-        self.OnSelectRegion(fullMT=True)
-
-
-    def PlotImage(self):
-        """
-            Plot self.intData. If not enough information about
-            e.g. cycle time is given we have to guess the dimensions
-            of the plot.
-        """
-        M = len(self.intData)
-        self.bins_per_line = Ny = self.BoxPrebin[8].GetValue()
-        Nx = int(np.floor(M/Ny))
-        # This checkbox is False, if we do not want to use t_linescan
-        # to set the length of a line.
-        if self.BoxPrebin[6].GetValue() == False:
-            # from µs to system clock ticks
-            t_bin = self.BoxPrebin[4].GetValue() * self.system_clock
-        else:
-            t_bin = self.t_linescan / self.bins_per_line
-        # This is a fast way of slicing our 1D intData array to a shorter
-        # plottable 2D array.
-        if Nx > Ny:
-            # Number of lines we have to jump over
-            P = Nx/Ny
-            Nx = P * Ny
-            plotdata = np.zeros((Ny,Ny))
-            MAX = Nx*Ny
-
-            for bin in np.arange(Ny):
-                # Take every P'th element in Nx direction
-                plotdata[bin] = self.intData[bin:MAX+bin:Ny*P]
-
-
-        else:
-            # We are lucky
-            plotdata = self.intData[:Nx*Ny]
-            plotdata.shape = (Nx,Ny)
-            plotdata = plotdata.transpose()
-
-
-        self.plotarea.image.set_data(plotdata)
-        # Set labels x [ms] and y[s]
-        Ty = self.t_bin*Ny/1e3/self.system_clock
-        Tx = Ty*Nx/1e3
-        self.plotarea.image.set_extent((0, Tx, Ty, 0))
-        # Make the square or else we would not see much
-        self.plotarea.axes.set_aspect(1.*Tx/Ty)
-
-        vmin = np.min(plotdata)
-        vmax = np.max(plotdata)
-        self.plotarea.colorbar.set_clim(vmin, vmax)
-        self.plotarea.colorbar.vmin = vmin
-        self.plotarea.colorbar.vmax = vmax
-        self.plotarea.colorbar.update_normal(self.plotarea.image)
-        self.plotarea.colorbar.set_ticks(np.arange(vmax+1), update_ticks=True)
-        self.plotarea.canvas.draw()
-
-        self.imgData = plotdata
-
-
-    def SaveCSVFile(self, G, trace, csvfile, num=1, num_traces=1, Type="AC",
-                    secondtrace=None):
-
-        openedfile = open(csvfile, 'wb')
-        openedfile.write('# This file was created using PyScanFCS v.'+\
-                         self.version+"\r\n")
-        openedfile.write("# Source file \t"+self.filename+"\r\n")
-        openedfile.write("# Source slice \t"+str(num)+" of "+str(num_traces)+"\r\n")
-        openedfile.write('# Channel (tau [s]) \t Correlation function \r\n')
-        if Type[:2] == "CC":
-            openedfile.write("# Type AC/CC \t Cross-Correlation "+Type[2:]+"\r\n")
-        else:
-            openedfile.write("# Type AC/CC \t Autocorrelation "+Type[2:]+"\r\n")
-        dataWriter = csv.writer(openedfile, delimiter='\t')
-        for i in np.arange(len(G)):
-            dataWriter.writerow([str(G[i,0])+" \t", str(G[i,1])])
-        openedfile.write('# BEGIN TRACE \r\n')
-        openedfile.write('# Time ([s]) \t Intensity Trace [kHz] \r\n')
-        for i in np.arange(len(trace)):
-            dataWriter.writerow([ str("%.10e")%trace[i,0], str("%.10e")%trace[i,1] ])
-
-        if secondtrace is not None:
-            openedfile.write('#\r\n# BEGIN SECOND TRACE \r\n')
-            openedfile.write('# Time ([s]) \t Intensity Trace [kHz] \r\n')
-            for i in np.arange(len(trace)):
-                dataWriter.writerow([ str("%.10e")%secondtrace[i,0], 
-                                      str("%.10e")%secondtrace[i,1] ])   
-
-        openedfile.close()
-
-
-    def Update(self, e=None):
-        self.UpdateInfo()
-        ### Box Prebin
-        #self.BoxPrebin.append(prebox)       # 0 box
-        #self.BoxPrebin.append(pretext)      # 1 text: enter # events to use
-        #self.BoxPrebin.append(prespin)      # 2 spin: how many bins to bin
-        #self.BoxPrebin.append(pretextt)     # 3 text: enter bin width 
-        #self.BoxPrebin.append(prespint)     # 4 spin: bin time
-        #self.BoxPrebin.append(prebutt)      # 5 button
-        #self.BoxPrebin.append(precheck)     # 6 checkbox: use linetime
-        #self.BoxPrebin.append(prebplt)      # 7 text: bins per line
-        #self.BoxPrebin.append(self.prebpl)  # 8 spin: bins per line
-        if self.datData is not None:
-            self.menuSaveDat.Enable(True)
-            for item in self.BoxPrebin:
-                item.Enable()
-            for item in self.BoxInfo:
-                item.Enable()
-            if self.t_linescan is not None:
-                for item in self.BoxBinTotal:
-                    item.Enable()
-            else:
-                for item in self.BoxBinTotal:
-                    item.Disable()
-        if self.t_linescan is not None:
-            # This means a linetime has been found
-            self.BoxPrebin[6].Enable()
-            #self.BoxPrebin[6].SetValue(True)
-        else:
-            self.BoxPrebin[6].Disable()
-            self.BoxPrebin[6].SetValue(False)
-        checked = self.BoxPrebin[6].GetValue()
-        if checked == True:
-            self.BoxPrebin[3].Disable()
-            self.BoxPrebin[4].Disable()
-        else:
-            self.BoxPrebin[3].Enable()
-            self.BoxPrebin[4].Enable()
-        # If no data is present, do not enable anything
-        if self.datData is None:
-            self.menuSaveDat.Enable(False)
-            for item in self.BoxPrebin:
-                item.Disable()
-            for item in self.BoxBinTotal:
-                item.Disable()
-            for item in self.BoxInfo:
-                item.Disable()
-
-
-        ### Box scan cycle time / Image Selection / Save Fits
-        if self.intData is None:
-            self.menuSaveFits.Enable(False)
-            for item in self.BoxLineScan:
-                item.Disable()
-            for item in self.BoxImageSelection:
-                item.Disable()
-        else:
-            self.menuSaveFits.Enable(True)
-            for item in self.BoxLineScan:
-                item.Enable()
-            for item in self.BoxImageSelection:
-                item.Enable()
-
-        ### Modes
-        if self.ModeDropDown.GetSelection() > 1 and self.intData is not None:
-            self.RbtnSelectB.Enable()
-        else:
-            self.RbtnSelectB.Disable()
-
-
-        ### MultipleTau Box
-        if self.square is None:
-            for item in self.BoxMultipleTau:
-                item.Disable()
-        else:
-            for item in self.BoxMultipleTau:
-                item.Enable()
-
-
-    def UpdateInfo(self):
-        # Initial data values:
-
-        if self.system_clock is not None:
-            self.BoxInfo[0].SetLabel("System clock [MHz]: "+str(self.system_clock))
-            if self.T_total is not None:
-                # This means a file has been opened
-                self.BoxInfo[1].SetLabel("Total time [s]: "+
-                                 str(self.T_total*1e-6/self.system_clock)[0:10])
-        if self.t_linescan is not None:
-            # This means a linetime has been found
-            self.BoxInfo[2].SetValue(str(self.t_linescan*1e-3/self.system_clock))
-            self.OnLinetimeSelected()
-
-
-## VERSION
-version = doc.__version__
-__version__ = version
-
-print doc.info(version)
-
-## Start gui
-def Main():
-    app = wx.App(False)
-    frame = MyFrame(None, -1, version)
-    app.MainLoop()
-
+sys.path = [split(abspath(dirname(__file__)))[0]] + sys.path
 
-if __name__ == "__main__":
-    Main()
+import pyscanfcs
+pyscanfcs.Main()
diff --git a/pyscanfcs/SFCSnumeric.pyx b/pyscanfcs/SFCSnumeric.pyx
index a47806c..f0cd98f 100755
--- a/pyscanfcs/SFCSnumeric.pyx
+++ b/pyscanfcs/SFCSnumeric.pyx
@@ -1,36 +1,27 @@
 # -*- coding: utf-8 -*-
-""" 
-    PyScanFCS
+""" Numerical algorithms for perpendicular line scanning FCS
     
-    Binning Data for Multiple Tau Algorithm
+(C) 2012 Paul Müller
 
-    As fast as you can get with python, binning the photon arrival times
-    created by Photon.exe from correlator.com.
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-    See at the end of the file, which .dat file will be opened.
-    In console, we ask for binning time in µs and an .int file
-    is created.
-    
-    (C) 2012 Paul Müller
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License 
-    along with this program. If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU General Public License 
+along with this program. If not, see <http://www.gnu.org/licenses/>.
 """
-
-#import codecs, sys, win32console
+from __future__ import division
 import sys
 import numpy as np                  # NumPy
 from scipy import optimize as spopt # For least squares fit
+import tempfile
+import warnings
 
 # See cython documentation for following stuff
 # "cimport" is used to import special compile-time information
@@ -61,14 +52,52 @@ cimport cython
 #from libcpp.vector cimport vector
 
 
+__all__ = ["BinPhotonEvents", "FitExp", "FitGaussian", "OpenDat",
+           "ReduceTrace"]
+
 
 @cython.cdivision(True)
 @cython.boundscheck(False) # turn of bounds-checking for entire function
-def BinPhotonEvents(np.ndarray[DTYPEuint32_t] data, double t_bin, filename, dtype, dlg, binshift=None):
-    """ Bin all photon arrival times in a numpy.uint32 array *data*, using 
+def BinPhotonEvents(np.ndarray[DTYPEuint32_t] data, double t_bin,
+                    binshift=None, outfile=None, outdtype=DTYPEuint16,
+                    callback=None, cb_kwargs={}):
+    """ Convert photon arrival times to a binned trace
+
+    Parameters
+    ----------
+    data : ndarray (uint32)
+        photon events to be binned
+    t_bin : (double)
+        binning time
+    binshift : int
+        adding a number of zeros at the beginning of the binned data
+    outfile : str
+        path to store output
+    outdtype : dtype
+        numpy dtype of the output file
+    callback : callable or None
+        Callback function to be called throughout the algorithm. If the
+        return value of `callback` is not None, the function will abort.
+        Number of function calls: 100
+    cb_kwargs : dict, optional
+        Keyword arguments for `callback` (e.g. "pid" of process).
+    
+    
+    Returns
+    -------
+    filename : str
+        The filename of the binned data.
+        
+    Bin all photon arrival times in a numpy.uint32 array *data*, using 
         the binning time float *t_bin* and saving the intensity trace as
         the file *filename*. *dlg* is a python object that suports 
         dlg.Update, like a progress dialog.
+    
+    
+    Notes
+    -----
+    The photon stram `data` is created by a program called `Photon.exe`
+    from correlator.com.
     """
     cdef int N = len(data)
     BinData = []
@@ -77,32 +106,34 @@ def BinPhotonEvents(np.ndarray[DTYPEuint32_t] data, double t_bin, filename, dtyp
     cdef int maxphot = 0
     cdef int j, i, emptybins, bin
 
-    dtype=dtype
+    dtype=np.dtype(outdtype)
+
+    if outfile is None:
+        outfile = tempfile.mktemp(suffix=".bin")
 
-    print "Creating file " + filename + " ("+str(dtype.__name__)+")"
+    #print("Creating file {} ({})".format(outfile, outdtype.__name__))
 
-    NewFile = open(filename, 'wb')
+    NewFile = open(outfile, 'wb')
     
     # Add number of empty bins to beginning of file
     if binshift is not None:
-        NewFile.write(dtype(np.zeros(binshift)))
+        NewFile.write(outdtype(np.zeros(binshift)))
         
     TempTrace = list()
 
+    Nperc = int(np.floor(N/100))
+
     for j in range(100):
         percent = str(j)
-        if dlg.Update(j+1, "Counting photon events...")[0] == False:
-            dlg.Destroy()
-            return False
-
-        for i in range(N/100):
-            i = i+N/100*j
+        
+        for i in range(Nperc):
+            i = i+Nperc*j
             time_c += data[i]
 
             if time_c >= t_bin:
                 # Append counted photons and
                 # reset counters
-                #NewFile.write(dtype(phot_c))
+                #NewFile.write(outdtype(phot_c))
                 TempTrace.append(phot_c)
                 time_c -=  t_bin
                 phot_c = 0
@@ -113,17 +144,23 @@ def BinPhotonEvents(np.ndarray[DTYPEuint32_t] data, double t_bin, filename, dtyp
                 # Equivalent to:
                 # time_c = int(time_c)%int(t_bin)
             phot_c +=  1
-        NewFile.write(dtype(TempTrace))
+        NewFile.write(outdtype(TempTrace))
         TempTrace = list()
 
+        if callback is not None:
+            ret = callback(**cb_kwargs)
+            if ret is not None:
+                warnings.warn("Aborted by user.")
+                return outfile
+
 
     # Now write the rest:
-    for i in range(N/100*100,N-1):
+    for i in range(Nperc*100,N-1):
         time_c += data[i]
         if time_c >= t_bin:
             # Append counted photons and
             # reset counters
-            #NewFile.write(dtype(phot_c))
+            #NewFile.write(outdtype(phot_c))
             TempTrace.append(phot_c)
             time_c -=  t_bin
             phot_c = 0
@@ -134,17 +171,28 @@ def BinPhotonEvents(np.ndarray[DTYPEuint32_t] data, double t_bin, filename, dtyp
             # Equivalent to:
             # time_c = int(time_c)%int(t_bin)
         phot_c +=  1
-    NewFile.write(dtype(TempTrace))
+    NewFile.write(outdtype(TempTrace))
     del TempTrace
     NewFile.close()
-
-    return True
+    return outfile
 
 
 def FitExp(times, trace):
-    """Fit an exponential function to the given trace.
-       Base is times.
-       Returns the functions plus paramtetera
+    """ Fit an exponential function to the given trace.
+    
+    
+    Parameters
+    ----------
+    times : ndarray of length N
+        x-values
+    
+    trace : ndarray of length N
+        y-values
+    
+    
+    Returns
+    -------
+        parameters, function
     """
     # Set starting parameters for exponential fit
     expfunc = lambda p, x: p[0]*np.exp(-x/p[1])
@@ -171,7 +219,7 @@ def FitGaussian(amplitudes, frequencies,  argmax):
     parms = np.zeros(3, dtype=np.float32)
     parms[0] = frequencies[argmax]
     parms[1] = amplitudes[argmax]
-    parms[2] = abs(frequencies[1]-frequencies[2])*2.
+    parms[2] = abs(frequencies[1]-frequencies[2])*2
     # Fit function is a gaussian
     gauss = lambda p, x: np.exp(-((x-p[0])/p[2])**2 / 2) * p[1]/(p[2]*np.sqrt(2*np.pi))
     # Function to minimize via least squares
@@ -184,18 +232,34 @@ def FitGaussian(amplitudes, frequencies,  argmax):
 
 @cython.cdivision(True)
 @cython.boundscheck(False) # turn of bounds-checking for entire function
-def OpenDat(filename, dlg):
-    # Open a data file
-    """
+def OpenDat(filename, callback=None, cb_kwargs={}):
+    """ Load "Flex02-12D" correlator.com files
+    
     We open a .dat file as produced by the "Flex02-12D" correlator in photon
     history recorder mode.
     The file contains the time differences between single photon events.
 
-    Returns:
-    This function makes the filename publicly available, bins a couple
-    of events to get 1e+6 points and plots them into the plotting area
-    (plotarea), using the Bin_Photon_Events() function.
+    Parameters
+    ----------
+    filename : str
+        Path to file
+    callback : callable or None
+        Callback function to be called throughout the algorithm. If the
+        return value of `callback` is not None, the function will abort.
+        Number of function calls: 3
+    cb_kwargs : dict, optional
+        Keyword arguments for `callback` (e.g. "pid" of process).
+    
+    Returns
+    -------
+    system_clock, datData
+        The system clock in MHz and the photon time event stream.
+        Returns (None, None) if the progress was aborted through the
+        callback function.
+
 
+    Notes
+    -----
     Raw data file format (taken from manual):
      1. The file records the difference in system clock ticks (1/60 us)
         between photon event.
@@ -218,18 +282,25 @@ def OpenDat(filename, dlg):
     File = open(filename, 'rb')
     # 1st byte: get file format
     # should be 16 - for 16 bit
-    format = int(np.fromfile(File, dtype="uint8", count=1))
-    if format == 8:
-        # No 8 bit format supported
-        print 'Error 8 bit format not supported.'
-        return None
+    fformat = int(np.fromfile(File, dtype="uint8", count=1))
     # 2nd byte: read system clock
     system_clock = int(np.fromfile(File, dtype="uint8", count=1))
-
-    # There is an utility to convert data to 32bit. This makes life easier:
-    if format == 32:
+    if fformat == 8:
+        # No 8 bit format supported
+        warnings.warn('8 bit format not supported.')
+        File.close()
+        return system_clock, None
+    elif fformat == 32:
+        # (There is an utility to convert data to 32bit)
         datData = np.fromfile(File, dtype="uint32", count=-1)
+        File.close()
         return  system_clock, datData
+    elif fformat == 16:
+        pass
+    else:
+        warnings.warn("Unknown format: {} bit".format(fformat))
+        File.close()
+        return system_clock, None
     # In case of 16 bit file format (assumed), read the rest of the file in
     # 16 bit format.
     # Load bunch of Data
@@ -239,24 +310,27 @@ def OpenDat(filename, dlg):
     # Now we need to check if there are any 0xFFFF values which would
     # mean, that we do not yet have the true data in our array.
     # There is 32 bit data after a 0xFFFF = 65535
-    if dlg.Pulse("Searching for 32bit events.") == False:
-        # Stop and end import of data
-        dlg.Destroy()
-        return
+    if callback is not None:
+        ret = callback(**cb_kwargs)
+        if ret is not None:
+            return None, None
+
     occurences = np.where(Data == 65535)[0]
     N = len(occurences)
-    if dlg.Pulse("Found "+str(N)+" 32bit events.") == False:
-        # Stop and end import of data
-        dlg.Destroy()
-        return
+    
+    if callback is not None:
+        ret = callback(**cb_kwargs)
+        if ret is not None:
+            return None, None
+            
     # Make a 32 bit array
     datData = np.uint32(Data)
     datData[occurences] = np.uint32(Data[occurences+1]) + np.uint32(Data[occurences+2])*65536
 
-    if dlg.Pulse("Added new 32 bit array. Finishing...") == False:
-        # Stop and end import of data
-        dlg.Destroy()
-        return
+    if callback is not None:
+        ret = callback(**cb_kwargs)
+        if ret is not None:
+            return None, None
 
     # Now delete the zeros
     zeroids = np.zeros(N*2)
@@ -270,25 +344,26 @@ def OpenDat(filename, dlg):
 
 
 def ReduceTrace(trace, deltat, length):
-    """
-        Given a `trace` of length `len(trace)`, compute a trace of
-        length smaller than `length` by averaging. 
-        
-        
-        Parameters
-        ----------
-        trace : ndarray, shape (N)
-            Input trace that is to be averaged.
-        deltat : float
-            Time difference between bins in trace.
-        length : int
-            Maximum length of the new trace.
-
-
-        Returns
-        -------
-        newtrace : ndarray, shape (N,2)
-            New trace (axis 1) with timepoints (axis 0).
+    """ Shorten an array by averaging.
+    
+    Given a `trace` of length `len(trace)`, compute a trace of
+    length smaller than `length` by averaging. 
+    
+    
+    Parameters
+    ----------
+    trace : ndarray, shape (N)
+        Input trace that is to be averaged.
+    deltat : float
+        Time difference between bins in trace.
+    length : int
+        Maximum length of the new trace.
+
+
+    Returns
+    -------
+    newtrace : ndarray, shape (N,2)
+        New trace (axis 1) with timepoints (axis 0).
 
     """
     step = 0
diff --git a/pyscanfcs/__init__.py b/pyscanfcs/__init__.py
index 0719dbe..588c4da 100644
--- a/pyscanfcs/__init__.py
+++ b/pyscanfcs/__init__.py
@@ -25,9 +25,19 @@
 """
 
 import multipletau
+import sys
+import warnings
 
 from . import doc
-from . import SFCSnumeric
+from .SFCSnumeric import *
+
+try:
+    from .main import Main
+except ImportError:
+    print(sys.exc_info())
+    warnings.warn("Frontend of `pyscanfcs` will not be available."+\
+                  " Reason: {}.".format(sys.exc_info()[1]))
+
 
 __version__ = doc.__version__
 __author__ = "Paul Mueller"
diff --git a/pyscanfcs/__main__.py b/pyscanfcs/__main__.py
index 8dd4dec..4751789 100644
--- a/pyscanfcs/__main__.py
+++ b/pyscanfcs/__main__.py
@@ -25,10 +25,12 @@
 """
 
 from . import doc
-from . import PyScanFCS
+from . import main
+from . import uilayer
+from . import SFCSnumeric
 
 ## VERSION
 version = doc.__version__
 __version__ = version
 
-PyScanFCS.Main()
+main.Main()
diff --git a/pyscanfcs/doc.py b/pyscanfcs/doc.py
index 3866c37..86131b5 100755
--- a/pyscanfcs/doc.py
+++ b/pyscanfcs/doc.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-"""
+u"""
     PyScanFCS
 
     Module doc
@@ -21,35 +21,43 @@
 """
 import csv
 import matplotlib
+import multipletau
 import numpy
 import os
 import platform
+import pyfits
 import scipy
 import sys
-import wx
+
+try:
+    import wx
+except:
+    pass
 
 # The icon file was created with
 # img2py -i -n Main PyScanFCS_icon.png icon.py
-import icon
-import multipletau
-
-
-def GetLocationOfChangeLog(filename = "ChangeLog.txt"):
-    locations = list()
-    fname1 = os.path.realpath(__file__)
-    # Try one directory up
-    dir1 = os.path.dirname(fname1)+"/../"
-    locations.append(os.path.realpath(dir1))
-    # In case of distribution with .egg files (pip, easy_install)
-    dir2 = os.path.dirname(fname1)+"/../pyscanfcs_doc/"
-    locations.append(os.path.realpath(dir2))
+try:
+    from . import icon
+except:
+    pass
+    
+from . import uilayer
+
+
+def GetLocationOfFile(filename):
+    dirname = os.path.dirname(os.path.abspath(__file__))
+    locations = [
+                    dirname+"/../",
+                    dirname+"/../pyscanfcs_doc/",
+                    dirname+"/../doc/",
+                ]
     ## freezed binaries:
     if hasattr(sys, 'frozen'):
         try:
-            dir2 = sys._MEIPASS + "/doc/"
+            adir = sys._MEIPASS + "/doc/"
         except:
-            dir2 = "./"
-        locations.append(os.path.realpath(dir2))
+            adir = "./"
+        locations.append(os.path.realpath(adir))
     for loc in locations:
         thechl = os.path.join(loc,filename)
         if os.path.exists(thechl):
@@ -59,31 +67,14 @@ def GetLocationOfChangeLog(filename = "ChangeLog.txt"):
     return None
 
 
+def GetLocationOfChangeLog(filename = "ChangeLog.txt"):
+    return GetLocationOfFile(filename)
+
+
 def GetLocationOfDocumentation(filename = "PyScanFCS_doc.pdf"):
     """ Returns the location of the documentation if there is any."""
-    ## running from source
-    locations = list()
-    fname1 = os.path.realpath(__file__)
-    # Documentation is usually one directory up
-    dir1 = os.path.dirname(fname1)+"/../"
-    locations.append(os.path.realpath(dir1))
-    # In case of distribution with .egg files (pip, easy_install)
-    dir2 = os.path.dirname(fname1)+"/../pyscanfcs_doc/"
-    locations.append(os.path.realpath(dir2))
-    ## freezed binaries:
-    if hasattr(sys, 'frozen'):
-        try:
-            dir2 = sys._MEIPASS + "/doc/"
-        except:
-            dir2 = "./"
-        locations.append(os.path.realpath(dir2))
-    for loc in locations:
-        thedoc = os.path.join(loc,filename)
-        if os.path.exists(thedoc):
-            return thedoc
-            break
-    # if this does not work:
-    return None
+    return GetLocationOfFile(filename)
+
 
 
 def description():
@@ -100,7 +91,7 @@ def info(version):
 
     Data processing for perpendicular line scanning FCS.
     """
-    textlin = """
+    textlin = u"""
     © 2011-2012 Paul Müller, Biotec - TU Dresden
 
     Data processing for perpendicular line scanning FCS.
@@ -152,7 +143,9 @@ def SoftwareUsed():
            "\n - matplotlib "+matplotlib.__version__+\
            "\n - multipletau "+multipletau.__version__+\
            "\n - NumPy "+numpy.__version__+\
+           "\n - PyFITS "+pyfits.__version__+\
            "\n - SciPy "+scipy.__version__+\
+           "\n - uilayer "+uilayer.__version__+\
            "\n - wxPython "+wx.__version__
     if hasattr(sys, 'frozen'):
         pyinst = "\n\nThis executable has been created using PyInstaller."
diff --git a/pyscanfcs/PyScanFCS.py b/pyscanfcs/main.py
similarity index 94%
copy from pyscanfcs/PyScanFCS.py
copy to pyscanfcs/main.py
index 9d5f8fb..78c4f80 100755
--- a/pyscanfcs/PyScanFCS.py
+++ b/pyscanfcs/main.py
@@ -1,6 +1,6 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
-""" 
+u""" 
     PyScanFCS
 
     Data processing for perpendicular line scanning FCS.
@@ -20,24 +20,26 @@
     You should have received a copy of the GNU General Public License 
     along with this program. If not, see <http://www.gnu.org/licenses/>.
 """
+from __future__ import print_function
+# TODO (Python3): 
+# from __future__ import division
+# -> There is an integer division somewhere
 
-# Generic modules
-import tempfile
-import zipfile
 import csv
 import sys
-import webbrowser
 
 ## On Windows XP I had problems with the unicode Characters.
 # I found this at 
 # http://stackoverflow.com/questions/5419/python-unicode-and-the-windows-console
 # and it helped (needs to be done before import of matplotlib):
 import platform
-reload(sys)
-sys.setdefaultencoding('utf-8')
+
+if sys.version_info[0] == 2:
+    reload(sys)
+    sys.setdefaultencoding('utf-8')
 
 import os
-import wx                               # GUI interface wxPython
+
 #import wx.lib.agw.pyprogress as PBusy   # Busy Dialog
 
 import matplotlib
@@ -48,33 +50,51 @@ from matplotlib.figure import Figure
 from matplotlib.backends.backend_wxagg import \
     FigureCanvasWxAgg as FigureCanvas, \
     NavigationToolbar2WxAgg as NavigationToolbar
-
 from matplotlib.widgets import RectangleSelector, Button
 from matplotlib.patches import Rectangle
-
 import matplotlib.pyplot as plt
 
-from wx.lib.agw import floatspin        # Float numbers in spin fields
-
-#import wxmplot                          # wxmplot-0.9.7.zip (PyPI)
+import multipletau
 
 import numpy as np                            # NumPy
 import pyfits
 from scipy.fftpack import fft
 from scipy.fftpack import fftfreq
-#import struct
-
-import edclasses
-import misc
 # SFCSnumeric needs scipy.optimize
 # We import it here, so that pyinstaller packs it into the executable.
 # Pyinstaller does not neccessarily know that SFCSnumeric needs it.
 from scipy import optimize
-import SFCSnumeric
-import multipletau
+import tempfile
+import traceback
+import webbrowser
+import wx                               # GUI interface wxPython
+from wx.lib.agw import floatspin        # Float numbers in spin fields
+from wx.lib.scrolledpanel import ScrolledPanel
+
+import zipfile
+
 
-import doc      # Documentation/some texts
+# module import
+from . import edclasses
+from . import misc
+from . import doc      # Documentation/some texts
+from . import SFCSnumeric
+from . import uilayer
 
+
+
+
+########################################################################
+class ExceptionDialog(wx.MessageDialog):
+    """"""
+    def __init__(self, msg):
+        """Constructor"""
+        wx.MessageDialog.__init__(self, None, msg, "Error",
+                                          wx.OK|wx.ICON_ERROR)   
+                                          
+                                          
+                                          
+########################################################################                                          
 class plotarea(wx.Panel):
     def __init__(self, parent, grandparent):
         wx.Panel.__init__(self, parent, -1, size=(500,500))
@@ -127,8 +147,7 @@ class plotarea(wx.Panel):
         
 
 
-
-
+########################################################################
 class FFTmaxDialog(wx.Dialog):
     def __init__(
             self, parent, frequency, amplitude, size=wx.DefaultSize, pos=wx.DefaultPosition, 
@@ -250,7 +269,7 @@ maximum. \n The data achieved will automatically be updated within the main prog
                     timeweights.append(weighta/self.freq[idx+i+1])
                     timeweights.append(weightb/self.freq[idx-i-1])
                     Pie = Pie + weighta + weightb
-                    print sum(np.array(timeweights))/Pie, weighta, weightb
+                    print(sum(np.array(timeweights))/Pie, weighta, weightb)
 
                 timeweights = np.array(timeweights)
                 #print timeweights
@@ -288,8 +307,13 @@ maximum. \n The data achieved will automatically be updated within the main prog
                 self.pnt.OnBinning_Prebin()   
 
 
+
+########################################################################
 class MyFrame(wx.Frame):
     def __init__(self, parent, id, version):
+        # GUI exceptions
+        sys.excepthook = MyExceptionHook
+        
         self.version = version
         wx.Frame.__init__(self, parent, id, "PyScanFCS " + self.version)
         self.CreateStatusBar() # A Statusbar in the bottom of the window
@@ -318,19 +342,21 @@ class MyFrame(wx.Frame):
         # thing accordingly and plot again.
 
         self.sp = wx.SplitterWindow(self, style=wx.SP_3DSASH)
-        self.buttonarea = wx.Panel(self.sp)
+        self.buttonarea = ScrolledPanel(self.sp)
+        self.buttonarea.SetupScrolling(scroll_y=True)
         self.plotarea = plotarea(self.sp, self)
         self.pdata = np.linspace(0,1,100)
         self.pdata.shape = (10,10)
         #self.plotarea = wxmplot.ImagePanel(self.sp)
         #self.plotarea.display(self.pdata)
 
-        self.sp.SplitVertically(self.buttonarea, self.plotarea, 450)
-
         self.MakeButtons()
 
         self.Layout()
 
+        split = max(400, self.firhorz.GetMinSize()[0]+5)
+        self.sp.SplitVertically(self.buttonarea, self.plotarea, split)
+
         self.Show()
 
         # Initial data values:
@@ -355,6 +381,10 @@ class MyFrame(wx.Frame):
         # List of absolute filenames that contain bleaching info
         self.file_bleach_profile = list()
         
+        # Temporary filenames for binned intensity
+        self.tempbintot = tempfile.mktemp("_binned_total.int")
+        self.tempbinpar = tempfile.mktemp("_binned_partial.int")
+
         # We try to work with a cache to save time.
         self.cache = dict()
         # Each element of the cache is a filename connected to some data
@@ -392,23 +422,29 @@ class MyFrame(wx.Frame):
         """ Bin all photon events according to a binsize t_bin.
         """
         eb = self.BoxPrebin[10].GetValue()  # 10 spin: bin shift
-        # Now show an informing dialog
-        style=wx.PD_REMAINING_TIME|wx.PD_SMOOTH|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT
-        dlg = wx.ProgressDialog("Binning Data", "Counting photon events..."
-        , maximum = 100, parent=self, style=style)
-
         # The box contains bins per line
-        self.bins_per_line = int(self.BoxPrebin[8].GetValue())
+        self.bins_per_line = int(self.BoxPrebin[8].GetValue())        
         # t_bin in clock ticks
         t_bin = self.t_linescan/self.bins_per_line
-        dtype = np.uint16
-        filename = "Binned_total.int"
-        SFCSnumeric.BinPhotonEvents(Data, t_bin, filename, dtype, dlg, binshift=eb)
+        outdtype = np.uint16
+        outfile = self.tempbintot
 
-        binneddata = np.fromfile(filename, dtype=dtype)
+        wxdlg = uilayer.wxdlg(parent=self, steps=100,
+                              title="Binning photon events...")
+        
+        print("Creating file {} ({})".format(outfile, outdtype.__name__))
+
+        SFCSnumeric.BinPhotonEvents(Data, t_bin, binshift=eb,
+                                    outfile=outfile,
+                                    outdtype=outdtype,
+                                    callback=wxdlg.Iterate)
+        wxdlg.Finalize()
+
+        binneddata = np.fromfile(outfile, dtype=outdtype)
+        
         if np.max(binneddata) < 256:
+            #save memory
             binneddata = np.uint8(binneddata)
-
         return binneddata
 
 
@@ -418,24 +454,32 @@ class MyFrame(wx.Frame):
         calculate the photon events that take place every *t_bin* in system 
         clocks, where n_events is the number of events to use.
         """
-        eb = self.BoxPrebin[10].GetValue()  # 10 spin: bin shift
+        # The box contains bins per line
+        self.bins_per_line = int(self.BoxPrebin[8].GetValue())
 
+        # t_bin in clock ticks
         self.t_bin = t_bin
-        # Now show an informing dialog
-        style=wx.PD_REMAINING_TIME|wx.PD_SMOOTH|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT
-        dlg = wx.ProgressDialog("Binning Data", "Counting photon events..."
-        , maximum = 100, parent=self, style=style)
+        outdtype = np.uint16
+        outfile = self.tempbinpar
+        eb = self.BoxPrebin[10].GetValue()  # 10 spin: bin shift
+
         Data = self.datData[:n_events]
+        
+        wxdlg = uilayer.wxdlg(parent=self, steps=100,
+                              title="Binning photon events...")
+        
+        print("Creating file {} ({})".format(outfile, outdtype.__name__))
 
-        # The box contains bins per line
-        self.bins_per_line = int(self.BoxPrebin[8].GetValue())
+        SFCSnumeric.BinPhotonEvents(Data, t_bin, binshift=eb,
+                                    outfile=outfile,
+                                    outdtype=outdtype,
+                                    callback=wxdlg.Iterate)
+        wxdlg.Finalize()
 
-        dtype = np.uint16
-        filename = "Binned_partial.int"
-        retval = SFCSnumeric.BinPhotonEvents(Data, t_bin, filename, dtype, dlg, binshift=eb)
+        binneddata = np.fromfile(outfile, dtype=outdtype)
 
-        binneddata = np.fromfile(filename, dtype=dtype)
         if np.max(binneddata) < 256:
+            # save memory
             binneddata = np.uint8(binneddata)
 
         return binneddata
@@ -930,6 +974,7 @@ class MyFrame(wx.Frame):
         self.firhorz.Add(self.secvert)
         self.buttonarea.SetSizer(self.firhorz)
 
+        
 
     def MakeMenu(self):
         ## Setting up the menus.
@@ -944,11 +989,13 @@ class MyFrame(wx.Frame):
  "Opens a correlator file (.dat) that contains photon arrival time differences")
         menuOpenFits = filemenu.Append(wx.ID_ANY, "Open .&fits file", 
                               "Opens a previously binned intensity file (.fits)")
-        self.menuSaveDat = filemenu.Append(wx.ID_ANY, "&Save 32 bit .dat file", 
+        self.menuSaveDat = filemenu.Append(wx.ID_ANY, "Save 32 bit .&dat file", 
               "Saves photon arrival time difference data in 32 bit file format")
         self.menuSaveFits = filemenu.Append(wx.ID_SAVE, "&Save .fits file", 
                                  "Saves binned intensity data into a .fits file")
         filemenu.AppendSeparator()
+        menuTest = filemenu.Append(wx.ID_ANY,"Create &artificial .dat file", "Create an artificial data set")
+        filemenu.AppendSeparator()
         menuExit = filemenu.Append(wx.ID_EXIT,"E&xit", "Terminate the program")
 
         # prefmenu
@@ -987,6 +1034,7 @@ class MyFrame(wx.Frame):
         self.Bind(wx.EVT_MENU, self.OnOpenFits, menuOpenFits)
         self.Bind(wx.EVT_MENU, self.OnSaveDat, self.menuSaveDat)
         self.Bind(wx.EVT_MENU, self.OnSaveFits, self.menuSaveFits)
+        self.Bind(wx.EVT_MENU, self.OnMenuTest, menuTest)
 
         # Help
         self.Bind(wx.EVT_MENU, self.OnMenuAbout, menuAbout)
@@ -1141,11 +1189,11 @@ class MyFrame(wx.Frame):
         info.SetName('PyScanFCS')
         info.SetVersion(self.version)
         info.SetDescription(description)
-        info.SetCopyright('(C) 2012 Paul Müller')
+        info.SetCopyright(u'(C) 2012 Paul Müller')
         info.SetWebSite('http://pyscanfcs.craban.de')
         info.SetLicence(licence)
-        info.AddDeveloper('Paul Müller')
-        info.AddDocWriter('Paul Müller')
+        info.AddDeveloper(u'Paul Müller')
+        info.AddDocWriter(u'Paul Müller')
         wx.AboutBox(info)
 
 
@@ -1179,6 +1227,10 @@ class MyFrame(wx.Frame):
         wx.MessageBox(text, 'Software', wx.OK | wx.ICON_INFORMATION)
 
 
+    def OnMenuTest(self, e=None):
+        misc.ArtificialDataDlg(self)
+        
+
     def OnMenuUpdate(self, event):
         misc.Update(self)
 
@@ -1309,11 +1361,13 @@ class MyFrame(wx.Frame):
                 except KeyError:
                     # Open B.dat and add to cache
                     filenames = os.path.join(self.dirname, filename)
-                    style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME|wx.PD_CAN_ABORT
-                    dlg2 = wx.ProgressDialog("Processing 2nd file", 
-                           "Finding 32 bit events...", parent=self, style=style)
-                    system_clock, datData2 = SFCSnumeric.OpenDat(filenames, dlg2)
-                    dlg2.Destroy()
+
+                    wxdlg = uilayer.wxdlg(parent=self, steps=3,
+                                          title="Importing dat file...")
+                    self.system_clock, self.datData = SFCSnumeric.OpenDat(
+                                         filename, callback=wxdlg.Iterate)
+                    wxdlg.Finalize()
+
                     # Bin to obtain intData2
                     intData2 = self.Bin_All_Photon_Events(datData2)
                     # Add to cache
@@ -1323,7 +1377,7 @@ class MyFrame(wx.Frame):
                     
             else:
                 # We should not be here.
-                print "No A.dat or A.fits file opened. Aborting."
+                print("No A.dat or A.fits file opened. Aborting.")
                 return
 
         # Start plotting?
@@ -1487,10 +1541,13 @@ class MyFrame(wx.Frame):
             except:
                 pass
             os.chdir(olddir)
-        
+
+            Arc.close()        
         os.chdir(returnWD)
-        os.removedirs(tempdir)
-        Arc.close()
+        try:
+            os.removedirs(tempdir)
+        except:
+            pass
 
         if self.MenuVerbose.IsChecked():
             plt.figure(0)
@@ -1613,11 +1670,12 @@ class MyFrame(wx.Frame):
             #self.filename = dlg.GetFilename()
             #self.dirname = dlg.GetDirectory()
             filename = os.path.join(self.dirname, self.filename)
-            style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME|wx.PD_CAN_ABORT
-            dlg2 = wx.ProgressDialog("Processing file", "Finding 32 bit events..."
-            , parent=self, style=style)
-            self.system_clock, self.datData = SFCSnumeric.OpenDat(filename, dlg2)
-            dlg2.Destroy()
+            
+            wxdlg = uilayer.wxdlg(parent=self, steps=3,
+                                  title="Importing dat file...")
+            self.system_clock, self.datData = SFCSnumeric.OpenDat(
+                                       filename, callback=wxdlg.Iterate)
+            wxdlg.Finalize()
             self.GetTotalTime()
             self.Update()
 
@@ -1755,11 +1813,13 @@ class MyFrame(wx.Frame):
         self.filename = cachename
         self.dirname = cache["dirname"]
         filename = os.path.join(self.dirname, self.filename)
-        style = wx.PD_APP_MODAL|wx.PD_ELAPSED_TIME|wx.PD_CAN_ABORT
-        dlg2 = wx.ProgressDialog("Processing file", "Finding 32 bit events..."
-        , parent=self, style=style)
-        self.system_clock, self.datData = SFCSnumeric.OpenDat(filename, dlg2)
-        dlg2.Destroy()
+        
+        wxdlg = uilayer.wxdlg(parent=self, steps=3,
+                              title="Importing dat file...")
+        self.system_clock, self.datData = SFCSnumeric.OpenDat(
+                                   filename, callback=wxdlg.Iterate)
+        wxdlg.Finalize()
+        
         self.GetTotalTime()
         self.Update()
         self.PlotImage()
@@ -2106,11 +2166,33 @@ class MyFrame(wx.Frame):
             self.OnLinetimeSelected()
 
 
+
+def MyExceptionHook(etype, value, trace):
+    """
+    Handler for all unhandled exceptions.
+ 
+    :param `etype`: the exception type (`SyntaxError`, `ZeroDivisionError`, etc...);
+    :type `etype`: `Exception`
+    :param string `value`: the exception error message;
+    :param string `trace`: the traceback header, if any (otherwise, it prints the
+     standard Python header: ``Traceback (most recent call last)``.
+    """
+    frame = wx.GetApp().GetTopWindow()
+    tmp = traceback.format_exception(etype, value, trace)
+    exception = "".join(tmp)
+ 
+    dlg = ExceptionDialog(exception)
+    dlg.ShowModal()
+    dlg.Destroy()     
+    wx.EndBusyCursor()
+    
+    
+
 ## VERSION
 version = doc.__version__
 __version__ = version
 
-print doc.info(version)
+print(doc.info(version))
 
 ## Start gui
 def Main():
diff --git a/pyscanfcs/misc.py b/pyscanfcs/misc.py
index 6e874d2..2c26ed3 100644
--- a/pyscanfcs/misc.py
+++ b/pyscanfcs/misc.py
@@ -19,6 +19,7 @@
     You should have received a copy of the GNU General Public License 
     along with this program. If not, see <http://www.gnu.org/licenses/>.
 """
+from __future__ import print_function, division
 
 import codecs
 from distutils.version import LooseVersion # For version checking
@@ -33,10 +34,12 @@ import wx                               # GUI interface wxPython
 import wx.html
 import wx.lib.delayedresult as delayedresult
 
-import doc                          # Documentation/some texts
+
+from . import doc                          # Documentation/some texts
 # The icon file was created with
 # img2py -i -n Main PyScanFCS_icon.png icon.py
-import icon                         # Contains the program icon
+from . import icon                         # Contains the program icon
+from . import edclasses
 
 
 class UpdateDlg(wx.Frame):
@@ -87,6 +90,194 @@ class wxHTML(wx.html.HtmlWindow):
          webbrowser.open(link.GetHref())
 
 
+class ArtificialDataDlg(wx.Frame):
+    # This tool is derived from a wx.frame.
+    def __init__(self, parent):
+        self.parent = parent
+        # Get the window positioning correctly
+        pos = self.parent.GetPosition()
+        pos = (pos[0]+100, pos[1]+100)
+        wx.Frame.__init__(self, parent=self.parent,
+                          title="Create artificial test data", pos=pos, 
+                  style=wx.DEFAULT_FRAME_STYLE|wx.FRAME_FLOAT_ON_PARENT)
+        
+        ## Content
+        self.panel = wx.Panel(self)
+        
+        topSizer = wx.BoxSizer(wx.VERTICAL)
+        
+
+        topSizer.Add(wx.StaticText(self.panel,
+                          label="Create artificial test data\n"+
+                          "with exponentially correlated noise.\n"))
+        
+        colsizer = wx.FlexGridSizer(4, 2)
+        
+        # decay time
+        colsizer.Add( wx.StaticText(self.panel,
+                                    label=u"Correlation time [ms]: "))
+        self.WXDecay = edclasses.FloatSpin(self.panel,
+                                          value="100")
+        colsizer.Add(self.WXDecay)
+
+        # line scanning time
+        colsizer.Add( wx.StaticText(self.panel,
+                                    label=u"Scan cycle time [ms]: "))
+        self.WXLine = edclasses.FloatSpin(self.panel,
+                                          value="0.714")
+        colsizer.Add(self.WXLine)
+
+        # number of samples
+        colsizer.Add( wx.StaticText(self.panel,
+                                    label=u"Number of samples: "))
+        self.WXNumber = wx.SpinCtrl(self.panel, -1, min=10000,
+                                    max=500000000, value="500000")
+        colsizer.Add(self.WXNumber)
+
+        # data format
+        colsizer.Add(wx.StaticText(self.panel, label="Data format: "))
+        self.WXDropInt = wx.ComboBox(self.panel, -1, "uint16", (15,30),
+                                   wx.DefaultSize, ["uint16", "uint32"],
+                                   wx.CB_DROPDOWN|wx.CB_READONLY)
+        colsizer.Add(self.WXDropInt)
+
+        topSizer.Add(colsizer)
+
+        btndo = wx.Button(self.panel, wx.ID_CLOSE, 'Create .dat file')
+        # Binds the button to the function - close the tool
+        
+        self.Bind(wx.EVT_BUTTON, self.OnCreateFile, btndo)
+        
+        topSizer.Add(btndo)
+        self.panel.SetSizer(topSizer)
+        topSizer.Layout()
+        topSizer.Fit(self)
+        #self.SetMinSize(colsizer.GetMinSizeTuple())
+        #Icon
+        if parent.MainIcon is not None:
+            wx.Frame.SetIcon(self, parent.MainIcon)
+        self.Show(True)
+
+
+    def OnClose(self, event=None):
+        # This is a necessary function for PyCorrFit.
+        # Do not change it.
+        self.parent.toolmenu.Check(self.MyID, False)
+        self.parent.ToolsOpen.__delitem__(self.MyID)
+        self.Destroy()
+
+    def OnCreateFile(self, e=None):
+        linetime = self.WXLine.GetValue()
+        taudiff = self.WXDecay.GetValue()
+        N = self.WXNumber.GetValue()
+        inttype = self.WXDropInt.GetValue()
+        
+        if inttype == "uint16":
+            dtype = np.uint16
+        else:
+            dtype = np.uint32
+
+        # file dialog
+        filename = "test_tau{}ms_line{}ms_N{}_{}.dat".format(
+                        taudiff, linetime, N, inttype)
+
+        dlg = wx.FileDialog(self, "Save as .dat file", "./", filename, 
+              "DAT files (*.dat)|*.dat;*.daT;*.dAt;*.dAT;*.Dat;*.DaT;*.DAt;*.DAT",
+           wx.SAVE|wx.FD_OVERWRITE_PROMPT)
+        # user cannot do anything until he clicks "OK"
+        if dlg.ShowModal() == wx.ID_OK:
+            # Workaround for Ubuntu 12.10 since 0.2.0
+            path = dlg.GetPath()
+        else:
+            return
+
+        wx.BeginBusyCursor()
+
+        # start new thread
+        args = N, taudiff, linetime, dtype, path
+        delayedresult.startWorker(_CreateConsumer, _CreateWorker,
+                                  wargs=(args,),)
+        
+
+
+
+
+def GenerateExpNoise(N, taud=20., variance=1., deltat=1.):
+    """
+        Generate exponentially correlated noise.
+    """
+    # length of mean0 trace
+    N_steps = N
+    dt = deltat
+    # time trace
+    t = np.arange(N_steps)
+    # AR-1 processes - what does that mean?
+    # time constant (inverse of correlationtime taud)
+    g = 1./taud
+    # variance
+    s0 = variance
+    
+    # normalization factor (memory of the trace)
+    exp_g = np.exp(-g*dt)
+    one_exp_g = 1-exp_g
+    z_norm_factor = np.sqrt(1-np.exp(-2*g*dt))/one_exp_g
+    
+    # create random number array
+    # generates random numbers in interval [0,1)
+    randarray = np.random.random(N_steps)
+    # make numbers random in interval [-1,1)
+    randarray = 2*(randarray-0.5)
+    
+    # simulate exponential random behavior
+    z = np.zeros(N_steps)
+    z[0] = one_exp_g*randarray[0]
+    for i in np.arange(N_steps-1)+1:
+        z[i] = exp_g*z[i-1] + one_exp_g*randarray[i]
+        
+    z = z * z_norm_factor*s0
+    return z
+
+
+
+def MakeDat(linetime, noisearray, dtype, filename):
+    """ Create a .dat file (like Photon.exe).
+        System clock is fixed to 60MHz.
+        linetime [s]
+        noisearray integer array (uint16 or uint32)
+    """
+    NewFile = open(filename, 'wb')
+    if dtype == np.uint32:
+        newformat = np.uint8(32)
+    elif dtype == np.uint16:
+        newformat = np.uint8(16)
+    else:
+        raise ValueError
+    newclock = np.uint8(60)
+    NewFile.write(newformat)
+    NewFile.write(newclock)
+    noisearray = dtype(noisearray)
+    # Create matrix. Each line is a scan.
+    data = list()
+    timeticks = linetime*newclock*1e6 # 60MHz
+    half1 = np.ceil(timeticks/2)
+    half2 = np.floor(timeticks/2)
+    for i in np.arange(len(noisearray)):
+        # Create a line
+        N = noisearray[i]
+        if N == 0:
+            line=np.zeros(1, dtype=dtype)
+            # Only one event at the far corner
+            line[0] = timeticks
+            line.tofile(NewFile)
+        else:
+            line = np.ones(N+1, dtype=dtype)
+            # events are included between two far events
+            line[0] = half1-len(line)
+            line[-1] = half2
+            line.tofile(NewFile)
+    NewFile.close()
+
+
 def removewrongUTF8(name):
     newname = u""
     for char in name:
@@ -129,12 +320,35 @@ def findprogram(program):
     return (0, None)
 
 
+def _CreateConsumer(e=None):
+    wx.EndBusyCursor()
+    
+
+def _CreateWorker(args):
+    N, taudiff, linetime, dtype, path = args
+
+    # deltat is linetime
+    noisearray = GenerateExpNoise(N, taud=taudiff, deltat=linetime)
+    noisearray -= np.min(noisearray)
+    noisearray *= 30./np.max(noisearray)
+    #noisearray += 5
+    noisearray = np.uint32(noisearray)
+
+    # Create 32bit and 16bit binary .dat files
+    # translate linetime in bins of taud
+    ltbin = linetime / 1000
+    data = MakeDat(ltbin, noisearray, dtype, path)
+
+
+
+
 def Update(parent):
     """ This is a thread for _Update """
     parent.StatusBar.SetStatusText("Connecting to server...")
     delayedresult.startWorker(_UpdateConsumer, _UpdateWorker,
                               wargs=(parent,), cargs=(parent,))
 
+
 def _UpdateConsumer(delayedresult, parent):
     results = delayedresult.get()
     dlg = UpdateDlg(parent, results)
diff --git a/pyscanfcs/uilayer.py b/pyscanfcs/uilayer.py
new file mode 100644
index 0000000..017e960
--- /dev/null
+++ b/pyscanfcs/uilayer.py
@@ -0,0 +1,560 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+    uilayer
+
+    python user interface layer to monitor progress of long-running
+    algorithms
+"""
+
+from __future__ import division
+
+import os
+import sys
+import warnings
+
+__all__=["dummy", "ui", "stdout"]
+
+try:
+    import wx
+except:
+    pass
+else:
+    __all__ += ["wxdlg"]
+
+
+if sys.version < '3':
+    integer_types = (int, long,)
+else:
+    integer_types = (int,)
+
+
+class base_ui():
+    """
+        This is the main class from which all interfaces are derived.
+        It is quiet, meaning it does not output any progress data, but
+        it will display warings and errors in the console.
+    """
+    def __init__(self, steps=None, pids=None, progress=None,
+                 subpids=None, show_warnings=True, totalsteps=None,
+                 dirname=None, **kwargs):
+        """
+            Creates an instance and sets initial parameters for progress
+            dialogs (optional).
+            
+            
+            Parameters:
+            -----------
+            pids, steps, progress, subpids : optional
+                See documentation of self.SetProgress
+            show_warnings : bool
+                Display warnings of/in the interface.
+            totalsteps : int or None
+                Known number of total steps of all progresses. This
+                number can be larger than the sum of all steps,
+                inferring knowledge on the progresses to come.
+
+
+            See Also
+            --------
+            SetProgress : Sets initial parameters manually
+        """
+        if dirname is None:
+            self._dirname = os.path.expanduser("~")
+        self._abortlist = list()
+        self._totalsteps = totalsteps
+        self._currentstep = 0
+        self._single_progress = False
+        self.ShowWarnings(show_warnings)
+        self.SetProgress(steps=steps,
+                         pids=pids,
+                         progress=progress,
+                         subpids=subpids)
+
+    
+    def GetDir(self):
+        """ Returns the current working directory.
+        """
+        return self._dirname
+
+
+    def Iterate(self, pid=None, subpid=0, **kwargs):
+        """ Iterate progress.
+
+        Increments the "current step" of a progress by one.
+        Warns the user if the step is above "total steps".
+        
+        Also looks for the pid in self._abortlist and returns it to
+        the process to stop it.
+        """
+        if self._totalsteps is not None:
+            self._currentstep += 1
+        
+        if pid is None:
+            if self._single_progress == False:
+                self.warn("I do not know which progress to iterate."+
+                          " Please specify the kwarg pid.")
+            pid=0
+
+        pid = int(pid)
+        subpid = int(subpid)
+
+        for i in range(len(self._pids)):
+            if self._pids[i] == pid and self._subpids[i] == subpid:
+                self._progress[i] += 1
+
+        self.Update()
+        
+        if pid in self._abortlist:
+            # Try to stop the process if it supports that.
+            # Returning anything else but None will stop the process.
+            return pid
+
+
+    def Finalize(self, pid=None, subpid=0, **kwargs):
+        """ Triggers output that a process is finished
+        """
+        pass
+
+
+    def SelectPath(self, **kwargs):
+        """ Select a file or folder from the file system.
+        
+        This does not do anything here.
+        """
+        pass
+
+
+    def GetDir(self, dirname):
+        """ Sets the current working directory.
+        """
+        self._dirname = dirname
+        
+
+    def SetProgress(self, steps=None, pids=None, progress=None,
+                          subpids=None, **kwargs):
+        """
+            Set the initial parameters of the processes that are to be
+            monitored by this class.
+            
+            
+            Parameters
+            ----------
+            pids : Array-like dtype(int) or int, length N
+                Process identifiers
+            steps : Array-like dtype(int) or int, length N
+                Maximum number of steps for each process
+            progress : Array-like dtype(int) or int, length N
+                Current step in the progress counting up until `steps`
+            subpids : Array-like dtype(int) or int, length N
+                Sub-process identifiers - useful for multithreading
+
+            The following kwargs combinations are possible:
+                1. pids, steps, progress, subpids all `None`
+                    Nothing will happen
+                2. pids, steps, progress, subpids all some int
+                    Only one process of unknown length
+                3. pids, steps, progress, subpids all integer `list`s
+                    Multiple processes are assumed
+                4. pids, progress, subpids all `None` and steps int
+                    Only one process of known length
+                5. pids, progress, subpids all `None` and steps `list`
+                    Multiple processes of known length - internally
+                    the processes get `pids` that are enumerated from
+                    zero onwards and `progress` is set no zeros.
+            
+            Returns
+            -------
+            success : bool
+                True if data was set and False if nothing was set.
+        """
+        self._single_progress = False
+        self._no_data = False
+        self._known_length = False
+        if (pids is None and steps is None and progress is None):
+            # 1. Nothing will happen
+            self._no_data = True
+            return False
+        elif (pids is not None and steps is not None and
+                                  progress is not None):
+            # 2. Only one process
+            # or
+            # 3. Multiple processes are assumed
+            self._known_length = False
+        elif (pids is None and steps is not None and progress is None):
+            self._known_length = True
+            if isinstance(steps, integer_types+(float, complex)):
+                # 4. Only one process of known length
+                self._single_progress = True
+                pids = 0
+                progress = 0
+            else:
+                # 5. Multiple processes of known length - internally
+                #    the processes get `pids` that are enumerated from
+                #    zero onwards and `progress` is set no zeros.
+                pids = range(len(steps))
+                progress = [0]*len(steps)
+        else:
+            raise NameError("Your set of parameters is invalid.")
+
+        # Convert input to list
+        if isinstance(pids, integer_types+(float, complex)):
+            # Only one progress
+            self._single_progress = True
+            pids = [pids]
+        if isinstance(steps, integer_types+(float, complex)):
+            steps = [steps]
+        if isinstance(progress, integer_types+(float, complex)):
+            progress = [progress]
+        if isinstance(subpids, integer_types+(float, complex)):
+            subpids = [subpids]
+            
+        self._pids = pids
+        # Defines how many steps should be used to split the total
+        # computation. The function self.progress will be used to
+        # follow the steps of the algorithm.
+        self._steps = steps
+        self._progress = progress
+
+        if subpids is None:
+            self._subpids = [0]*len(self._pids)
+        else:
+            self._subpids = subpids
+        
+        return True
+
+
+    def ShowWarnings(self, show_warnings):
+        """
+            show_warnings : bool
+                enable or disable warning
+        """
+        self._show_warnings = show_warnings
+
+
+    def Update(self, **kwargs):
+        """  Read and write from and to the user interface
+        
+        This does not do anything here.
+        """
+        pass
+        
+
+    def warn(self, msg):
+        """ Warns the user when there is a problem. """
+        if self._show_warnings:
+            warnings.warn(msg)
+
+
+class dummy(object):
+    """
+        This is a dummy class that can be used to improve speed.
+        There will be no output.
+    """
+    def __init__(self, *args, **kwargs):
+        pass
+    def Finalize(self, *args, **kwargs):
+        pass
+    def Iterate(self, *args, **kwargs):
+        pass
+    def SelectPath(self, *args, **kwargs):
+        pass
+    def SetDir(self, *args, **kwargs):
+        pass
+    def SetProgress(self, *args, **kwargs):
+        pass
+    def ShowWarnings(self, *args, **kwargs):
+        pass
+    def Update(self, *args, **kwargs):
+        pass
+    def warn(self, *args, **kwargs):
+        pass
+
+
+class stdout(base_ui):
+    """ Writes progress into standard output.
+        
+    """
+    def __init__(self, **kwargs):
+        """ Stuff that needs to be done in the beginning.
+            
+        """
+        base_ui.__init__(self, **kwargs)
+        self._maxlength = get_terminal_width()
+
+
+    def Finalize(self, pid=None, subpid=0, name=None, **kwargs):
+        """ Triggers output when a process is finished.
+            
+        """
+        if pid is None:
+            self.warn("I do not know which progress to finalize."+
+                          " Please specify the kwarg pid.")
+
+        pid = int(pid)
+        subpid = int(subpid)
+
+
+        msg = "Progress finished: {}-{}".format(pid,subpid)
+        if name is not None:
+            msg += " ({})".format(name)
+        dn = max(self._maxlength-len(msg),0)
+
+        sys.stdout.write("\r{}{}\n".format(msg,dn*" "))
+        sys.stdout.flush()
+
+    
+    def Update(self, **kwargs):
+        """ Read and write from and to the user interface.
+        
+        The algorithm wants to tell the user something.
+        We use the last line of the standard output to write the
+        progress of all algorithms.
+        """
+        startline = u"Progress: "
+        msg = startline
+        if self._single_progress:
+            if self._steps[0] == 0:
+                perc = int(self._progress[0])
+                msg += u"{}".format(perc)
+            else:
+                perc = self._progress[0]/self._steps[0]*100.
+                msg += u"{:0.2f}%".format(perc)
+        else:
+            for i in range(len(self._pids)):
+                # compute percentage
+                if self._pids[i] != -1:
+                    if self._steps[i] == 0:
+                        perc = int(self._progress[i])
+                        msg += u"{}-{}@{}|".format(
+                            self._pids[i], self._subpids[i], perc)
+                    else:
+                        perc = self._progress[i]/self._steps[i]*100.
+                        msg += u"{}-{}@{:0.2f}%|".format(
+                            self._pids[i], self._subpids[i], perc)
+        msg = msg.strip(" |")
+
+        
+        dn = max(self._maxlength-len(msg),0)
+
+        newline = "\r{}{}".format(msg,dn*" ")
+        
+        if len(newline) > self._maxlength+1:
+            warnings.warn("Terminal width too small. Output cropped.")
+            newline = newline[:self._maxlength-1]
+        
+        if newline.strip() == startline.strip():
+            newline = self._maxlength*" "+"\r"
+
+        sys.stdout.write(newline)
+        sys.stdout.flush()
+
+
+
+class wxdlg(base_ui):
+    """ Displays propgress in a wx dialog window.
+    
+    Can be used from within a wx.App.
+    """
+    def __init__(self, parent=None, title="Progress", **kwargs):
+        """ Stuff that needs to be done in the beginning.
+            
+        """
+        self.parent = parent
+        self.title = title
+        base_ui.__init__(self, **kwargs)
+
+
+    def Destroy(self):
+        """ Destroys the wxdlg class.
+        """
+        try:
+            self.Finalize()
+        except:
+            pass
+        
+        
+    def Finalize(self, pid=None, subpid=0, name=None, **kwargs):
+        """ Triggers output when a process is finished.
+            
+        """
+        if self._single_progress:
+            self.dlg.Destroy()
+        elif (self._totalsteps is not None and
+              self._totalsteps <= self._currentstep):
+            self.dlg.Destroy()
+        else:
+            self.Update()
+
+
+    def SelectPath(self, dirname=None, title="Open file",
+                   wildcards=["*"], fname="All files", mode="r",
+                   **kwargs):
+        """ Select a file or folder from the file system.
+        
+        Opens a wx.FileDialog for selecting files.
+        
+        Parameters
+        ----------
+        mode : str
+            File mode operations read "r" or write "w" or
+            read multiple files "mr".
+        
+        Returns the files in a list.
+        """
+        if dirname is None:
+            dirname = self._dirname
+        front = " ("
+        rear = ")|"
+        for wc in wildcards:
+            front += "*.{}, ".format(wc)
+            rear += ";*{}".format(wc)
+        front.strip(", ")
+        wcstring = fname+front+rear
+
+        if mode == "r":
+            wxmode = wx.OPEN
+        else:
+            raise NotImplementedError(
+                                 "Mode '{}' not supported".format(mode))
+        dlg = wx.FileDialog(self.parent, title, dirname, "", 
+                            wcstring, wxmode)
+        if dlg.ShowModal() == wx.ID_OK:
+            path = dlg.GetPath()
+            self._dirname = os.path.split(path)[0]
+            dlg.Destroy()
+            return path
+        else:
+            return
+
+
+    def SetProgress(self, **kwargs):
+        """ Sets progress data from base_ui and dialog parameters
+        
+        """
+        if base_ui.SetProgress(self, **kwargs):
+
+            style = wx.PD_SMOOTH|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT
+            
+            if self._known_length:
+                style |= wx.PD_REMAINING_TIME
+            
+            if self._totalsteps is not None:
+                maxsteps = self._totalsteps
+            else:
+                maxsteps = 0
+                for i in self._steps:
+                    maxsteps += i
+            
+            self._total_counter = 0
+            
+            # known length?
+            title = self.title
+            if not self._single_progress:
+                title += " ({} processes)".format(len(self._steps))
+
+            self.dlg = wx.ProgressDialog(
+                 title = title,
+                 message = "Running : ",
+                 maximum = maxsteps,
+                 parent = self.parent,
+                 style = style)
+
+            self.dlg.SetMinSize((300+20*len(self._steps),80))
+
+
+    def Update(self, **kwargs):
+        """ Read and write from and to the user interface.
+        
+        Checks if the user has pressed 'Cancel' and updates the
+        Progress bar.
+        """
+        self._total_counter += 1
+
+        msg = "Running : "
+        
+        if self._single_progress:
+            if self._known_length:
+                msg += "PID {}-{}".format(self._pids[0],
+                                       self._subpids[0])
+            else:
+                msg += "PID {}-{}@{}".format(self._pids[0],
+                                          self._subpids[0],
+                                          self._progress[0])
+        else:
+            for i in range(len(self._pids)):
+                if self._pids[i] != -1:
+                    if self._known_length:
+                        msg += u"PID {}-{}@{}, ".format(
+                            self._pids[i], self._subpids[i],self._progress[i])
+                    else:
+                        msg += u"PID {}-{}, ".format(
+                            self._pids[i], self._subpids[i])
+
+        msg = msg.strip(" ,")
+
+        if self._known_length:
+            (cont,skip) = self.dlg.Update(self._total_counter, msg)
+        else:
+            (cont,skip) = self.dlg.UpdatePulse(newmsg=msg)
+
+        if cont is False:
+            # On next iteration, algorithms can abort if they
+            # support it.
+            self._abortlist += self._pids
+
+
+def get_terminal_size(fd=1):
+    """
+    Returns height and width of current terminal. First tries to get
+    size via termios.TIOCGWINSZ, then from environment. Defaults to 25
+    lines x 80 columns if both methods fail.
+
+    :param fd: file descriptor (default: 1=stdout)
+
+    Author: cas (http://blog.taz.net.au/author/cas/)
+    """
+    try:
+        import fcntl, termios, struct
+        hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
+    except:
+        try:
+            hw = (os.environ['LINES'], os.environ['COLUMNS'])
+        except:  
+            hw = (25, 80)
+
+    return hw
+
+
+def get_terminal_height(fd=1):
+    """
+    Returns height of terminal if it is a tty, 999 otherwise
+
+    :param fd: file descriptor (default: 1=stdout)
+    """
+    if os.isatty(fd):
+        height = get_terminal_size(fd)[0]
+    else:
+        height = 999
+   
+    return height
+
+
+def get_terminal_width(fd=1):
+    """
+    Returns width of terminal if it is a tty, 999 otherwise
+
+    :param fd: file descriptor (default: 1=stdout)
+    """
+    if os.isatty(fd):
+        width = get_terminal_size(fd)[1]
+    else:
+        width = 999
+
+    return width
+
+
+__version__ = "0.1.4"
+__author__ = "Paul Mueller"
+__email__ = "paul.mueller at biotec.tu-dresden.de"
+__license__ = "BSD (3-Clause)"
diff --git a/setup.py b/setup.py
index da6f729..46a8709 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ from setuptools import setup, find_packages, Extension
 from Cython.Distutils import build_ext
 import numpy as np
 
-from os.path import join, dirname, realpath
+from os.path import join, dirname, realpath, exists
 from warnings import warn
 
 # The next three lines are necessary for setup.py install to include
@@ -15,9 +15,17 @@ for scheme in INSTALL_SCHEMES.values():
     scheme['data'] = scheme['purelib']
 
 
+# Download documentation if it was not compiled
+Documentation = join(dirname(realpath(__file__)), "doc/PyScanFCS_doc.pdf")
+webdoc = "https://github.com/paulmueller/PyScanFCS/wiki/PyScanFCS_doc.pdf"
+if not exists(Documentation):
+    print "Downloading {} from {}".format(Documentation, webdoc)
+    import urllib
+    #testfile = urllib.URLopener()
+    urllib.urlretrieve(webdoc, Documentation)
+
 # Get the version of PyCorrFit from the Changelog.txt
 StaticChangeLog = join(dirname(realpath(__file__)), "ChangeLog.txt")
-
 try:
     clfile = open(StaticChangeLog, 'r')
     version = clfile.readline().strip()
@@ -44,7 +52,7 @@ setup(
     version=version,
     packages=[name],
     package_dir={name: name},
-    data_files=[('pyscanfcs_doc', ['ChangeLog.txt', 'PyScanFCS_doc.pdf'])],
+    data_files=[('pyscanfcs_doc', ['ChangeLog.txt', 'doc/PyScanFCS_doc.pdf'])],
     license="GPL v2",
     description='Scientific tool for perpendicular line scanning FCS.',
     long_description=open(join(dirname(__file__), 'Readme.txt')).read(),

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/pyscanfcs.git



More information about the debian-med-commit mailing list