[3depict] 01/07: * Import 0.0.19

D Haley mycae-guest at moszumanska.debian.org
Wed Aug 3 23:47:16 UTC 2016


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

mycae-guest pushed a commit to branch master
in repository 3depict.

commit cf0e3570abcae402fd632e30451806e7b6d0a41f
Author: D Haley <mycae at gmx.com>
Date:   Wed Aug 3 23:52:56 2016 +0200

    * Import 0.0.19
---
 ChangeLog                                          |   35 +-
 README                                             |   12 +-
 TODO                                               |   18 +-
 config.h.in                                        |   17 +-
 configure.ac                                       |   49 +-
 data/startup-tips.txt                              |    7 +-
 docs/manual-latex/manual.aux                       |  118 +-
 docs/manual-latex/manual.bbl                       |    2 +-
 docs/manual-latex/manual.bib                       |    4 +-
 docs/manual-latex/manual.blg                       |   29 +-
 docs/manual-latex/manual.log                       |  113 +-
 docs/manual-latex/manual.pdf                       |  Bin 4550865 -> 4523074 bytes
 docs/manual-latex/manual.tex                       |    2 +-
 docs/manual-latex/manual.toc                       |   66 +-
 locales/de_DE/LC_MESSAGES/3Depict.mo               |  Bin 44825 -> 44640 bytes
 packaging/RPM/3Depict-0.0.17-font-path.patch       |   27 -
 packaging/RPM/3Depict-0.0.17-manual-pdf-loc.patch  |   16 -
 packaging/RPM/3Depict-0.0.17-upstream.patch        |   65 -
 packaging/RPM/3Depict.spec                         |   56 +-
 packaging/debian/changelog                         |    6 +
 packaging/mac/3package.sh                          |   16 +-
 packaging/mac/makeMacOSXApp                        |   36 +-
 packaging/makeTarball.sh                           |  136 +-
 packaging/mingw-debian-cross/bootstrap.sh          |  270 +-
 .../patches/gettext-disable-tools                  |   30 +-
 packaging/mingw-debian-cross/patches/glew-makefile |   17 +-
 .../mingw-debian-cross/patches/glew-makefile.base  |   15 +-
 packaging/mingw-debian-cross/windows-installer.nsi |   11 +-
 src/3Depict.cpp                                    |   34 +-
 src/Makefile.am                                    |    7 +-
 src/backend/APT/APTFileIO.cpp                      |    6 +-
 src/backend/APT/APTFileIO.h                        |    5 -
 src/backend/APT/APTRanges.cpp                      |   40 +-
 src/backend/APT/APTRanges.h                        |    5 +
 src/backend/APT/ionhit.cpp                         |   66 +-
 src/backend/APT/ionhit.h                           |   15 +-
 src/backend/animator.cpp                           |    4 +-
 src/backend/filter.cpp                             |  182 +-
 src/backend/filter.h                               |   42 +-
 src/backend/filters/algorithms/K3DTree-mk2.cpp     |  414 +-
 src/backend/filters/algorithms/K3DTree-mk2.h       |   32 +-
 src/backend/filters/algorithms/mass.cpp            |   94 +-
 src/backend/filters/algorithms/mass.h              |   12 +-
 src/backend/filters/algorithms/rdf.cpp             |   13 +-
 src/backend/filters/allFilter.cpp                  |    4 +-
 src/backend/filters/allFilter.h                    |    2 +-
 src/backend/filters/annotation.cpp                 |    3 +-
 src/backend/filters/boundingBox.cpp                |  194 +-
 src/backend/filters/boundingBox.h                  |    6 +-
 src/backend/filters/clusterAnalysis.cpp            |  292 +-
 src/backend/filters/clusterAnalysis.h              |    1 +
 src/backend/filters/compositionProfile.cpp         | 1972 -------
 src/backend/filters/compositionProfile.h           |  156 -
 src/backend/filters/dataLoad.cpp                   |    2 +-
 src/backend/filters/filterCommon.cpp               |   85 +-
 src/backend/filters/filterCommon.h                 |   84 +-
 src/backend/filters/geometryHelpers.cpp            |   20 +-
 src/backend/filters/ionClip.cpp                    |    3 +-
 src/backend/filters/ionColour.cpp                  |   18 +-
 src/backend/filters/ionDownsample.cpp              |   56 +-
 src/backend/filters/rangeFile.cpp                  |   26 +-
 src/backend/filters/spatialAnalysis.cpp            | 1257 ++++-
 src/backend/filters/spatialAnalysis.h              |   25 +-
 src/backend/filters/spectrumPlot.cpp               |   13 +-
 src/backend/filters/transform.cpp                  |  102 +-
 src/backend/filters/voxelise.cpp                   |   28 +-
 src/backend/filtertree.cpp                         |   44 +-
 src/backend/filtertreeAnalyse.cpp                  |   12 +-
 src/backend/plot.h                                 |    4 +
 src/backend/state.cpp                              |  111 +-
 src/backend/state.h                                |   22 +-
 src/backend/viscontrol.cpp                         |   23 +-
 src/common/assertion.h                             |    7 +-
 src/common/basics.cpp                              |   80 +-
 src/common/basics.h                                |   11 +-
 src/common/constants.cpp                           |    2 +-
 src/common/constants.h                             |    2 -
 src/common/mathfuncs.cpp                           |  105 +-
 src/common/mathfuncs.h                             |   20 +
 src/common/stringFuncs.cpp                         |   46 +-
 src/common/stringFuncs.h                           |    6 +
 src/common/voxels.cpp                              |  236 +-
 src/common/voxels.h                                |  104 +-
 src/gl/cameras.cpp                                 |   66 +-
 src/gl/cameras.h                                   |   13 +
 src/gl/drawables.cpp                               |  164 +-
 src/gl/drawables.h                                 |   44 +-
 src/gl/glDebug.h                                   |    2 +-
 src/gl/isoSurface.cpp                              |    1 +
 src/gui/cropPanel.cpp                              |    5 +
 src/gui/dialogs/ExportPos.cpp                      |   11 +-
 src/gui/dialogs/ExportRngDialog.cpp                |   21 +-
 src/gui/dialogs/StashDialog.cpp                    |   13 +-
 src/gui/dialogs/animateFilterDialog.cpp            |   39 +-
 .../animateSubDialogs/colourKeyFrameDialog.cpp     |   41 +-
 .../dialogs/animateSubDialogs/realKeyFrameDialog.h |    8 +-
 src/gui/glPane.cpp                                 |   55 +-
 src/gui/glPane.h                                   |    7 +-
 src/gui/glade-skeleton/mainWindow.wxg              |  252 +-
 src/gui/mainFrame.cpp                              |  543 +-
 src/gui/mainFrame.h                                |  237 +-
 src/gui/mathglPane.cpp                             |   31 +-
 src/testing/mglTesting.cpp                         |    2 +-
 src/testing/testing.cpp                            |   20 +-
 src/wx/propertyGridUpdater.h                       |    2 +-
 src/wx/wxcommon.cpp                                |    5 -
 src/wx/wxcomponents.cpp                            |    6 +-
 translations/3Depict_base.pot                      | 4862 +++++++++--------
 translations/3Depict_de_DE.mo                      |  Bin 44825 -> 44640 bytes
 translations/3Depict_de_DE.po                      | 5676 ++++++++++----------
 110 files changed, 10508 insertions(+), 8946 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index cf84aaa..e55657b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,37 @@
-* 05 Apr 2014 : 0.0.18
+* ?? Jun 2016 : 0.0.19
+	Features:
+	- New "Local concentration" algorithm in spatial analysis filter 
+	- Add text and VTK export to Export Pos dialog
+	- Experimental Background fitting in spectra 
+	 
+	User Visible Changes:
+	- Camera re-orientation buttons have been added. Previously you
+	  could get a similar effect using keyboard shortcuts, eg Ctrl+Space
+	- Fixed breakage to monitor mode
+	- Only show erosion clustering parameter if bulk linking is enabled
+	- Fixes for hanging when loading some files under windows
+	- Fix broken point em/replacement (set operation) mode in spatial analysis
+	- Fix missing and incorrectly labelled denominator property in voxelisation
+	- Refresh button now changes to "Abort" during calculations for
+	  all platforms (Previously windows only)
+	- Fix loading of rangefile data in filter tree, broken in 0.0.18
+	- Improve progress reporting for some filters
+	- Fix opengl rendering on OSX (Previously resizes would cause
+	  scene to be distorted or clipped)
+	- Minor improvements to point colour and size tracking
+	- Fix bug in point replace mode where square distance was used instead of regular distance.
+
+	Technical Bugfixes/changes:
+	- Many minor memory leaks fixed
+	- Fixes for C++11 compilation
+	- Many small crash bugs fixed
+	- Fix analysis state lost if loading state failed
+	- Fix name collision detection in package export
+		- will now check for origin of file, not just name
+	- Fix race bug in voxel summation, caught by unit tests.
+
+* 05 Apr 2015 : 0.0.18
+* 05 Apr 2015 : 0.0.18
 	Features:
 	- User interface now uses its own CPU. Should be much more
 	  responsive during refreshes
diff --git a/README b/README
index db45638..f726557 100644
--- a/README
+++ b/README
@@ -12,16 +12,17 @@ make install
 
 to build the default-mode (single-threaded, debug on ) program. 
 
-Interesting configure flags (see ./configure --help):
+Interesting configure flags (see "./configure --help" for more options):
 
 --enable-openmp-parallel : Enable multi-CPU mode (for multi-CPU sections
  				of the program) via the "openMP" framework
 --disable-debug-checks : Disable debug checks. This makes the program
 				much faster, but less likely to catch
 				program bugs
---enable-mgl2 : Enable mathgl 2.x mode. By default, mathgl 1.x is assumed
-			to be installed
-
+--disable-ubsan : Disable undefined behaviour santiser. Makes the program
+			go faster, but undefined program behaviour (bugs)
+			will not be as readily detected
+--enable-experimental-cpp11 : Enables experimental C++11 support.
 
 Some Dependencies:
 	libxml2
@@ -32,7 +33,8 @@ Some Dependencies:
 	libpng
 	wxwidgets
 	gettext
-
+	vigra
+	
 
 	Remember, for dependencies under linux platforms you must install
 	the -dev, or -devel packages, in order to allow compilation
diff --git a/TODO b/TODO
index cd3b456..c0122f7 100644
--- a/TODO
+++ b/TODO
@@ -6,10 +6,18 @@ TODO List - worlds simplest bugtracking system
 	To Implement:
 		== Next version ==
 		* Voxelisation filter should not show ions disabled in upstream range
+		* VTK voxel data export UI
+		* Bounding box tick values could be improved - scientific
+		  notation, better font size control, absol. coords, etc
+		* Mesh generation/operation?
+			- This is tricky. I don't have a good mesh library
+		* Proxigram?
+		* Theoretical distributions are missing from the binomial algorithm
 	
 		== Eventually == 
+		* Update to qhull 2015's qhull_r (reentrant qhull). 
+			- This requires some refactoring of the doHull wrapper for convex hull computation
 		* Voxel export dialog 
-		* VTK voxel data export
 		* OPS and other 3DAP formats reader?
 		* Polynomial error estimator in graph
 		* Shear-warp volume render mode for voxels
@@ -25,14 +33,15 @@ TODO List - worlds simplest bugtracking system
 		* Better progress during cluster ranging
 		* Billboard text
 		* Camera animation control (slerp?)
-		* Bounding box tick values could be improved - scientific
-		  notation, better font size control, absol. coords, etc
 		* Range file drag/drop ignores drop coordinates; this could be useful
 		  in trying to interpret where the user wants to drop the object
 		* Plots cannot currently be updated on name change. Need to add "needUpdate" to setUserString
-
+		* Isotope overlay in normal spectra
+			- Include full atomic species eg 57^Fe18^O in label
+	
 	Outstanding bugs:
 		== Next release==
+		* Composition profile progress bad 
 	
 		== Eventually==
 		* Cluster filter wont save state correctly if parent
@@ -48,7 +57,6 @@ TODO List - worlds simplest bugtracking system
 		
 		OSX:
 			* drag drop not working?
-			* icon on dock bounces very fast during some refreshes
 
 		== Needs reproducing ==
 
diff --git a/config.h.in b/config.h.in
index 6166767..7d069f2 100644
--- a/config.h.in
+++ b/config.h.in
@@ -42,10 +42,6 @@
 /* Define to 1 if you have the <mach/mach.h> header file. */
 #undef HAVE_MACH_MACH_H
 
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
-   to 0 otherwise. */
-#undef HAVE_MALLOC
-
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -64,10 +60,6 @@
 /* qhull compilation OK */
 #undef HAVE_QHULL
 
-/* Define to 1 if your system has a GNU libc compatible `realloc' function,
-   and to 0 otherwise. */
-#undef HAVE_REALLOC
-
 /* Define to 1 if you have the `setlocale' function. */
 #undef HAVE_SETLOCALE
 
@@ -107,6 +99,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Have got vigra headers */
+#undef HAVE_VIGRA
+
 /* Define to 1 if the system has the type `_Bool'. */
 #undef HAVE__BOOL
 
@@ -157,12 +152,6 @@
 #undef inline
 #endif
 
-/* Define to rpl_malloc if the replacement function should be used. */
-#undef malloc
-
-/* Define to rpl_realloc if the replacement function should be used. */
-#undef realloc
-
 /* Define to `unsigned int' if <sys/types.h> does not define. */
 #undef size_t
 
diff --git a/configure.ac b/configure.ac
index c6dd0e5..d1779b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,12 @@
-AC_INIT([3Depict], [0.0.18]) 
+AC_INIT([3Depict], [0.0.19]) 
 AM_INIT_AUTOMAKE([foreign subdir-objects])
 AC_PROG_CXX
 AC_PROG_CC
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([Makefile src/Makefile])
 
+m4_include([m4/ax_compare_version.m4])
+
 #Ok, lets try using gcc style precompiled headers.
 AM_CONDITIONAL(USE_PRECOMPILED_HEADERS, 1)
 
@@ -18,8 +20,18 @@ dnl Test for wx-widgets
 dnl ----------
 AM_OPTIONS_WXCONFIG
 
-AM_PATH_WXCONFIG(2.9.0, wxWin=1)
-
+case "${host_os}" in
+	*mingw*)
+		#Windows requires 3.1, as there is a bug with wxPropertyGrid modification during events
+		# under GTK we use a hack to workaround, by keeping two grids, and flipping them in and out. 
+		#This doesn't work properly under windows. wx3.1 is not available under linux  
+		# (using repositories) at this time.
+		AM_PATH_WXCONFIG(3.1.0, wxWin=1)
+		;;	
+	*)
+		AM_PATH_WXCONFIG(3.0.0, wxWin=1)
+esac
+		
 if test "$wxWin" != 1; then
 AC_MSG_ERROR([
 		wxWidgets must be installed on your system
@@ -28,7 +40,7 @@ AC_MSG_ERROR([
 		Please check that wx-config is in path, the directory
 		where wxWidgets libraries are installed (returned by
 		'wx-config --libs' command) is in LD_LIBRARY_PATH or
-		equivalent variable and wxWidgets version is 2.6.0 or above.
+		equivalent variable and wxWidgets version is above the minimum specified above.
 ])
 fi
 
@@ -186,7 +198,7 @@ AC_SUBST([QHULL_CFLAGS])
 CFLAGS_ORIG="$CFLAGS"
 CFLAGS="$CFLAGS $QHULL_CFLAGS"
 AC_CHECK_HEADER([qhull/qhull_a.h],[AC_DEFINE(HAVE_QHULL,[],[Have got libqhull headers])],
-	[AC_MSG_ERROR([Required libqhull headers not found (looking for qhull/qhull_a.h])])
+	[AC_MSG_ERROR([Required libqhull headers not found (looking for qhull/qhull_a.h)])])
 
 if test x"$with_libqhull_link" != x"" ;
 then
@@ -372,6 +384,15 @@ fi
 dnl -----------------
 
 
+dnl -----------------
+AC_LANG_PUSH([C++])
+AC_CHECK_HEADER([vigra/multi_array.hxx],[AC_DEFINE(HAVE_VIGRA,[],[Have got vigra headers])],
+	[AC_MSG_ERROR([Required vigra headers not found (looking for vigra/multi_array.hxx)])])
+
+AC_LANG_POP([C++])
+dnl -----------------
+
+
 #Should we compile with openMP?
 AC_ARG_ENABLE(openmp-parallel,
   [  --enable-openmp-parallel  Enable OpenMP multi-CPU usage; requires GCC > 4.2 for parallel STL support ])
@@ -427,11 +448,10 @@ then
 			case "${host_os}" in
 				*inux*)
 					GCC_VER=`gcc --version | head -n 1 | awk '{ print $(NF)}'`
-					case "${GCC_VER}" in
-						4.9*)
-							USE_UBSAN="yes"
-						;;
-					esac
+					AX_COMPARE_VERSION( [ $GCC_VER ], ge, 4.9,
+							[ USE_UBSAN="yes" ] , [ USE_UBSAN="no" ])
+					AX_COMPARE_VERSION( [ $GCC_VER ], ge, 6.0,
+							[ USE_UBSAN_GCC6="yes" ] , [ USE_UBSAN_GCC6="no" ])
 				;;
 			esac
 
@@ -441,6 +461,13 @@ then
 				LDFLAGS="$LDFLAGS  -fsanitize=address -fsanitize=undefined -fsanitize=return "
 				AC_MSG_RESULT(["Enabling Gcc-UbSan"]);
 			fi
+			
+			if test x"$USE_UBSAN_GCC6" == x"yes" ; then
+				CFLAGS="$CFLAGS -fsanitize=bounds-strict" 
+				CXXFLAGS="$CXXFLAGS  -fsanitize=bounds-strict"
+				LDFLAGS="$LDFLAGS  -fsanitize=bounds-strict"
+				AC_MSG_RESULT(["Enabling More Gcc-UbSan (gcc6)"]);
+			fi
 		fi
 		#--
 	
@@ -471,8 +498,6 @@ fi
 # Checks for typedefs, structures, and compiler characteristics.
 AC_HEADER_STDBOOL
 AC_C_CONST
-AC_FUNC_MALLOC 
-AC_FUNC_REALLOC 
 AC_TYPE_SIZE_T 
 AC_TYPE_UINT64_T 
 
diff --git a/data/startup-tips.txt b/data/startup-tips.txt
index 1ae43f9..9d32607 100644
--- a/data/startup-tips.txt
+++ b/data/startup-tips.txt
@@ -1,5 +1,5 @@
 #This is the startup tips file that is passed to wxTipProvider, to generate the startup tips dialog
-# each tip must be of the form _("some tip"), the leading _(" must be the same for each tip.
+# each tip must be of the form _("some tip")
 # wx docs say : blank lines, and lines starting with # are skipped
 
 _("You can reset the main view by tapping the space bar. Hold down modifier keys like shift,ctrl to change the axis. Double tap to switch which axis to look down")
@@ -11,7 +11,7 @@ _("You can access the manual from the Help menu")
 _("You can change filter defaults using the Edit->Preferences menu item")
 _("You can overlay multiple plots at once, by selecting more than on plot at a time (e.g. using Ctrl)")
 _("Calculations are much faster (more than linear speedup) when working with smaller datasets - try sampling, or clipping out a small region to work faster, then remove the sampling when you are ready")
-_("You can abort most calculations by pressing Escape")
+_("You can abort most calculations either by pressing Escape (OSX/Linux), or by using the Abort button (Windows)")
 _("That anyone can contribute to improving this program, even without knowing about computer programming?")
 _("You can load more than one file at a time, then either operate on the separately, or together")
 _("You can have more than one range file for different parts of your dataset")
@@ -19,5 +19,6 @@ _("Cameras can be saved and retrieved whenever you like, using the camera tab")
 _("Subsections of the filter tree can be saved to the \"Stashed filters\" drop-down")
 _("The console tab along the bottom often shows useful messages from filters. When new messages appear, a small symbol is shown on the tab")
 _("The raw data used for any plot can be accessed from the \"Raw\" tab on the bottom panel")
-_("You can ask questions about the program, or using it on your data on our forums (http://sourceforge.net/apps/phpbb/threedepict/)")
+_("You can ask questions about the program, or using it on your data on our forums (https://sourceforge.net/p/threedepict/discussion/general/)")
 _("By creating a camera, you can switch between orthographic and perspective views")
+_("You can open multiple files at once, and get a side-by-side view by translating (shifting) one of the datasets to one side")
diff --git a/docs/manual-latex/manual.aux b/docs/manual-latex/manual.aux
index f9d6972..8344701 100644
--- a/docs/manual-latex/manual.aux
+++ b/docs/manual-latex/manual.aux
@@ -134,73 +134,77 @@
 \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.7}Spectrum}{29}{subsubsection.5.2.7}}
 \@writefile{lot}{\contentsline {table}{\numberline {7}{\ignorespaces Propagation matrix for Spectrum.}}{30}{table.7}}
 \@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.8}Profile}{30}{subsubsection.5.2.8}}
-\@writefile{lot}{\contentsline {table}{\numberline {8}{\ignorespaces Propagation matrix for Profile.}}{30}{table.8}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.9}Spatial Analysis}{30}{subsubsection.5.2.9}}
-\@writefile{toc}{\contentsline {paragraph}{Algorithms}{30}{section*.3}}
 \citation{Moody2008}
 \citation{Gault2012}
 \citation{Geiser2007}
 \citation{Boll2007}
-\@writefile{lot}{\contentsline {table}{\numberline {9}{\ignorespaces Propagation matrix for Spatial Analysis.}}{31}{table.9}}
+\@writefile{lot}{\contentsline {table}{\numberline {8}{\ignorespaces Propagation matrix for Profile.}}{31}{table.8}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.9}Spatial Analysis}{31}{subsubsection.5.2.9}}
+\@writefile{toc}{\contentsline {paragraph}{Algorithms}{31}{section*.3}}
+\@writefile{toc}{\contentsline {paragraph}{Radial Distribution:}{31}{section*.4}}
+\@writefile{toc}{\contentsline {paragraph}{Axial Distribution:}{32}{section*.5}}
+\@writefile{toc}{\contentsline {paragraph}{Binomial:}{32}{section*.6}}
+\@writefile{toc}{\contentsline {paragraph}{Point em/re-placement}{32}{section*.7}}
+\@writefile{lot}{\contentsline {table}{\numberline {9}{\ignorespaces Propagation matrix for Spatial Analysis.}}{32}{table.9}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.10}Clustering analysis}{32}{subsubsection.5.2.10}}
 \citation{Stephenson07}
 \citation{Hyde10}
 \citation{Vaumousse03}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.10}Clustering analysis}{32}{subsubsection.5.2.10}}
-\@writefile{lot}{\contentsline {table}{\numberline {10}{\ignorespaces Propagation matrix for Clustering Analysis.}}{33}{table.10}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.11}External Program}{33}{subsubsection.5.2.11}}
-\@writefile{toc}{\contentsline {paragraph}{Command syntax: }{33}{section*.4}}
-\@writefile{toc}{\contentsline {paragraph}{Prior to program execution:}{33}{section*.5}}
-\@writefile{toc}{\contentsline {paragraph}{After program execution:}{33}{section*.6}}
-\@writefile{lot}{\contentsline {table}{\numberline {11}{\ignorespaces Propagation matrix for External Program.}}{34}{table.11}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.12}Annotation}{34}{subsubsection.5.2.12}}
-\@writefile{toc}{\contentsline {paragraph}{Text}{34}{section*.7}}
-\@writefile{toc}{\contentsline {paragraph}{Arrow, Arrow with Text}{34}{section*.8}}
-\@writefile{toc}{\contentsline {paragraph}{Angle Measurement}{34}{section*.9}}
-\@writefile{lot}{\contentsline {table}{\numberline {12}{\ignorespaces Propagation matrix for Annotation.}}{35}{table.12}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.13}Voxels}{35}{subsubsection.5.2.13}}
-\@writefile{lot}{\contentsline {table}{\numberline {13}{\ignorespaces Propagation matrix for Voxels.}}{35}{table.13}}
-\@writefile{lof}{\contentsline {figure}{\numberline {22}{\ignorespaces Voxelisation filter, showing different representations. Left to right shows point cloud, axial slice and isosurface mode on the same dataset}}{36}{figure.22}}
-\newlabel{fig:voxeliseDisplayType}{{22}{36}{Voxelisation filter, showing different representations. Left to right shows point cloud, axial slice and isosurface mode on the same dataset}{figure.22}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.14}Ion Colour}{36}{subsubsection.5.2.14}}
-\@writefile{lot}{\contentsline {table}{\numberline {14}{\ignorespaces Propagation matrix for Ion Colour.}}{36}{table.14}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.15}Ion Transform}{36}{subsubsection.5.2.15}}
-\@writefile{lot}{\contentsline {table}{\numberline {15}{\ignorespaces Propagation matrix for Ion Transform.}}{37}{table.15}}
-\@writefile{toc}{\contentsline {section}{\numberline {6}Attributions}{37}{section.6}}
-\@writefile{toc}{\contentsline {section}{\numberline {7}Licence}{37}{section.7}}
-\@writefile{toc}{\contentsline {section}{\numberline {8}Appendices}{37}{section.8}}
-\newlabel{sec:appendix}{{8}{37}{Appendices}{section.8}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {8.1}Paths}{37}{subsection.8.1}}
-\newlabel{sec:3DepictPaths}{{8.1}{37}{Paths}{subsection.8.1}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {8.2}File formats}{38}{subsection.8.2}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.1}State file}{38}{subsubsection.8.2.1}}
-\newlabel{sec:xmlstatefile}{{8.2.1}{38}{State file}{subsubsection.8.2.1}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.2}Range files}{39}{subsubsection.8.2.2}}
-\newlabel{sec:rangeFormat}{{8.2.2}{39}{Range files}{subsubsection.8.2.2}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.3}POS files}{40}{subsubsection.8.2.3}}
-\newlabel{sec:posformat}{{8.2.3}{40}{POS files}{subsubsection.8.2.3}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.4}Text files}{40}{subsubsection.8.2.4}}
-\newlabel{sec:textformat}{{8.2.4}{40}{Text files}{subsubsection.8.2.4}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {8.3}External Program Examples}{40}{subsection.8.3}}
-\newlabel{sec:externalProgExample}{{8.3}{40}{External Program Examples}{subsection.8.3}{}}
-\@writefile{lof}{\contentsline {figure}{\numberline {23}{\ignorespaces Example program screenshot using the \emph  {Scilab} sample script. The \%i value in the command line instructs \emph  {3Depict} to take the first (and only the first) ion stream, and save it as an input file for the external program. }}{41}{figure.23}}
-\newlabel{fig:externalProgScilabSample}{{23}{41}{Example program screenshot using the \emph {Scilab} sample script. The \%i value in the command line instructs \emph {3Depict} to take the first (and only the first) ion stream, and save it as an input file for the external program}{figure.23}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.1}Scilab}{41}{subsubsection.8.3.1}}
-\@writefile{lof}{\contentsline {figure}{\numberline {24}{\ignorespaces Example program screenshot without and with the Python test example present. Note that the program merges ion streams into a single pos file, which is re-loaded as a single ion stream, as marked by the arrows.}}{45}{figure.24}}
-\newlabel{fig:externalProgPythonSample}{{24}{45}{Example program screenshot without and with the Python test example present. Note that the program merges ion streams into a single pos file, which is re-loaded as a single ion stream, as marked by the arrows}{figure.24}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.2}Python}{45}{subsubsection.8.3.2}}
-\@writefile{lof}{\contentsline {figure}{\numberline {25}{\ignorespaces Example program screenshot when using the BASH test example.}}{47}{figure.25}}
-\newlabel{fig:externalProgBashSample}{{25}{47}{Example program screenshot when using the BASH test example}{figure.25}{}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.3}Bash}{47}{subsubsection.8.3.3}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.4}C/C++}{48}{subsubsection.8.3.4}}
-\@writefile{lof}{\contentsline {figure}{\numberline {26}{\ignorespaces Example program screenshot without and with the C++ test example present..}}{49}{figure.26}}
-\newlabel{fig:externalProgCppSample}{{26}{49}{Example program screenshot without and with the C++ test example present.}{figure.26}{}}
-\@writefile{toc}{\contentsline {subsection}{\numberline {8.4}Modifying the program}{53}{subsection.8.4}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.4.1}Development tools}{53}{subsubsection.8.4.1}}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.4.2}Getting yourself set up}{53}{subsubsection.8.4.2}}
+\@writefile{lot}{\contentsline {table}{\numberline {10}{\ignorespaces Propagation matrix for Clustering Analysis.}}{34}{table.10}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.11}External Program}{34}{subsubsection.5.2.11}}
+\@writefile{toc}{\contentsline {paragraph}{Command syntax: }{34}{section*.8}}
+\@writefile{toc}{\contentsline {paragraph}{Prior to program execution:}{34}{section*.9}}
+\@writefile{toc}{\contentsline {paragraph}{After program execution:}{34}{section*.10}}
+\@writefile{lot}{\contentsline {table}{\numberline {11}{\ignorespaces Propagation matrix for External Program.}}{35}{table.11}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.12}Annotation}{35}{subsubsection.5.2.12}}
+\@writefile{toc}{\contentsline {paragraph}{Text}{35}{section*.11}}
+\@writefile{toc}{\contentsline {paragraph}{Arrow, Arrow with Text}{35}{section*.12}}
+\@writefile{toc}{\contentsline {paragraph}{Angle Measurement}{35}{section*.13}}
+\@writefile{lot}{\contentsline {table}{\numberline {12}{\ignorespaces Propagation matrix for Annotation.}}{36}{table.12}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.13}Voxels}{36}{subsubsection.5.2.13}}
+\@writefile{lot}{\contentsline {table}{\numberline {13}{\ignorespaces Propagation matrix for Voxels.}}{36}{table.13}}
+\@writefile{lof}{\contentsline {figure}{\numberline {22}{\ignorespaces Voxelisation filter, showing different representations. Left to right shows point cloud, axial slice and isosurface mode on the same dataset}}{37}{figure.22}}
+\newlabel{fig:voxeliseDisplayType}{{22}{37}{Voxelisation filter, showing different representations. Left to right shows point cloud, axial slice and isosurface mode on the same dataset}{figure.22}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.14}Ion Colour}{37}{subsubsection.5.2.14}}
+\@writefile{lot}{\contentsline {table}{\numberline {14}{\ignorespaces Propagation matrix for Ion Colour.}}{37}{table.14}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.2.15}Ion Transform}{37}{subsubsection.5.2.15}}
+\@writefile{lot}{\contentsline {table}{\numberline {15}{\ignorespaces Propagation matrix for Ion Transform.}}{38}{table.15}}
+\@writefile{toc}{\contentsline {section}{\numberline {6}Attributions}{38}{section.6}}
+\@writefile{toc}{\contentsline {section}{\numberline {7}Licence}{38}{section.7}}
+\@writefile{toc}{\contentsline {section}{\numberline {8}Appendices}{38}{section.8}}
+\newlabel{sec:appendix}{{8}{38}{Appendices}{section.8}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.1}Paths}{38}{subsection.8.1}}
+\newlabel{sec:3DepictPaths}{{8.1}{38}{Paths}{subsection.8.1}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.2}File formats}{39}{subsection.8.2}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.1}State file}{39}{subsubsection.8.2.1}}
+\newlabel{sec:xmlstatefile}{{8.2.1}{39}{State file}{subsubsection.8.2.1}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.2}Range files}{40}{subsubsection.8.2.2}}
+\newlabel{sec:rangeFormat}{{8.2.2}{40}{Range files}{subsubsection.8.2.2}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.3}POS files}{41}{subsubsection.8.2.3}}
+\newlabel{sec:posformat}{{8.2.3}{41}{POS files}{subsubsection.8.2.3}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.2.4}Text files}{41}{subsubsection.8.2.4}}
+\newlabel{sec:textformat}{{8.2.4}{41}{Text files}{subsubsection.8.2.4}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.3}External Program Examples}{41}{subsection.8.3}}
+\newlabel{sec:externalProgExample}{{8.3}{41}{External Program Examples}{subsection.8.3}{}}
+\@writefile{lof}{\contentsline {figure}{\numberline {23}{\ignorespaces Example program screenshot using the \emph  {Scilab} sample script. The \%i value in the command line instructs \emph  {3Depict} to take the first (and only the first) ion stream, and save it as an input file for the external program. }}{42}{figure.23}}
+\newlabel{fig:externalProgScilabSample}{{23}{42}{Example program screenshot using the \emph {Scilab} sample script. The \%i value in the command line instructs \emph {3Depict} to take the first (and only the first) ion stream, and save it as an input file for the external program}{figure.23}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.1}Scilab}{42}{subsubsection.8.3.1}}
+\@writefile{lof}{\contentsline {figure}{\numberline {24}{\ignorespaces Example program screenshot without and with the Python test example present. Note that the program merges ion streams into a single pos file, which is re-loaded as a single ion stream, as marked by the arrows.}}{46}{figure.24}}
+\newlabel{fig:externalProgPythonSample}{{24}{46}{Example program screenshot without and with the Python test example present. Note that the program merges ion streams into a single pos file, which is re-loaded as a single ion stream, as marked by the arrows}{figure.24}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.2}Python}{46}{subsubsection.8.3.2}}
+\@writefile{lof}{\contentsline {figure}{\numberline {25}{\ignorespaces Example program screenshot when using the BASH test example.}}{48}{figure.25}}
+\newlabel{fig:externalProgBashSample}{{25}{48}{Example program screenshot when using the BASH test example}{figure.25}{}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.3}Bash}{48}{subsubsection.8.3.3}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.3.4}C/C++}{49}{subsubsection.8.3.4}}
+\@writefile{lof}{\contentsline {figure}{\numberline {26}{\ignorespaces Example program screenshot without and with the C++ test example present..}}{50}{figure.26}}
+\newlabel{fig:externalProgCppSample}{{26}{50}{Example program screenshot without and with the C++ test example present.}{figure.26}{}}
+\@writefile{toc}{\contentsline {subsection}{\numberline {8.4}Modifying the program}{54}{subsection.8.4}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.4.1}Development tools}{54}{subsubsection.8.4.1}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.4.2}Getting yourself set up}{54}{subsubsection.8.4.2}}
 \bibstyle{unsrt}
 \bibdata{manual}
 \bibcite{Moody2008}{1}
-\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.4.3}Changing stuff}{54}{subsubsection.8.4.3}}
+\@writefile{toc}{\contentsline {subsubsection}{\numberline {8.4.3}Changing stuff}{55}{subsubsection.8.4.3}}
 \bibcite{Gault2012}{2}
 \bibcite{Geiser2007}{3}
 \bibcite{Boll2007}{4}
diff --git a/docs/manual-latex/manual.bbl b/docs/manual-latex/manual.bbl
index 40c1dc3..8b346b9 100644
--- a/docs/manual-latex/manual.bbl
+++ b/docs/manual-latex/manual.bbl
@@ -4,7 +4,7 @@
 Michael~P. Moody, Leigh Stephenson, Anna~V. Ceguerra, and S.~P. Ringer.
 \newblock Quantitative binomial distribution analyses of nanoscale like-solute
   atom clustering and segregation in atom probe tomography data.
-\newblock (71):542--550, 2008.
+\newblock {\em Microscopy Research and Technique}, 71(7):542--550, 2008.
 
 \bibitem{Gault2012}
 B.~Gault, M.~Moody, J.~Cairney, and Ringer~S. P.
diff --git a/docs/manual-latex/manual.bib b/docs/manual-latex/manual.bib
index 89615a2..9bb0e5a 100644
--- a/docs/manual-latex/manual.bib
+++ b/docs/manual-latex/manual.bib
@@ -54,9 +54,11 @@
 @Article{Moody2008,
   Title                    = {Quantitative Binomial Distribution Analyses of Nanoscale Like-Solute Atom Clustering and Segregation in Atom Probe Tomography Data },
   Author                   = {Michael P. Moody and Leigh Stephenson and Anna V. Ceguerra and S. P. Ringer},
+  Journal                  = {Microscopy Research and Technique},
   Year                     = {2008},
-  Number                   = {71},
   Pages                    = {542-550},
+  Volume                   = {71},
+  Number                   = {7},
 
   Abstract                 = {The applicability of the binomial frequency distribution is outlined for the analysis of the evolution nanoscale atomic clustering of dilute solute in an alloy subject to thermal ageing in 3D atom probe data. The conventional v2 statistics and significance testing are demonstrated to be inappropriate for comparison of quantity of solute segregation present in two or more different sized system. Pearson coefficient, l, is shown to normalize v2 with respect to s [...]
 },
diff --git a/docs/manual-latex/manual.blg b/docs/manual-latex/manual.blg
index 2d3519b..20e2fba 100644
--- a/docs/manual-latex/manual.blg
+++ b/docs/manual-latex/manual.blg
@@ -1,49 +1,46 @@
-This is BibTeX, Version 0.99d (TeX Live 2014/Debian)
+This is BibTeX, Version 0.99d (TeX Live 2013/Debian)
 Capacity: max_strings=35307, hash_size=35307, hash_prime=30011
 The top-level auxiliary file: manual.aux
 The style file: unsrt.bst
 Database file #1: manual.bib
-Warning--empty journal in Moody2008
-Warning--there's a number but no volume in Moody2008
 You've used 7 entries,
             1791 wiz_defined-function locations,
-            491 strings with 4839 characters,
-and the built_in function-call counts, 1681 in all, are:
-= -- 136
+            493 strings with 4873 characters,
+and the built_in function-call counts, 1680 in all, are:
+= -- 137
 > -- 98
 < -- 0
 + -- 35
 - -- 28
-* -- 137
-:= -- 287
+* -- 136
+:= -- 288
 add.period$ -- 22
 call.type$ -- 7
 change.case$ -- 6
 chr.to.int$ -- 0
-cite$ -- 9
+cite$ -- 7
 duplicate$ -- 63
 empty$ -- 153
 format.name$ -- 28
-if$ -- 362
+if$ -- 363
 int.to.chr$ -- 0
 int.to.str$ -- 7
 missing$ -- 8
 newline$ -- 38
 num.names$ -- 7
-pop$ -- 16
+pop$ -- 13
 preamble$ -- 1
 purify$ -- 0
 quote$ -- 0
-skip$ -- 18
+skip$ -- 20
 stack$ -- 0
 substring$ -- 109
-swap$ -- 6
+swap$ -- 7
 text.length$ -- 0
 text.prefix$ -- 0
 top$ -- 0
 type$ -- 0
-warning$ -- 2
+warning$ -- 0
 while$ -- 13
 width$ -- 8
-write$ -- 77
-(There were 2 warnings)
+write$ -- 78
diff --git a/docs/manual-latex/manual.log b/docs/manual-latex/manual.log
index 38771a5..bf9fb79 100644
--- a/docs/manual-latex/manual.log
+++ b/docs/manual-latex/manual.log
@@ -1,11 +1,11 @@
-This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014/Debian) (preloaded format=pdflatex 2014.6.29)  2 AUG 2014 00:59
+This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013/Debian) (format=pdflatex 2016.5.5)  31 MAY 2016 12:21
 entering extended mode
  restricted \write18 enabled.
  %&-line parsing enabled.
 **manual.tex
 (./manual.tex
-LaTeX2e <2014/05/01>
-Babel <3.9k> and hyphenation patterns for 2 languages loaded.
+LaTeX2e <2011/06/27>
+Babel <3.9h> and hyphenation patterns for 2 languages loaded.
 (/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
 Document Class: article 2007/10/19 v1.4h Standard LaTeX document class
 (/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo
@@ -28,10 +28,10 @@ Package: fullpage 1999/02/23 1.1 (PWD)
 \FP at margin=\skip43
 )
 (/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
-Package: graphicx 2014/04/25 v1.0g Enhanced LaTeX Graphics (DPC,SPQR)
+Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR)
 
 (/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty
-Package: keyval 2014/05/08 v1.15 key=value parser (DPC)
+Package: keyval 1999/03/16 v1.13 key=value parser (DPC)
 \KV at toks@=\toks14
 )
 (/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
@@ -492,91 +492,76 @@ line 568.
  [22 <./figures/exportanimParamDialog.png (PNG copy)>] [23 <./figures/exportani
 mDialogConflict.png (PNG copy)> <./figures/exportanimDialogPropString.png (PNG 
 copy)>] [24 <./figures/exportanimDialogFrameView.png (PNG copy)>] [25] [26] [27
-] [28] [29] [30]
+] [28] [29]
 
-LaTeX Warning: Citation `Moody2008' on page 31 undefined on input line 905.
-
-
-LaTeX Warning: Citation `Gault2012' on page 31 undefined on input line 908.
-
-
-LaTeX Warning: Citation `Geiser2007' on page 31 undefined on input line 910.
-
-
-LaTeX Warning: Citation `Boll2007' on page 31 undefined on input line 910.
-
-[31]
-
-LaTeX Warning: Citation `Stephenson07' on page 32 undefined on input line 947.
-
-
-LaTeX Warning: Citation `Hyde10' on page 32 undefined on input line 947.
+LaTeX Warning: `!h' float specifier changed to `!ht'.
 
+[30] [31] [32]
 
-LaTeX Warning: Citation `Vaumousse03' on page 32 undefined on input line 947.
+LaTeX Warning: `!h' float specifier changed to `!ht'.
 
-[32]
+[33]
 
 LaTeX Warning: `!h' float specifier changed to `!ht'.
 
-[33] [34]
-<./figures/voxel-representations.png, id=1411, 1615.03375pt x 1027.84pt>
+[34] [35]
+<./figures/voxel-representations.png, id=1434, 1615.03375pt x 1027.84pt>
 File: ./figures/voxel-representations.png Graphic file (type png)
 
 <use ./figures/voxel-representations.png>
 Package pdftex.def Info: ./figures/voxel-representations.png used on input line
- 1099.
+ 1114.
 (pdftex.def)             Requested size: 422.77664pt x 269.06708pt.
- [35] [36 <./figures/voxel-representations.png>] [37] [38] [39] [40]
-<./figures/externalProgScilab.png, id=1461, 1686.3pt x 847.165pt>
+ [36] [37 <./figures/voxel-representations.png>] [38] [39] [40] [41]
+<./figures/externalProgScilab.png, id=1484, 1686.3pt x 847.165pt>
 File: ./figures/externalProgScilab.png Graphic file (type png)
 
 <use ./figures/externalProgScilab.png>
 Package pdftex.def Info: ./figures/externalProgScilab.png used on input line 13
-46.
+61.
 (pdftex.def)             Requested size: 422.77664pt x 212.38535pt.
- [41 <./figures/externalProgScilab.png>]
-[42] [43] [44]
-<./figures/externalProgPython.png, id=1482, 1465.475pt x 856.19875pt>
+ [42 <./figures/externalProgScilab.png>]
+[43] [44] [45]
+<./figures/externalProgPython.png, id=1505, 1465.475pt x 856.19875pt>
 File: ./figures/externalProgPython.png Graphic file (type png)
 
 <use ./figures/externalProgPython.png>
 Package pdftex.def Info: ./figures/externalProgPython.png used on input line 15
-27.
+42.
 (pdftex.def)             Requested size: 399.29463pt x 233.28014pt.
- [45 <./figures/externalProgPython.png>]
-[46] <./figures/externalProgBash.png, id=1495, 1385.175pt x 876.27374pt>
+ [46 <./figures/externalProgPython.png>]
+[47] <./figures/externalProgBash.png, id=1517, 1385.175pt x 876.27374pt>
 File: ./figures/externalProgBash.png Graphic file (type png)
 
 <use ./figures/externalProgBash.png>
-Package pdftex.def Info: ./figures/externalProgBash.png used on input line 1601
+Package pdftex.def Info: ./figures/externalProgBash.png used on input line 1616
 .
 (pdftex.def)             Requested size: 399.29463pt x 252.5886pt.
- [47 <./figures/externalProgBash.png>]
-LaTeX Font Info:    Try loading font information for OMS+cmtt on input line 165
-8.
-LaTeX Font Info:    No file OMScmtt.fd. on input line 1658.
+ [48 <./figures/externalProgBash.png>]
+LaTeX Font Info:    Try loading font information for OMS+cmtt on input line 167
+3.
+LaTeX Font Info:    No file OMScmtt.fd. on input line 1673.
 
 
 LaTeX Font Warning: Font shape `OMS/cmtt/m/n' undefined
 (Font)              using `OMS/cmsy/m/n' instead
-(Font)              for symbol `textbraceleft' on input line 1658.
+(Font)              for symbol `textbraceleft' on input line 1673.
 
-<./figures/externalProgCpp.png, id=1502, 2123.935pt x 839.135pt>
+<./figures/externalProgCpp.png, id=1524, 2123.935pt x 839.135pt>
 File: ./figures/externalProgCpp.png Graphic file (type png)
 
 <use ./figures/externalProgCpp.png>
-Package pdftex.def Info: ./figures/externalProgCpp.png used on input line 1666.
+Package pdftex.def Info: ./figures/externalProgCpp.png used on input line 1681.
 
 (pdftex.def)             Requested size: 399.29463pt x 157.74715pt.
- [48] [49 <./figures/externalProgCpp.png>]
-[50] [51] [52] [53] (./manual.bbl [54])
-Package atveryend Info: Empty hook `BeforeClearDocument' on input line 1911.
- [55]
-Package atveryend Info: Empty hook `AfterLastShipout' on input line 1911.
+ [49] [50 <./figures/externalProgCpp.png>]
+[51] [52] [53] [54] (./manual.bbl [55])
+Package atveryend Info: Empty hook `BeforeClearDocument' on input line 1926.
+ [56]
+Package atveryend Info: Empty hook `AfterLastShipout' on input line 1926.
  (./manual.aux)
-Package atveryend Info: Executing hook `AtVeryEndDocument' on input line 1911.
-Package atveryend Info: Executing hook `AtEndAfterFileList' on input line 1911.
+Package atveryend Info: Executing hook `AtVeryEndDocument' on input line 1926.
+Package atveryend Info: Executing hook `AtEndAfterFileList' on input line 1926.
 
 Package rerunfilecheck Info: File `manual.out' has not changed.
 (rerunfilecheck)             Checksum: 5D9DF5F8101C21D1BE54E57385EA4596;5634.
@@ -584,19 +569,13 @@ Package rerunfilecheck Info: File `manual.out' has not changed.
 
 LaTeX Font Warning: Some font shapes were not available, defaults substituted.
 
-
-LaTeX Warning: There were undefined references.
-
-
-LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
-
-Package atveryend Info: Empty hook `AtVeryVeryEnd' on input line 1911.
+Package atveryend Info: Empty hook `AtVeryVeryEnd' on input line 1926.
  ) 
 Here is how much of TeX's memory you used:
- 5698 strings out of 495021
- 86846 string characters out of 6181344
- 165106 words of memory out of 5000000
- 8630 multiletter control sequences out of 15000+600000
+ 5703 strings out of 495028
+ 86896 string characters out of 6181498
+ 165302 words of memory out of 5000000
+ 8626 multiletter control sequences out of 15000+600000
  13156 words of font info for 46 fonts, out of 8000000 for 9000
  14 hyphenation exceptions out of 8191
  29i,11n,28p,1058b,447s stack positions out of 5000i,500n,10000p,200000b,80000s
@@ -617,10 +596,10 @@ re/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmti8.pfb></usr/share/texl
 ive/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10.pfb></usr/share/texlive/te
 xmf-dist/fonts/type1/public/amsfonts/cm/cmtt12.pfb></usr/share/texlive/texmf-di
 st/fonts/type1/public/amsfonts/cm/cmtt8.pfb>
-Output written on manual.pdf (59 pages, 4550865 bytes).
+Output written on manual.pdf (60 pages, 4523074 bytes).
 PDF statistics:
- 1660 PDF objects out of 1728 (max. 8388607)
- 1281 compressed objects within 13 object streams
- 209 named destinations out of 1000 (max. 500000)
+ 1676 PDF objects out of 1728 (max. 8388607)
+ 1296 compressed objects within 13 object streams
+ 214 named destinations out of 1000 (max. 500000)
  816 words of extra memory for PDF output out of 10000 (max. 10000000)
 
diff --git a/docs/manual-latex/manual.pdf b/docs/manual-latex/manual.pdf
index fef3e72..db2ac9b 100644
Binary files a/docs/manual-latex/manual.pdf and b/docs/manual-latex/manual.pdf differ
diff --git a/docs/manual-latex/manual.tex b/docs/manual-latex/manual.tex
index 36f168b..29a8f0c 100644
--- a/docs/manual-latex/manual.tex
+++ b/docs/manual-latex/manual.tex
@@ -40,7 +40,7 @@
 \begin{minipage}{0.3\textwidth}
 \begin{flushright} \large
 \emph{Version:} \\
- 0.0.18, Apr 2014\end{flushright}
+ 0.0.19, May 2016\end{flushright}
 \end{minipage}
 
 \vfill
diff --git a/docs/manual-latex/manual.toc b/docs/manual-latex/manual.toc
index 4012a83..edb77f1 100644
--- a/docs/manual-latex/manual.toc
+++ b/docs/manual-latex/manual.toc
@@ -59,35 +59,39 @@
 \contentsline {subsubsection}{\numberline {5.2.6}Clipping}{29}{subsubsection.5.2.6}
 \contentsline {subsubsection}{\numberline {5.2.7}Spectrum}{29}{subsubsection.5.2.7}
 \contentsline {subsubsection}{\numberline {5.2.8}Profile}{30}{subsubsection.5.2.8}
-\contentsline {subsubsection}{\numberline {5.2.9}Spatial Analysis}{30}{subsubsection.5.2.9}
-\contentsline {paragraph}{Algorithms}{30}{section*.3}
+\contentsline {subsubsection}{\numberline {5.2.9}Spatial Analysis}{31}{subsubsection.5.2.9}
+\contentsline {paragraph}{Algorithms}{31}{section*.3}
+\contentsline {paragraph}{Radial Distribution:}{31}{section*.4}
+\contentsline {paragraph}{Axial Distribution:}{32}{section*.5}
+\contentsline {paragraph}{Binomial:}{32}{section*.6}
+\contentsline {paragraph}{Point em/re-placement}{32}{section*.7}
 \contentsline {subsubsection}{\numberline {5.2.10}Clustering analysis}{32}{subsubsection.5.2.10}
-\contentsline {subsubsection}{\numberline {5.2.11}External Program}{33}{subsubsection.5.2.11}
-\contentsline {paragraph}{Command syntax: }{33}{section*.4}
-\contentsline {paragraph}{Prior to program execution:}{33}{section*.5}
-\contentsline {paragraph}{After program execution:}{33}{section*.6}
-\contentsline {subsubsection}{\numberline {5.2.12}Annotation}{34}{subsubsection.5.2.12}
-\contentsline {paragraph}{Text}{34}{section*.7}
-\contentsline {paragraph}{Arrow, Arrow with Text}{34}{section*.8}
-\contentsline {paragraph}{Angle Measurement}{34}{section*.9}
-\contentsline {subsubsection}{\numberline {5.2.13}Voxels}{35}{subsubsection.5.2.13}
-\contentsline {subsubsection}{\numberline {5.2.14}Ion Colour}{36}{subsubsection.5.2.14}
-\contentsline {subsubsection}{\numberline {5.2.15}Ion Transform}{36}{subsubsection.5.2.15}
-\contentsline {section}{\numberline {6}Attributions}{37}{section.6}
-\contentsline {section}{\numberline {7}Licence}{37}{section.7}
-\contentsline {section}{\numberline {8}Appendices}{37}{section.8}
-\contentsline {subsection}{\numberline {8.1}Paths}{37}{subsection.8.1}
-\contentsline {subsection}{\numberline {8.2}File formats}{38}{subsection.8.2}
-\contentsline {subsubsection}{\numberline {8.2.1}State file}{38}{subsubsection.8.2.1}
-\contentsline {subsubsection}{\numberline {8.2.2}Range files}{39}{subsubsection.8.2.2}
-\contentsline {subsubsection}{\numberline {8.2.3}POS files}{40}{subsubsection.8.2.3}
-\contentsline {subsubsection}{\numberline {8.2.4}Text files}{40}{subsubsection.8.2.4}
-\contentsline {subsection}{\numberline {8.3}External Program Examples}{40}{subsection.8.3}
-\contentsline {subsubsection}{\numberline {8.3.1}Scilab}{41}{subsubsection.8.3.1}
-\contentsline {subsubsection}{\numberline {8.3.2}Python}{45}{subsubsection.8.3.2}
-\contentsline {subsubsection}{\numberline {8.3.3}Bash}{47}{subsubsection.8.3.3}
-\contentsline {subsubsection}{\numberline {8.3.4}C/C++}{48}{subsubsection.8.3.4}
-\contentsline {subsection}{\numberline {8.4}Modifying the program}{53}{subsection.8.4}
-\contentsline {subsubsection}{\numberline {8.4.1}Development tools}{53}{subsubsection.8.4.1}
-\contentsline {subsubsection}{\numberline {8.4.2}Getting yourself set up}{53}{subsubsection.8.4.2}
-\contentsline {subsubsection}{\numberline {8.4.3}Changing stuff}{54}{subsubsection.8.4.3}
+\contentsline {subsubsection}{\numberline {5.2.11}External Program}{34}{subsubsection.5.2.11}
+\contentsline {paragraph}{Command syntax: }{34}{section*.8}
+\contentsline {paragraph}{Prior to program execution:}{34}{section*.9}
+\contentsline {paragraph}{After program execution:}{34}{section*.10}
+\contentsline {subsubsection}{\numberline {5.2.12}Annotation}{35}{subsubsection.5.2.12}
+\contentsline {paragraph}{Text}{35}{section*.11}
+\contentsline {paragraph}{Arrow, Arrow with Text}{35}{section*.12}
+\contentsline {paragraph}{Angle Measurement}{35}{section*.13}
+\contentsline {subsubsection}{\numberline {5.2.13}Voxels}{36}{subsubsection.5.2.13}
+\contentsline {subsubsection}{\numberline {5.2.14}Ion Colour}{37}{subsubsection.5.2.14}
+\contentsline {subsubsection}{\numberline {5.2.15}Ion Transform}{37}{subsubsection.5.2.15}
+\contentsline {section}{\numberline {6}Attributions}{38}{section.6}
+\contentsline {section}{\numberline {7}Licence}{38}{section.7}
+\contentsline {section}{\numberline {8}Appendices}{38}{section.8}
+\contentsline {subsection}{\numberline {8.1}Paths}{38}{subsection.8.1}
+\contentsline {subsection}{\numberline {8.2}File formats}{39}{subsection.8.2}
+\contentsline {subsubsection}{\numberline {8.2.1}State file}{39}{subsubsection.8.2.1}
+\contentsline {subsubsection}{\numberline {8.2.2}Range files}{40}{subsubsection.8.2.2}
+\contentsline {subsubsection}{\numberline {8.2.3}POS files}{41}{subsubsection.8.2.3}
+\contentsline {subsubsection}{\numberline {8.2.4}Text files}{41}{subsubsection.8.2.4}
+\contentsline {subsection}{\numberline {8.3}External Program Examples}{41}{subsection.8.3}
+\contentsline {subsubsection}{\numberline {8.3.1}Scilab}{42}{subsubsection.8.3.1}
+\contentsline {subsubsection}{\numberline {8.3.2}Python}{46}{subsubsection.8.3.2}
+\contentsline {subsubsection}{\numberline {8.3.3}Bash}{48}{subsubsection.8.3.3}
+\contentsline {subsubsection}{\numberline {8.3.4}C/C++}{49}{subsubsection.8.3.4}
+\contentsline {subsection}{\numberline {8.4}Modifying the program}{54}{subsection.8.4}
+\contentsline {subsubsection}{\numberline {8.4.1}Development tools}{54}{subsubsection.8.4.1}
+\contentsline {subsubsection}{\numberline {8.4.2}Getting yourself set up}{54}{subsubsection.8.4.2}
+\contentsline {subsubsection}{\numberline {8.4.3}Changing stuff}{55}{subsubsection.8.4.3}
diff --git a/locales/de_DE/LC_MESSAGES/3Depict.mo b/locales/de_DE/LC_MESSAGES/3Depict.mo
index c31b1ce..d746b34 100644
Binary files a/locales/de_DE/LC_MESSAGES/3Depict.mo and b/locales/de_DE/LC_MESSAGES/3Depict.mo differ
diff --git a/packaging/RPM/3Depict-0.0.17-font-path.patch b/packaging/RPM/3Depict-0.0.17-font-path.patch
deleted file mode 100644
index 02f52fc..0000000
--- a/packaging/RPM/3Depict-0.0.17-font-path.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-diff -r 7abb69436c2b src/wx/wxcomponents.cpp
---- src/wx/wxcomponents.cpp	Sat Aug 02 05:39:24 2014 -0400
-+++ src/wx/wxcomponents.cpp	Sat Aug 02 05:40:51 2014 -0400
-@@ -547,16 +547,17 @@
- 	//(Oh look Ma, I'm autoconf!)
- 
- 	const char *dirs[] = {	".",
--				"/usr/share/fonts/truetype", //Old debian 
-+				"/usr/local/share/fonts/truetype", // User fonts
- 				"/usr/share/fonts/truetype/freefont", // New debian
- 				"/usr/share/fonts/truetype/ttf-dejavu", //New debian
--				"/usr/local/share/fonts/truetype", // User fonts
-+				"/usr/share/fonts/truetype", //Old debian 
-+				"/usr/share/fonts/dejavu", //Fedora
- 				"/usr/X11R6/lib/X11/fonts/truetype",
- 				"/usr/X11R6/lib64/X11/fonts/truetype",
--				"/usr/lib/X11/fonts/truetype",// Fedora 32
--				"/usr/lib64/X11/fonts/truetype", //Fedora 64
--				"/usr/local/lib/X11/fonts/truetype", // Fedora 32 new
--				"/usr/local/lib64/X11/fonts/truetype",// Fedora 64 new
-+				"/usr/lib/X11/fonts/truetype",
-+				"/usr/lib64/X11/fonts/truetype", 
-+				"/usr/local/lib/X11/fonts/truetype", 
-+				"/usr/local/lib64/X11/fonts/truetype",
- 				"",
- 				}; //MUST end with "".
- 
diff --git a/packaging/RPM/3Depict-0.0.17-manual-pdf-loc.patch b/packaging/RPM/3Depict-0.0.17-manual-pdf-loc.patch
deleted file mode 100644
index 31178af..0000000
--- a/packaging/RPM/3Depict-0.0.17-manual-pdf-loc.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -r 7abb69436c2b src/gui/mainFrame.cpp
---- src/gui/mainFrame.cpp	Sat Aug 02 05:39:24 2014 -0400
-+++ src/gui/mainFrame.cpp	Sat Aug 02 05:40:32 2014 -0400
-@@ -2840,9 +2840,9 @@
- 	string s;
- 	s=locateDataFile("3Depict-manual.pdf");
- 
--	//Also Debian makes us use the lowercase "D", so check there too.
--	if(!s.size())
--		s=locateDataFile("3depict-manual.pdf");
-+	//Also Fedora has diff dir
-+	if(!wxFileExists(s))
-+		s="/usr/share/doc/3Depict-0.0.8/3Depict-0.0.8-manual.pdf";
- 
- 	//FIXME: under windows, currently we use "manual.pdf"
- 	if(!s.size())
diff --git a/packaging/RPM/3Depict-0.0.17-upstream.patch b/packaging/RPM/3Depict-0.0.17-upstream.patch
deleted file mode 100644
index c82d579..0000000
--- a/packaging/RPM/3Depict-0.0.17-upstream.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-diff -r 7372047ee6f9 src/common/basics.cpp
---- src/common/basics.cpp	Sun Aug 03 16:58:06 2014 -0400
-+++ src/common/basics.cpp	Sun Aug 03 17:01:04 2014 -0400
-@@ -1471,6 +1471,21 @@
- 	return 0;
- }
- 
-+bool isNotDirectory(const char *filename)
-+{
-+	struct stat statbuf;
-+
-+	if(stat(filename,&statbuf) == -1)
-+		return false;
-+
-+	return (statbuf.st_mode !=S_IFDIR);
-+}
-+
-+bool rmFile(const std::string &filename)
-+{
-+	return remove(filename.c_str()) == 0;
-+}
-+
- #ifdef DEBUG
- bool isValidXML(const char *filename)
- {
-@@ -1503,27 +1518,6 @@
- 	return true;
- }
- 
--#if !defined(__WIN32__) && !defined(__WIN64)
- 	
--bool isNotDirectory(const char *filename)
--{
--	struct stat statbuf;
--
--	if(stat(filename,&statbuf) == -1)
--		return false;
--
--	return (statbuf.st_mode !=S_IFDIR);
--}
--
--bool rmFile(const std::string &filename)
--{
--	return remove(filename.c_str()) == 0;
--}
--#elif defined(__WIN32) || defined(__WIN64)
--bool rmFile(const std::string &filename)
--{ 
--	return DeleteFile((const wchar_t*)filename.c_str()) == 0;
--}
--#endif
- 
- #endif
-diff -r 7372047ee6f9 src/gl/tr.cpp
---- src/gl/tr.cpp	Sun Aug 03 16:58:06 2014 -0400
-+++ src/gl/tr.cpp	Sun Aug 03 17:01:04 2014 -0400
-@@ -63,7 +63,7 @@
- #include "common/assertion.h"
- 
- #include <math.h>
--
-+#include <stdlib.h>
- 
- #ifdef WIN32
- #include <windows.h>
diff --git a/packaging/RPM/3Depict.spec b/packaging/RPM/3Depict.spec
index 53080f2..048bada 100644
--- a/packaging/RPM/3Depict.spec
+++ b/packaging/RPM/3Depict.spec
@@ -1,5 +1,5 @@
 Name:		3Depict
-Version:	0.0.18
+Version:	0.0.19
 Release:	1%{?dist}
 Summary:	Valued 3D point cloud visualization and analysis
 Group:		Applications/Engineering
@@ -10,8 +10,6 @@ URL:		http://threedepict.sourceforge.net
 Source0:	http://downloads.sourceforge.net/threedepict/%{name}-%{version}.tar.gz
 
 
-BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-
 #Mathgl for plotting
 BuildRequires:	mathgl-devel 
 #Mesa for GLU
@@ -25,7 +23,7 @@ BuildRequires: libpng-devel
 #Desktop file utils for installing desktop file
 BuildRequires: desktop-file-utils
 #WX widgets
-BuildRequires: wxGTK-devel
+BuildRequires: wxGTK3-devel
 #Vigra, for voxelisation
 BuildRequires: vigra-devel
 
@@ -54,12 +52,23 @@ useful for general scalar valued point data purposes.
 %patch0
 %patch1
 
+%if 0%{?fedora} > 24
+# Installation directory has changed
+sed -i -e 's,qhull/qhull_a.h,libqhull/qhull_a.h,' \
+  src/backend/filters/filterCommon.h \
+  src/backend/filters/algorithms/rdf.cpp \
+  configure configure.ac
+# Avoid rerunning the autotools
+touch -r aclocal.m4 configure configure.ac
+%endif
+
 %build
-%configure --disable-debug-checks --enable-openmp-parallel --enable-mgl2
+#Due to bug 1077718, wx-config cannot be specified, due to
+# wx2/wx3 conflict.
+%configure --disable-debug-checks --enable-openmp-parallel --with-wx-config=wx-config-3.0
 make %{?_smp_mflags}
 
 %install
-rm -rf %{buildroot}
 make install DESTDIR=%{buildroot}
 
 # Install the textures
@@ -96,13 +105,9 @@ mv docs/manual-latex/manual.pdf %{name}-%{version}-manual.pdf
 %find_lang %{name}
 
 
-%clean
-rm -rf %{buildroot}
-
-
 %files -f %{name}.lang
-%defattr(-,root,root,-)
-%doc COPYING AUTHORS ChangeLog README TODO %{name}-%{version}-manual.pdf
+%license COPYING
+%doc AUTHORS ChangeLog README TODO %{name}-%{version}-manual.pdf
 %{_bindir}/%{name}
 %dir %{_datadir}/%{name}/
 %dir %{_datadir}/%{name}/textures
@@ -113,7 +118,31 @@ rm -rf %{buildroot}
 
 
 %changelog
-* Tue Apr 21 2015 D Haley <mycae(a!t)gmx.com> - 0.0.18-1
+* Wed Jun 01 2016 D Haley <mycae(a!t)gmx.com> - 0.0.19-1
+- Update to 0.0.19
+- Remove gcc patch, fixed upstream
+
+* Fri Apr 29 2016 Ralf Corsépius <corsepiu at fedoraproject.org> - 0.0.18-7
+- Rebuild for qhull-2015.2-1.
+- Reflect qhull_a.h's location having changed.
+
+* Tue Mar 8 2016 Orion Poplawski <orion at cora.nwra.com> - 0.0.18-6
+- Add patch for fix compilation with gcc 6
+
+* Mon Feb 22 2016 Orion Poplawski <orion at cora.nwra.com> - 0.0.18-5
+- Rebuild for gsl 2.1
+- Cleanup spec
+
+* Wed Feb 03 2016 Fedora Release Engineering <releng at fedoraproject.org> - 0.0.18-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Sun Nov 29 2015 Kalev Lember <klember at redhat.com> - 0.0.18-3
+- Rebuilt for libmgl soname bump
+
+* Tue Jun 16 2015 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.0.18-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Fri May 01 2015 D Haley <mycae(a!t)gmx.com> - 0.0.18-1
 - Update to 0.0.18
 
 * Sat Oct 11 2014 D Haley <mycae(a!t)gmx.com> - 0.0.17-2
@@ -222,3 +251,4 @@ rm -rf %{buildroot}
 
 * Sun Aug 08 2010 D Haley <mycae(a!t)yahoo.com> - 0.0.1-1
 - Initial package
+
diff --git a/packaging/debian/changelog b/packaging/debian/changelog
index 83cb3c2..c3f7bf2 100644
--- a/packaging/debian/changelog
+++ b/packaging/debian/changelog
@@ -1,3 +1,9 @@
+3depict (0.0.19-1) unstable; urgency=medium
+
+  * 
+
+ -- D Haley <mycae at gmx.com>  Tue, 31 May 2016 12:00:39 +1000
+
 3depict (0.0.18-1) unstable; urgency=medium
 
   * Update to upstream 0.0.17
diff --git a/packaging/mac/3package.sh b/packaging/mac/3package.sh
index 7fee2f3..c51a720 100755
--- a/packaging/mac/3package.sh
+++ b/packaging/mac/3package.sh
@@ -5,10 +5,16 @@ PROGRAM_NAME=3Depict
 cp makeMacOSXApp ../..
 cp -R ${PROGRAM_NAME}.app ../..
 cd ../..
+echo "" > compile
+echo "" > install-sh
+
+make clean > out.txt 2>&1
 make distclean > out.txt 2>&1
 
+autoreconf >> out.txt 2>&1
+
 #Pull version number out of configure
-VERSION=`cat ./configure.ac | grep '^\s*AC_INIT(' | awk -F, '{ print $2 } ' | sed 's/\s*\[//' | sed 's/\]\s*//' | sed 's/\ //g'`
+VERSION=`cat ./configure.ac | grep '^\s*AC_INIT(' | awk -F, '{ print $2 } ' | sed 's/\s*\[//' | sed 's/\]\s*//' | sed 's/\ //g' | sed 's/)//g'`
 BUILT_PROGRAMS_DIR=.
 MAC_OS_VER=`sw_vers | grep ProductVersion | awk '{print $2}'`
 YEAR=`date | awk '{print $NF}'`
@@ -53,14 +59,14 @@ fi
 
 #ensure that we have some .pdf files in here
 if [ x`find ./ -name \*.pdf` == x"" ] ; then
-	echo "No PDF files (manual) found!"
-	exit 1 
+	echo "WARNING: No PDF files (manual) found!"
+	sleep 1
 fi
 
 #ensure that some .mo (translation files) are here
 if [ x`find ./ -name \*.mo` == x"" ] ; then
-	echo "No mo files (translations) found!"
-	exit 1 
+	echo "WARNING : No mo files (translations) found!"
+	sleep 1
 fi
 
 #--
diff --git a/packaging/mac/makeMacOSXApp b/packaging/mac/makeMacOSXApp
index 0fe5b5d..78dce71 100755
--- a/packaging/mac/makeMacOSXApp
+++ b/packaging/mac/makeMacOSXApp
@@ -1,5 +1,8 @@
 #!/bin/bash
 #
+#This is configured to be specific to the mac build machine. 
+# Do not assume that this will work on any given mac system
+
 export PATH=/opt/local/bin:$PATH:/opt//local/Library/Frameworks/wxWidgets.framework/Versions/wxWidgets/3.0/bin
 #This will make the mac .app bundle
 
@@ -16,15 +19,10 @@ if [ $1 = '--update-config=yes' ]; then
 		DISABLE_DEBUG="--disable-debug-checks"
 	fi
 
-#	CFLAGS="$CFLAGS -std=c++11"
-
-	CXX=g++ #"`wx-config --cxx` " \
-	CFLAGS="$CFLAGS -I/opt/local/include -I/usr/local/include " \
-	CXXFLAGS="$CXXFLAGS -I/opt/local/include -I/usr/local/include " \
-	LDFLAGS="$LDFLAGS -L/opt/local/lib -L/usr/local/lib" \
-	./configure $SHOULD_PARALLEL $DISABLE_DEBUG --enable-mgl2=yes \
-		--with-libpng-flag="-I/opt/local/include/libpng16" \
-		--with-libpng-link="-L/opt/local/lib/ -lpng16"
+	CFLAGS="$CFLAGS -I/opt/local/include " \
+	LDFLAGS="$LDFLAGS -L/opt/local/lib " \
+	CXXFLAGS="$CXXFLAGS -std=c++11 -D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_ -I/opt/local/include " \
+	./configure $SHOULD_PARALLEL $DISABLE_DEBUG
 
 	if [ $? -ne 0 ]; then
 		echo "Configure unsuccessful - exiting"
@@ -36,11 +34,16 @@ if [ $1 = '--update-config=yes' ]; then
 fi
 read -p "have you changed the makefile?" yn
 
-make -j8
+	CFLAGS="$CFLAGS -I/opt/local/include " \
+	LDFLAGS="$LDFLAGS -L/opt/local/lib " \
+	CXXFLAGS="$CXXFLAGS -std=c++11 -D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_ -I/opt/local/include " \
+	make -j8
+
+	if [ $? -ne 0 ]; then
+		echo "Make unsuccessful - exiting"
+		exit 1
+	fi
 
-if [ $? -ne 0 ]; then
-	echo "Make unsuccessful - exiting"
-	exit 1
 fi
 
 echo "Updating .app bundle..."
@@ -50,16 +53,15 @@ mkdir -p ./3Depict.app/Contents/libs/
 cp ./src/3Depict ./3Depict.app/Contents/MacOS/3Depict
 cp data/textures/tex-source/3Depict-icon.icns ./3Depict.app/Contents/Resources/3Depict-icon.icns
 touch ./3Depict.app/Contents/PkgInfo
-touch ./3Depict.app/Contents/info.plist
-#copy textures
+touch ./3Depict.app/Contents/Info.plist
+#copy all information from data folder
 cp ./data/* ./3Depict.app/Contents/Resources/
-cp ./data/textures/* ./3Depict.app/Contents/Resources/textures/
-cp ./data/textures/tex-source/3Depict-icon.icns ./3Depict.app/Contents/Resources
 
 
 #Update gettext translation
 #----
 echo "Updating translation files..."
+cd ./translations;./makeTranslations;cd ..
 for i in `ls ./translations/3Depict_*.mo`
 do
 	j=`echo $i | sed 's/.\/translations\/3Depict_//' | sed 's/.mo//'`
diff --git a/packaging/makeTarball.sh b/packaging/makeTarball.sh
index cca0bff..ef89b52 100755
--- a/packaging/makeTarball.sh
+++ b/packaging/makeTarball.sh
@@ -1,5 +1,7 @@
 #!/bin/bash
 MSG_FILE=tmp-messages
+#Should we use clang if available?
+USE_CLANG=0 
 
 if [ x`uname | grep Linux` != x"" ] ; then
 	NUM_PROCS=`cat /proc/cpuinfo | grep cores | uniq | sed 's/.*:\s*//'`
@@ -9,10 +11,12 @@ else
 fi
 
 
+HG_ROOT=`hg root`
 
+pushd $HG_ROOT
 
 if [ ! -f configure ] ; then
-	echo "Configure not found -- are you running this script from the top dir? " 
+	echo "Configure not found in root (hg root). Are you runing this from inside the repository?" 
 	exit 1
 fi
 
@@ -29,47 +33,84 @@ done
 #	- ubsan
 #-------
 #CONF_ARGS=("--enable-openmp-parallel" "--disable-debug-checks " " --enable-debug-checks " " --enable-openmp-parallel --disable-debug-checks " " --enable-ubsan --enable-openmp-parallel " " --enable-ubsan "  )
-#
-#for i in ${CONF_ARGS[*]}
-#do
-#	if [ -f Makefile ] ; then
-#		make distclean
-#	fi
-#
-#	./configure "$i"
-#
-#	if [ $? -ne 0 ] ; then
-#		echo "test-configuration failed to configure: arguments are $i"
-#		exit 1
-#	fi
-#
-#	if [ ! -f Makefile ] ; then
-#		echo "Configure claimed everything was OK, but did not create a Makefile"
-#		exit 1
-#	fi
-#
-#	make -j $NUM_PROCS
-#	if [ $? -ne 0 ] ; then
-#		echo "failed to build: arguments are $i"
-#		exit 1
-#	fi
-#
-#	#Check for unit test availability, and run them
-#	# where possible
-#	pushd src
-#	TEST_FLAG=`./3Depict --help  2>&1 | grep "\-\-test"`
-#	if [ x"$TEST_FLAG" != x"" ] ; then
-#		./3Depict -t
-##		if [ $? -ne 0 ] ; then
-##			echo "Unit tests failed for configure flag : $i" 
-###			exit 1
-##		fi
-#	fi
-#	popd	
-#      
-#	make distclean
-#done
-#-------
+
+for i in ${CONF_ARGS[*]}
+do
+	if [ -f Makefile ] ; then
+		make distclean
+	fi
+
+	./configure "$i"
+
+	if [ $? -ne 0 ] ; then
+		echo "test-configuration failed to configure: arguments are $i"
+		exit 1
+	fi
+
+	if [ ! -f Makefile ] ; then
+		echo "Configure claimed everything was OK, but did not create a Makefile"
+		exit 1
+	fi
+
+	make -j $NUM_PROCS
+	if [ $? -ne 0 ] ; then
+		echo "failed to build: arguments are $i"
+		exit 1
+	fi
+
+	#Check for unit test availability, and run them
+	# where possible
+	pushd src
+	TEST_FLAG=`./3Depict --help  2>&1 | grep "\-\-test"`
+	if [ x"$TEST_FLAG" != x"" ] ; then
+		./3Depict -t
+		if [ $? -ne 0 ] ; then
+			echo "Unit tests failed for configure flag : $i" 
+			exit 1
+		fi
+	fi
+	popd	
+      
+	make distclean
+done
+
+if  [ x"`which clang`" != x"" ]  && [ $USE_CLANG -ne 0 ] ; then
+	#OK, we have clang
+	CXX=clang++ C=clang CFLAGS=-std=c++11 CXXFLAGS=-std=c++11 ./configure 
+	if [ $? -ne 0 ] ; then
+		echo "configuration failed to configure with clang"
+		exit 1
+	fi
+	
+	if [ ! -f Makefile ] ; then
+		echo "Configure claimed everything was OK, but did not create a Makefile"
+		exit 1
+	fi
+
+	make -j $NUM_PROCS
+	if [ $? -ne 0 ] ; then
+		#If we fail to build with clang, we don't care. We just want to see how far we can get. 
+		# Clang seems to have a lot of problems at link time, 
+		# which we don't see with gcc.
+		echo "Failed to build with clang. Ignoring"
+	else	
+		pushd src/
+		./3Depict -t
+		if [ $? -ne 0 ] ; then
+			echo "Unit tests failed for configure flag : $i" 
+			exit 1
+		fi
+
+		popd
+		make distclean
+	fi	
+fi
+
+
+
+if [ ! -f compile ] ; then
+	touch compile
+fi
 
 ./configure
 if [ $? -ne 0 ] ; then
@@ -78,7 +119,14 @@ if [ $? -ne 0 ] ; then
 fi
 rm -rf autom4te.cache
 
-#Build tarball
+#Build program 
+make -j $NUM_PROCS
+if [ $? -ne 0 ] ; then
+	echo "make failed";
+	exit 1;
+fi
+
+#Build distributable tarball
 make dist -j $NUM_PROCS
 
 if [ $? -ne 0 ] ; then
@@ -312,3 +360,5 @@ if [ -f $MSG_FILE ] ; then
 
 	rm $MSG_FILE
 fi
+
+popd
diff --git a/packaging/mingw-debian-cross/bootstrap.sh b/packaging/mingw-debian-cross/bootstrap.sh
index bfbe5c9..f9e458b 100755
--- a/packaging/mingw-debian-cross/bootstrap.sh
+++ b/packaging/mingw-debian-cross/bootstrap.sh
@@ -4,6 +4,9 @@
 # and debian-like systems	
 # Note that building wx requires ~8GB of ram (or swap)
 
+# Its unlikely that this script will work first-time, or even second-time
+# you will need to do quite some work to be able to make this run
+
 #--- Determine which system we wish to build for
 #HOST_VAL=x86_64-w64-mingw32 #For mingw64 (windows 64 bit)
 #HOST_VAL=i686-w64-mingw32 #For mingw32 (Windows 32 bit)
@@ -72,23 +75,30 @@ if [ `id -u` -eq 0 ]; then
 	exit 1;
 fi
 #2) own patch for fixing wx-config's lack of sysroot support
-PATCHES_WXWIDGETS_PRE="wx_changeset_76890.diff"
+#PATCHES_WXWIDGETS_PRE="wx_changeset_76890.diff"
 PATCHES_WXWIDGETS_POST="wx-config-sysroot.patch"
 #1) Zlib no longer needs to explicitly link libc, and will fail if it tries
 PATCHES_ZLIB="zlib-no-lc.patch"
 #1) Override some configure patches to bypass false positive failures
 PATCHES_FTGL="ftgl-disable-doc"
 PATCHES_FTGL_POSTCONF="ftgl-override-configure-2"
+
+#Fix compilation error with iconv, where alias2_lookup function
+# is incorrectly declared as inline on non GNUC builds
+PATCHES_ICONV="iconv-fix-alias2.patch"
+
 #1) gettext-tools fails in various places, but we don't actually need it, so turn it off
 #2) gettext fails to correctly determine windows function call prefix.
 #   should be fixed for gettext > 0.18.1.1 ?
 #   https://lists.gnu.org/archive/html/bug-gettext/2012-12/msg00071.html
-PATCHES_GETTEXT="gettext-disable-tools gettext-fix-configure-versions"    #gettext-win32-prefix
+PATCHES_GETTEXT="gettext-fix-configure-versions"    #gettext-win32-prefix
 
 PATCHES_GLEW="glew-makefile.base"
 
-PATCHES_MATHGL="mathgl-openmp-linker-flag"
-PATCH_LIST="$PATCHES_WXWIDGETS_PRE $PATCHES_WXWIDGETS_POST $PATCHES_GSL $PATCHES_ZLIB $PATCHES_LIBPNG $PATCHES_GETTEXT $PATCHES_FTGL $PATCHES_GLEW $PATCHES_MATHGL $PATCHES_FTGL_POSTCONF"
+PATCHES_MATHGL="mathgl-openmp-linker-flag mathgl-disable-things"
+PATCHES_QHULL="qhull-ptr.patch"
+PATCH_LIST="$PATCHES_WXWIDGETS_POST $PATCHES_GSL $PATCHES_ZLIB $PATCHES_LIBPNG $PATCHES_GETTEXT $PATCHES_FTGL $PATCHES_GLEW $PATCHES_MATHGL $PATCHES_FTGL_POSTCONF $PATCHES_ICONV $PATCHES_QHULL"
+
 
 BUILD_STATUS_FILE="$BASE/build-status"
 PATCH_STATUS_FILE="$BASE/patch-status"
@@ -149,13 +159,13 @@ function grabDeps()
 {
 	pushd deps 2>/dev/null
 
-	DEB_PACKAGES="expat freetype ftgl gettext gsl libpng libxml2 mathgl qhull tiff wxwidgets3.0 zlib glew libvigraimpex"
+	DEB_PACKAGES="qhull expat freetype ftgl gettext gsl libpng libxml2 mathgl tiff zlib glew libvigraimpex"
 	if [ x$DIST_NAME == x"Ubuntu" ] || [ x$DIST_NAME == x"LinuxMint" ]  ; then 
        		LIBJPEGNAME="libjpeg6b"
 	else
 		#Libjpeg seems to be forked/renamed very frequently in debian
 		# Likely a new libjpeg will need to be picked each time this script is run
-		LIBJPEGNAME="libjpeg-turbo"
+		LIBJPEGNAME="libjpeg9"
 	fi
 	DEB_PACKAGES="$DEB_PACKAGES $LIBJPEGNAME"
 
@@ -503,7 +513,7 @@ function build_libxml2()
 
 	#Modifications
 	#	Disable python, because sys/select.h is not in mingw
-	./configure --host=$HOST_VAL --without-python --without-html --without-http --without-ftp --without-push --without-writer --without-push --without-legacy --without-xpath --without-iconv  --enable-shared=yes --enable-static=no --prefix=/ || { echo "Libxml2 configure failed"; exit 1; } 
+	./configure --host=$HOST_VAL --without-lzma --without-python --without-html --without-http --without-ftp --without-push --without-writer --without-push --without-legacy --without-xpath --without-iconv  --enable-shared=yes --enable-static=no --prefix=/ || { echo "Libxml2 configure failed"; exit 1; } 
 
 	make -j $NUM_PROCS || { echo "libxml2 build failed"; exit 1; } 
 	
@@ -548,6 +558,8 @@ function build_libjpeg()
 
 	make clean
 
+	autoconf
+
 	./configure --host=$HOST_VAL --enable-shared --disable-static --prefix=/ || { echo "$NAME configure failed"; exit 1; } 
 
 	make -j $NUM_PROCS || { echo "$NAME build failed"; exit 1; } 
@@ -597,7 +609,7 @@ function build_libtiff()
 	echo ${NAME} >> $BUILD_STATUS_FILE
 }
 
-function build_qhull()
+function build_qhull2012()
 {
 	NAME="libqhull"
 	ISBUILT_ARG=${NAME}
@@ -616,6 +628,116 @@ function build_qhull()
 
 	make clean
 
+	# We have an internal COMPILE_ASSERT test for ptr_intT length
+	#if using win64, then ensure that there is only the correct long long version
+	# of the pointer
+	#if [ `egrep "typedef .* ptr_intT" src/libqhull/mem.h | wc -l` -ne 1 ] ; then
+	#	echo "There appears to be multiple ptr_intT types in qhull's mem.h. Qhull normally picks the wrong one. Aborting- please fix"
+	#	exit 1
+	#fi
+
+	sed -i "s/ gcc$/${HOST_VAL}-gcc/" Makefile
+	sed -i "s/ g++$/${HOST_VAL}-g++/" Makefile
+
+	make SO="dll" -j $NUM_PROCS 
+	find ./ -name \*dll -exec cp {} ${BASE}/bin/	
+	make SO="dll" -j $NUM_PROCS || { echo "qhull build failed"; exit 1; } 
+	make install DESTDIR="$BASE"|| { echo "qhull install failed"; exit 1; } 
+
+	popd >/dev/null
+	popd >/dev/null
+
+	ln -s ${BASE}/include/libqhull ${BASE}/include/qhull
+
+
+
+	FIX_LA_FILE_ARG=libqhull
+	fix_la_file
+	echo ${NAME} >> $BUILD_STATUS_FILE
+}
+
+function build_qhull2015()
+{
+	NAME="libqhull"
+	ISBUILT_ARG=${NAME}
+	isBuilt
+	if [ $ISBUILT -eq 1 ] ; then
+		return;
+	fi
+	
+	pushd deps >/dev/null
+	pushd qhull-* >/dev/null
+	
+	if [ $? -ne 0 ] ; then
+		echo "qhull dir missing, or duplicated?"
+		exit 1
+	fi
+
+	#delete the qhull directories that do NOT correspond to the version of qhull we want to build
+	rm -rf src/libqhull src/libqhullcpp src/libqhullstatic*
+
+	APPLY_PATCH_ARG="$PATCHES_QHULL"
+	applyPatches
+	make clean
+
+	cp ../../patches/qhull2015-cmakefile-replacement CMakeLists.txt
+
+	# TODO: Technically, deleting CMakeCache doesn't solve all caching problems. Cached data can remain elsewhere
+	# This seems to stem from cmakes stubborn approach of "we only allow out-of-source-tree builds".
+	# This is annoying, as in-tree building is very common, and natural for small projects. It also allows incremental building.
+	#  IMHO, once I manually alter a cmakefile, the cache should fucking well work out that it is out-of-date, as I keep getting nasty suprises.
+	# https://cmake.org/Bug/view.php?id=14820 .
+	rm -f CMakeCache.txt
+	cmake -DCMAKE_INSTALL_PREFIX="$BASE" -DCMAKE_TOOLCHAIN_FILE=../../patches/cmake-toolchain$BITS_VAL 
+
+
+	#TODO: Better test (using c)
+	#if using win64, then ensure that there is only the correct long long version
+	# of the pointer
+	if [ `egrep "typedef .* ptr_intT" src/libqhull_r/mem_r.h | wc -l` -ne 1 ] ; then
+		echo "There appears to be multiple ptr_intT types in qhull's mem.h. Qhull normally picks the wrong one. Aborting- please fix"
+		exit 1
+	fi
+
+	sed -i "s/ gcc$/${HOST_VAL}-gcc/" Makefile
+	sed -i "s/ g++$/${HOST_VAL}-g++/" Makefile
+
+	make SO="dll" -j $NUM_PROCS 
+	find ./ -name \*dll -exec cp {} ${BASE}/bin/	
+	make SO="dll" -j $NUM_PROCS || { echo "qhull build failed"; exit 1; } 
+	make install DESTDIR="$BASE"|| { echo "qhull install failed"; exit 1; } 
+
+	popd >/dev/null
+	popd >/dev/null
+
+	ln -s ${BASE}/include/libqhull ${BASE}/include/qhull
+
+
+
+	FIX_LA_FILE_ARG=libqhull
+	fix_la_file
+	echo ${NAME} >> $BUILD_STATUS_FILE
+}
+
+function build_qhull2009()
+{
+	NAME="libqhull"
+	ISBUILT_ARG=${NAME}
+	isBuilt
+	if [ $ISBUILT -eq 1 ] ; then
+		return;
+	fi
+	
+	pushd deps >/dev/null
+	pushd qhull-* >/dev/null
+	
+	if [ $? -ne 0 ] ; then
+		echo "qhull dir missing, or duplicated?"
+		exit 1
+	fi
+
+	./configure --host=$HOST_VAL --enable-shared --disable-static --prefix=/ || { echo "$NAME configure failed"; exit 1; } 
+
 	sed -i "s/ gcc$/${HOST_VAL}-gcc/" Makefile
 	sed -i "s/ g++$/${HOST_VAL}-g++/" Makefile
 
@@ -634,6 +756,38 @@ function build_qhull()
 	echo ${NAME} >> $BUILD_STATUS_FILE
 }
 
+#FIXME: This does not work. Qhull uses a strange combination of cmake
+# and hand makefiles, so propagating correct cross-compiling 
+# parameters is quite tricky
+function build_qhull2015()
+{
+	NAME="libqhull"
+	ISBUILT_ARG=${NAME}
+	isBuilt
+	if [ $ISBUILT -eq 1 ] ; then
+		return;
+	fi
+	
+	pushd deps >/dev/null
+	pushd qhull-* >/dev/null
+	
+	if [ $? -ne 0 ] ; then
+		echo "qhull dir missing, or duplicated?"
+		exit 1
+	fi
+
+	rm -f CMakeCache.txt
+	cmake -DCMAKE_INSTALL_PREFIX="$BASE" -DCMAKE_TOOLCHAIN_FILE=../../patches/cmake-toolchain$BITS_VAL 
+
+	make -j $NUM_PROCS || exit 1
+
+	make install	
+
+	popd >/dev/null
+	popd >/dev/null
+
+	echo ${NAME} >> $BUILD_STATUS_FILE
+}
 
 function build_expat()
 {
@@ -697,6 +851,7 @@ function build_gsl()
 	APPLY_PATCH_ARG=$PATCHES_GSL
 	applyPatches
 
+
 	./configure --host=$HOST_VAL --enable-shared --disable-static --prefix=/ || { echo "gsl configure failed"; exit 1; } 
 
 	make -j $NUM_PROCS || { echo "gsl build failed"; exit 1; } 
@@ -723,27 +878,31 @@ function build_wx()
 	fi
 	
 	pushd deps >/dev/null
-	pushd wxwidgets[23].[0-9]-* >/dev/null
+	pushd wx[Ww]idgets* >/dev/null
        	
 	if [ $? -ne 0 ] ; then
 		echo "wxwidgets dir missing, or duplicated?"
 		exit 1
 	fi
+	WX_VER=`grep "WX_RELEASE =" Makefile`
+
+	if [ x"${WX_VER}" == x"3.0" ] ; then
+		echo "WX needs to be at least 3.1, but is 3.0..."
+		exit 1
+	fi
 
 	make clean
 
-	APPLY_PATCH_ARG=$PATCHES_WXWIDGETS_PRE
-	applyPatches
 	WX_DISABLE="--disable-compat26 --disable-compat28 --disable-ole --disable-dataobj --disable-ipc --disable-apple_ieee --disable-zipstream --disable-protocol_ftp --disable-mshtmlhelp --disable-aui --disable-mdi --disable-postscript --disable-datepick --disable-splash --disable-wizarddlg --disable-joystick --disable-loggui --disable-debug --disable-logwin --disable-logdlg --disable-tarstream --disable-fs_archive --disable-fs_inet --disable-fs_zip --disable-snglinst --disable-sound --disabl [...]
 
 	./configure --host=$HOST_VAL --enable-shared --disable-static --with-opengl --enable-unicode --without-regex --prefix=/ || { echo "wxwidgets configure failed"; exit 1; } 
 
-	#TODO: Where is this coming from ???
+       #TODO: Where is this coming from ???
 	for i in `find ./ -name Makefile | grep -v samples | grep -v wxPython`
 	do
 		sed -i "s at -luuid-L@ -luuid -L@" $i
 	done	
-	
+       
 	make -j $NUM_PROCS || { echo "wxwidgets build failed"; exit 1; } 
 	make install DESTDIR="$BASE"|| { echo "wxwidgets install failed"; exit 1; } 
 
@@ -753,17 +912,24 @@ function build_wx()
 	popd >/dev/null
 
 	pushd ./bin/
-	unlink wx-config
+
+	if [ -l wx-config ] ; then
+		unlink wx-config
+	fi
 
 
 	#Search for the wx-config file. It get installed into /lib/wx, but has
 	# unusual naming conventions
 	WX_CONFIG_FILE=`find ${BASE}/lib/wx/config/ -type f -executable -name \*release-\*`
-	if [ x$WX_CONFIG_FILE == x"" ] ; then
-		WX_CONFIG_FILE=`find ${BASE}/lib/wx/config/ -type f  -executable -name \*-unicode-\*`
+	if [ x"$WX_CONFIG_FILE" == x"" ] ; then
+		WX_CONFIG_FILE=`find ${BASE}/lib/wx/config/ -type f  -executable -name \*-unicode-\*3.1`
 	fi
 
-	if [ x$WX_CONFIG_FILE == x"" ] ; then
+	if [ x"$WX_CONFIG_FILE" == x"" ] ; then
+		WX_CONFIG_FILE=`find ${BASE}/lib/wx/config/ -type f  -executable -name x\*mingw32-msw-unicode-\*`
+	fi	
+
+	if [ x"$WX_CONFIG_FILE" == x"" ] ; then
 		echo "Couldn't find the wx-config script."
 		exit 1
 	fi
@@ -777,9 +943,15 @@ function build_wx()
 	popd
 
 	pushd ./lib/
-	ln -s wx-3.0/wx/ wx
+	ln -s wx-${WX_VER}/wx/ wx
 	popd
 
+	pushd ./include/wx-${WX_VER}/wx/msw/
+	if [ x$BITS_VAL == 64 ] ; then
+		cp amd64.manifest wx.manifest
+	fi
+	popd	
+
 
 	echo ${NAME} >> $BUILD_STATUS_FILE
 
@@ -805,7 +977,7 @@ function build_freetype()
 
 	pushd freetype-[0-9]*
 	make clean
-	./configure --host=$HOST_VAL --enable-shared --disable-static --without-png --prefix=/ || { echo "freetype configure failed"; exit 1; } 
+	./configure --host=$HOST_VAL --enable-shared --disable-static --without-png --with-harfbuzz=no --prefix=/ || { echo "freetype configure failed"; exit 1; } 
 
 	make -j $NUM_PROCS || { echo "freetype build failed"; exit 1; } 
 	
@@ -847,7 +1019,12 @@ function build_libiconv()
 		exit 1
 	fi
 
+	APPLY_PATCH_ARG=$PATCHES_ICONV
+	applyPatches
+
 	make clean
+
+
 	./configure --host=$HOST_VAL --enable-shared --disable-static --prefix=/ || { echo "libiconv configure failed"; exit 1; } 
 
 	make -j $NUM_PROCS || { echo "libiconv build failed"; exit 1; } 
@@ -892,8 +1069,17 @@ function build_gettext()
 
 	#FIXME: I had to copy the .lib, .la and .a files manually
 	# I don't know why the makefile does not do this.
-	cp gettext-runtime/intl/.libs/libintl.{la,lib,a} ${BASE}/lib/ || {  echo "semi-manual copy of libintl failed"; exit 1; } 
-	
+	CPSUCCESS=0
+	for i in `ls gettext-runtime/intl/.libs/libintl*.{la,lib,a,dll}`
+	do
+		cp $i ${BASE}/lib/ 
+		if [ $? -eq 0 ] ; then
+			CPSUCCESS=1;
+		fi
+	done
+	if [ $CPSUCCESS -eq 0 ] ; then	
+		{  echo "semi-manual copy of libintl failed"; exit 1; } 
+	fi
 	popd >/dev/null
 	popd >/dev/null
 	
@@ -930,6 +1116,7 @@ function build_mathgl()
 		exit 1
 	fi
 
+	rm -f CMakeCache.txt
 	LIBS=-lpng cmake -Denable-gsl="yes" -Denable-mpi="no"  -DCMAKE_INSTALL_PREFIX="$BASE" -DCMAKE_TOOLCHAIN_FILE=../../patches/cmake-toolchain$BITS_VAL -DPNG_PNG_INCLUDE_DIR=${BASEDIR}/include/
 
 	make -j $NUM_PROCS
@@ -968,7 +1155,7 @@ function build_libvigra()
 	fi
 	make clean
 
-	APPLY_PATCH_ARG=$PATCHES_MATHGL
+	APPLY_PATCH_ARG=$PATCHES_LIBVIGRA
 	applyPatches
 
 	cmake -DCMAKE_INSTALL_PREFIX="$BASE" -DCMAKE_TOOLCHAIN_FILE=../../patches/cmake-toolchain$BITS_VAL -DPNG_PNG_INCLUDE_DIR=${BASEDIR}/include/
@@ -1037,9 +1224,16 @@ function build_ftgl()
 	find ./ -name Makefile -exec sed -i "s at -I//@-I${BASE}/@" {} \;
 	find ./ -name Makefile -exec sed -i "s at -L//@-L${BASE}/@" {} \;
 
-	make -j $NUM_PROCS || { echo "ftgl build failed"; exit 1; } 
+	LIBS="-lfreetype -lz" make -j $NUM_PROCS || { echo "ftgl build failed"; exit 1; } 
 	
-	DESTDIR="$BASE" make install | { echo "ftgl install failed"; exit 1; } 
+	DESTDIR="$BASE" make install || { echo "ftgl install failed"; exit 1; } 
+
+
+	#HACK: Ftgl doesn't install the dll correctly. Just do it by hand
+	cp src/.libs/libftgl-*dll ${BASE}/lib/ || { echo "FTGL dll could not be installed." ; exit 1; }
+	pushd $BASE/lib/
+	ln -s libftgl-*dll libftgl.dll
+	popd > /dev/null
 
 	popd >/dev/null
 	popd >/dev/null
@@ -1136,18 +1330,26 @@ function build_3Depict()
 	make distclean
 
 
-	CONF_FLAG="--host=$HOST_VAL --with-libqhull-link=-lqhull_p"
+	autoreconf
+	automake --add-missing
+
+	CONF_FLAG="--host=$HOST_VAL --with-libqhull-link=-lqhull"
 	if [ $IS_RELEASE -ne 0 ] ; then
 		CONF_FLAG="$CONF_FLAG --disable-debug-checks --enable-openmp-parallel"
 	fi
 
-	FTGL_CFLAGS="-I${BASE}/include/freetype/" CFLAGS="$CFLAGS -DUNICODE" CPPFLAGS="${CPPFLAGS} -DUNICODE" ./configure  $CONF_FLAG
+
+	FTGL_CFLAGS="-I${BASE}/include/freetype2/" CFLAGS="$CFLAGS -DUNICODE -Dqh_QHpointer" CPPFLAGS="${CPPFLAGS} -DUNICODE -Dqh_QHpointer" ./configure  $CONF_FLAG 
 
 	if [ $? -ne 0 ] ; then
 		echo "Failed 3Depict configure"
 		exit 1
 	fi
 
+	#comment out the rpl_malloc and rpl_realloc calls
+	sed -i 's@^#define \([a-z]*\) rpl_@//#define \1 rpl_@' config.h
+
+
 	#sanity check that windres is activated
 	if [ x`grep HAVE_WINDRES_TRUE config.log | grep '#' ` != x"" ] ; then
 		echo "Windres appears to be commented out. Shouldn't be for windows builds"
@@ -1191,7 +1393,8 @@ function build_3Depict()
 	#HACK - find all -I// and -L// and replace them with something sane
 	find ./ -name Makefile -exec sed -i "s at -I//@-I${BASE}/@" {} \;
 	find ./ -name Makefile -exec sed -i "s at -L//@-L${BASE}/@" {} \;
-	
+
+	#Actually perform build	
 	make -j$NUM_PROCS
 	if [ $? -ne 0 ] ; then
 		echo "Failed 3Depict build"
@@ -1224,6 +1427,11 @@ function build_3Depict()
 #Build the nsis package
 function make_package()
 {
+	if [ x"$HOST_EXT" != x"win64" ] ; then
+		echo "WRONG HOST EXT!"
+		exit 1
+	fi
+
 	pushd ./code/3Depict 2> /dev/null
 
 	#Check that the PDF manual has been built
@@ -1270,7 +1478,7 @@ function make_package()
 	 
 
 	echo -n " Copying dll files... "
-	SYSTEM_DLLS="(ADVAPI32.dll|COMCTL32.DLL|COMDLG32.DLL|GDI32.dll|KERNEL32.dll|ole32.dll|OLEAUT32.dll|RPCRT4.dll|SHELL32.DLL|USER32.dll|WINMM.DLL|WINSPOOL.DRV|WSOCK32.DLL|GLU32.dll|OPENGL32.dll|msvcrt.dll|WS2_32.dll)"
+	SYSTEM_DLLS="(ADVAPI32.dll|COMCTL32.DLL|COMDLG32.DLL|GDI32.dll|KERNEL32.dll|ole32.dll|OLEAUT32.dll|RPCRT4.dll|SHELL32.DLL|USER32.dll|WINMM.DLL|WINSPOOL.DRV|WSOCK32.DLL|GLU32.dll|OPENGL32.dll|msvcrt.dll|WS2_32.dll|SHLWAPI.dll|VERSION.dll)"
 
 	DLL_FILES=`${HOST_VAL}-objdump -x src/3Depict.exe | grep 'DLL Name:' | awk '{print $3}' | egrep -i -v ${SYSTEM_DLLS}`
 	FOUND_DLLS=""
@@ -1372,7 +1580,7 @@ function make_package()
 		TARGET_FILE=3Depict-${VERSION}-${HOST_EXT}-debug.exe
 	fi
 	
-	mv Setup.exe  $TARGET_FILE
+	mv 3Depict-setup.exe  $TARGET_FILE
 	echo "File written to : `pwd`/$TARGET_FILE"
 	echo "-------------------"
 	
@@ -1410,6 +1618,7 @@ case ${HOST_VAL}  in
 	;;
 esac
 
+
 #install the compiler
 install_mingw
 #---
@@ -1441,7 +1650,8 @@ build_libpng
 build_libjpeg
 build_libxml2
 build_gsl
-build_qhull
+build_qhull2012
+#build_qhull2015
 build_expat
 build_freetype
 build_libiconv
diff --git a/packaging/mingw-debian-cross/patches/gettext-disable-tools b/packaging/mingw-debian-cross/patches/gettext-disable-tools
index 70503f6..0c847a9 100644
--- a/packaging/mingw-debian-cross/patches/gettext-disable-tools
+++ b/packaging/mingw-debian-cross/patches/gettext-disable-tools
@@ -1,6 +1,6 @@
-diff -r decc1317356a Makefile.am
---- a/Makefile.am	Sun Nov 17 14:47:59 2013 +0100
-+++ b/Makefile.am	Sun Nov 17 14:50:27 2013 +0100
+diff -r fc8ef26fbd29 Makefile.am
+--- a/Makefile.am	Fri Apr 22 23:17:46 2016 +0100
++++ b/Makefile.am	Fri Apr 22 23:20:55 2016 +0100
 @@ -19,7 +19,7 @@
  AUTOMAKE_OPTIONS = 1.5 gnu no-dependencies
  ACLOCAL_AMFLAGS = -I m4
@@ -8,9 +8,9 @@ diff -r decc1317356a Makefile.am
 -SUBDIRS = gnulib-local gettext-runtime gettext-tools
 +SUBDIRS = gnulib-local gettext-runtime
  
- EXTRA_DIST = \
-   version.sh DEPENDENCIES PACKAGING HACKING ChangeLog.0 autogen.sh \
-@@ -28,10 +28,12 @@
+ changelog_etc = \
+   gettext-runtime/ChangeLog.0 \
+@@ -57,10 +57,12 @@
    m4/libtool.m4
  
  # Additional dependencies for configure, due to the use of autoconf --trace.
@@ -24,19 +24,19 @@ diff -r decc1317356a Makefile.am
  	cmp -s gettext-runtime/po/Makefile.in.in gettext-tools/po/Makefile.in.in
  	cmp -s gettext-runtime/po/Rules-quot gettext-tools/po/Rules-quot
  	cmp -s gettext-runtime/po/boldquot.sed gettext-tools/po/boldquot.sed
-diff -r decc1317356a Makefile.in
---- a/Makefile.in	Sun Nov 17 14:47:59 2013 +0100
-+++ b/Makefile.in	Sun Nov 17 14:50:27 2013 +0100
-@@ -298,7 +298,7 @@
+diff -r fc8ef26fbd29 Makefile.in
+--- a/Makefile.in	Fri Apr 22 23:17:46 2016 +0100
++++ b/Makefile.in	Fri Apr 22 23:20:55 2016 +0100
+@@ -312,7 +312,7 @@
  top_srcdir = @top_srcdir@
  AUTOMAKE_OPTIONS = 1.5 gnu no-dependencies
  ACLOCAL_AMFLAGS = -I m4
 -SUBDIRS = gnulib-local gettext-runtime gettext-tools
-+SUBDIRS = gnulib-local gettext-runtime 
- 
- # DJGPP port.
- 
-@@ -769,6 +769,8 @@
++SUBDIRS = gnulib-local gettext-runtime
+ changelog_etc = \
+   gettext-runtime/ChangeLog.0 \
+   gettext-runtime/doc/ChangeLog.0 \
+@@ -839,6 +839,8 @@
  
  # Verify that some files are the same.
  distcheck-hook:
diff --git a/packaging/mingw-debian-cross/patches/glew-makefile b/packaging/mingw-debian-cross/patches/glew-makefile
index 30e6b8c..bf34418 100644
--- a/packaging/mingw-debian-cross/patches/glew-makefile
+++ b/packaging/mingw-debian-cross/patches/glew-makefile
@@ -1,26 +1,29 @@
-diff -r 9bbbd8b43e5b Makefile
---- a/Makefile	Sun Jun 29 17:24:13 2014 +0100
-+++ b/Makefile	Sun Jun 29 17:25:52 2014 +0100
-@@ -28,19 +28,13 @@
+diff -r ec3d3c4b0904 Makefile
+--- a/Makefile	Sat Apr 23 00:47:08 2016 +0100
++++ b/Makefile	Sat Apr 23 00:48:25 2016 +0100
+@@ -28,20 +28,14 @@
  ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  ## THE POSSIBILITY OF SUCH DAMAGE.
  
 -include config/version
 +include config/Makefile.mingw
++
  
  SHELL = /bin/sh
 -SYSTEM ?= $(shell config/config.guess | cut -d - -f 3 | sed -e 's/[0-9\.]//g;')
 -SYSTEM.SUPPORTED = $(shell test -f config/Makefile.$(SYSTEM) && echo 1)
-+SYSTEM = i686-w64-mingw32
  
 -ifeq ($(SYSTEM.SUPPORTED), 1)
 -include config/Makefile.$(SYSTEM)
 -else
 -$(error "Platform '$(SYSTEM)' not supported")
 -endif
- 
+-
+-GLEW_PREFIX ?= /usr
 -GLEW_DEST ?= /usr
-+GLEW_DEST ?= /home/pcuser/mingw32
++SYSTEM = x86_64-w64-mingw32
++GLEW_PREFIX ?= /home/pcuser/mingw64
++GLEW_DEST ?= /home/pcuser/mingw64
  BINDIR    ?= $(GLEW_DEST)/bin
  LIBDIR    ?= $(GLEW_DEST)/lib
  INCDIR    ?= $(GLEW_DEST)/include/GL
diff --git a/packaging/mingw-debian-cross/patches/glew-makefile.base b/packaging/mingw-debian-cross/patches/glew-makefile.base
index ae6b8d2..dda9222 100644
--- a/packaging/mingw-debian-cross/patches/glew-makefile.base
+++ b/packaging/mingw-debian-cross/patches/glew-makefile.base
@@ -1,25 +1,28 @@
-diff -r 9bbbd8b43e5b Makefile
---- a/Makefile	Sun Jun 29 17:24:13 2014 +0100
-+++ b/Makefile	Sun Jun 29 17:25:52 2014 +0100
-@@ -28,19 +28,13 @@
+diff -r ec3d3c4b0904 Makefile
+--- a/Makefile	Sat Apr 23 00:47:08 2016 +0100
++++ b/Makefile	Sat Apr 23 00:48:25 2016 +0100
+@@ -28,20 +28,14 @@
  ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  ## THE POSSIBILITY OF SUCH DAMAGE.
  
 -include config/version
 +include config/Makefile.mingw
++
  
  SHELL = /bin/sh
 -SYSTEM ?= $(shell config/config.guess | cut -d - -f 3 | sed -e 's/[0-9\.]//g;')
 -SYSTEM.SUPPORTED = $(shell test -f config/Makefile.$(SYSTEM) && echo 1)
-+SYSTEM = HOST_VAL
  
 -ifeq ($(SYSTEM.SUPPORTED), 1)
 -include config/Makefile.$(SYSTEM)
 -else
 -$(error "Platform '$(SYSTEM)' not supported")
 -endif
- 
+-
+-GLEW_PREFIX ?= /usr
 -GLEW_DEST ?= /usr
++SYSTEM = HOST_VAL
++GLEW_PREFIX ?= BASEDIR
 +GLEW_DEST ?= BASEDIR
  BINDIR    ?= $(GLEW_DEST)/bin
  LIBDIR    ?= $(GLEW_DEST)/lib
diff --git a/packaging/mingw-debian-cross/windows-installer.nsi b/packaging/mingw-debian-cross/windows-installer.nsi
index 1f1a358..096855e 100755
--- a/packaging/mingw-debian-cross/windows-installer.nsi
+++ b/packaging/mingw-debian-cross/windows-installer.nsi
@@ -2,7 +2,7 @@
 
 ; HM NIS Edit Wizard helper defines
 !define PRODUCT_NAME "3Depict"
-!define PRODUCT_VERSION "0.0.18"
+!define PRODUCT_VERSION "0.0.19"
 !define PRODUCT_PUBLISHER "D. Haley, A. Ceguerra"
 !define PRODUCT_WEB_SITE "http://threedepict.sourceforge.net"
 !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\3Depict.exe"
@@ -19,8 +19,11 @@ SetCompressorDictSize 64
 
 ; MUI Settings
 !define MUI_ABORTWARNING
-!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
-!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+!define MUI_ICON "src/myAppIcon.ico"
+!define MUI_UNICON "src/myAppIcon.ico"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "data/textures/tex-source/3Depict-icon-hires.png"
+!define MUI_HEADERIMAGE_RIGHT
 
 ; Welcome page
 !insertmacro MUI_PAGE_WELCOME
@@ -43,7 +46,7 @@ SetCompressorDictSize 64
 ; MUI end ------
 
 Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
-OutFile "Setup.exe"
+OutFile "3Depict-setup.exe"
 InstallDir "$PROGRAMFILES64\3Depict"
 InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
 ShowInstDetails show
diff --git a/src/3Depict.cpp b/src/3Depict.cpp
index ad1b583..e7a109e 100644
--- a/src/3Depict.cpp
+++ b/src/3Depict.cpp
@@ -21,6 +21,9 @@
 #include <wx/cmdline.h>
 #include <wx/filename.h>
 #include <wx/stdpaths.h>
+#ifndef DEBUG
+#include <wx/log.h>
+#endif
 
 #ifdef __APPLE__
 #include "CoreFoundation/CoreFoundation.h"
@@ -39,11 +42,12 @@ enum
 
 class threeDepictApp: public wxApp {
 private:
-#ifndef DEBUG
-	//instance of this class suppresses internal wx error dialogs.
-	// these are a nuisance in release code, as recovered errors often annoy the user
-	wxLogNull nullifyLogs;
-#endif
+
+
+	void redirectWxLogging();
+
+	std::ofstream debugLogStream;
+
 
 	MainWindowFrame* MainFrame ;
 	wxArrayString commandLineFiles;
@@ -101,11 +105,29 @@ threeDepictApp::threeDepictApp()
 {
        	MainFrame=0;usrLocale=0;
 	dontLoad=false;
-#ifndef DEBUG
+	
 	//Wx 2.9 and up now has assertions auto-enabled. 
 	//Disable for release builds
+#ifndef DEBUG
 	wxSetAssertHandler(NULL);
 #endif
+	redirectWxLogging();
+}
+
+void threeDepictApp::redirectWxLogging()
+{
+	//Disable user visible logging on the main thread, this can throw up "error dialogs"
+	// to the user that seem to be false positives, such as "Error: Sucess" type messages
+	// ihstead try first to log to file. If that fails, just disable it
+        wxStandardPaths &paths = wxStandardPaths::Get();
+	wxString filePath = paths.GetDocumentsDir();
+	filePath+=("/.")+string(PROGRAM_NAME) + string("log.txt");
+	debugLogStream.open(filePath.c_str());
+
+	if(!debugLogStream)
+		wxLog::EnableLogging(false);	
+	else
+		wxLog::SetActiveTarget(new wxLogStream(&debugLogStream));
 }
 
 int threeDepictApp::OnExit()
diff --git a/src/Makefile.am b/src/Makefile.am
index 363a44f..de622e3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,7 +36,7 @@ FILTER_FILES = backend/filters/allFilter.cpp backend/filters/filterCommon.cpp \
 		backend/filters/spectrumPlot.cpp backend/filters/transform.cpp \
 		backend/filters/externalProgram.cpp backend/filters/ionClip.cpp \
 		backend/filters/ionColour.cpp backend/filters/boundingBox.cpp  \
-		backend/filters/compositionProfile.cpp backend/filters/spatialAnalysis.cpp \
+		backend/filters/profile.cpp backend/filters/spatialAnalysis.cpp \
 		backend/filters/clusterAnalysis.cpp backend/filters/ionInfo.cpp \
 		backend/filters/annotation.cpp backend/filters/geometryHelpers.cpp \
 		backend/filters/algorithms/binomial.cpp  backend/filters/algorithms/mass.cpp  
@@ -46,20 +46,21 @@ FILTER_HEADER_FILES = backend/filters/allFilter.h backend/filters/filterCommon.h
 		backend/filters/rangeFile.h backend/filters/voxelise.h backend/filters/spectrumPlot.h \
 	       	backend/filters/transform.h backend/filters/externalProgram.h backend/filters/ionClip.h \
 		backend/filters/ionColour.h backend/filters/boundingBox.h  \
-		backend/filters/compositionProfile.h backend/filters/spatialAnalysis.h \
+		backend/filters/profile.h backend/filters/spatialAnalysis.h \
 		backend/filters/clusterAnalysis.h backend/filters/ionInfo.h \
 		backend/filters/annotation.h backend/filters/geometryHelpers.h \
 		backend/filters/algorithms/binomial.h backend/filters/algorithms/mass.h
 
 BACKEND_SOURCE_FILES = backend/animator.cpp backend/filtertreeAnalyse.cpp backend/filtertree.cpp \
 		     	backend/APT/ionhit.cpp backend/APT/APTFileIO.cpp backend/APT/APTRanges.cpp backend/APT/abundanceParser.cpp \
+			backend/APT/vtk.cpp \
 			backend/filters/algorithms/K3DTree.cpp backend/filters/algorithms/K3DTree-mk2.cpp\
 			backend/filter.cpp backend/filters/algorithms/rdf.cpp \
 		       backend/viscontrol.cpp backend/state.cpp backend/plot.cpp  backend/configFile.cpp 
 
 BACKEND_HEADER_FILES =  backend/animator.h backend/filtertreeAnalyse.h backend/filtertree.h\
 			backend/APT/ionhit.h backend/APT/APTFileIO.h backend/APT/APTRanges.h backend/APT/abundanceParser.h \
-			backend/filters/algorithms/K3DTree.h backend/filters/algorithms/K3DTree-mk2.h \
+			backend/APT/vtk.h backend/filters/algorithms/K3DTree.h backend/filters/algorithms/K3DTree-mk2.h \
 			backend/filter.h backend/filters/algorithms/rdf.h \
 			backend/viscontrol.h backend/state.h backend/plot.h backend/configFile.h \
 		        backend/tree.hh
diff --git a/src/backend/APT/APTFileIO.cpp b/src/backend/APT/APTFileIO.cpp
index 62ae9a6..7b3d54d 100644
--- a/src/backend/APT/APTFileIO.cpp
+++ b/src/backend/APT/APTFileIO.cpp
@@ -473,7 +473,7 @@ unsigned int limitLoadTextFile(unsigned int maxCols,
 	//we define this as the split value being able to generate 
 	//1) Enough data to make interpretable columns
 	//2) Enough columns that can be interpreted.
-	while(!CFile.eof() && curPos < maxPos)
+	while(CFile.good() && !CFile.eof() && curPos < maxPos)
 	{
 		string s;
 		curPos = CFile.tellg();
@@ -505,7 +505,7 @@ unsigned int limitLoadTextFile(unsigned int maxCols,
 	}	
 
 	//could not find any data.. only header.
-	if(CFile.eof() || curPos >=maxPos)
+	if(!CFile.good() || CFile.eof() || curPos >=maxPos)
 		return TEXT_ERR_ONLY_HEADER;
 
 
@@ -526,7 +526,7 @@ unsigned int limitLoadTextFile(unsigned int maxCols,
 	newLinePositions.push_back(curPos);
 	bool seenNumeric=false;
 	buffer = new char[BUFFER_SIZE];
-	while(!CFile.eof() && curPos < maxPos)
+	while(CFile.good() && !CFile.eof() && curPos < maxPos)
 	{
 		size_t bytesToRead;
 
diff --git a/src/backend/APT/APTFileIO.h b/src/backend/APT/APTFileIO.h
index 7677e9f..841fa55 100644
--- a/src/backend/APT/APTFileIO.h
+++ b/src/backend/APT/APTFileIO.h
@@ -23,11 +23,6 @@
 
 class IonHit;
 
-//!Allowable export ion formats
-enum
-{
-	IONFORMAT_POS=1
-};
 
 using std::vector;
 
diff --git a/src/backend/APT/APTRanges.cpp b/src/backend/APT/APTRanges.cpp
index e851d20..4960b92 100644
--- a/src/backend/APT/APTRanges.cpp
+++ b/src/backend/APT/APTRanges.cpp
@@ -498,7 +498,7 @@ unsigned int RangeFile::write(std::ostream &f, size_t format) const
 					
 					f << "Range" << ui+1 <<"=" 
 					<< ranges[ui].first << " " << ranges[ui].second <<
-					" " << "Name:" << strName << ":1" << 
+					" " << "Name:" << strName << " " << strName << ":1" << 
 					" Color:" << colString << endl;
 
 				}
@@ -1118,7 +1118,7 @@ unsigned int RangeFile::detectFileType(const char *rangeFile)
 			getline(f,tmpStr);
 
 			//shouldn't hit eof
-			if(f.eof())
+			if(f.eof() || (!f.good()) )
 			{
 				tmpStr.clear();
 				break;
@@ -1134,10 +1134,10 @@ unsigned int RangeFile::detectFileType(const char *rangeFile)
 		}
 
 		//Now, spin forwards until we either hit EOF or our double-dash marker
-
-		while(!f.eof())
+		while( ! (f.eof() || f.bad()) )
 		{
-			getline(f,tmpStr);
+			if(!getline(f,tmpStr))
+				break;
 
 			if(tmpStr.size() > 2 &&
 				tmpStr[0] == '-' && tmpStr[1] == '-')
@@ -1149,7 +1149,7 @@ unsigned int RangeFile::detectFileType(const char *rangeFile)
 			}
 		}
 
-		if(f.eof())
+		if(!f.good())
 		{
 			//we did not see a double-dash, must be a vanilla ORNL file
 			typeStatus[RANGE_FORMAT_DBL_ORNL]=STATUS_IS_NOT;
@@ -1179,7 +1179,7 @@ skipoutRNGChecks:
 		bool foundAllSections=false;
 
 		//Scan through each line, looking for a matching section header
-		while(!f.eof())
+		while((!f.eof()) &&f.good())
 		{
 
 			//Get line, stripped of whitespace
@@ -1505,6 +1505,7 @@ unsigned int RangeFile::openENV(FILE *fpRange)
 	bool beyondRanges=false;
 	bool haveNumRanges=false;	
 	bool haveNameBlock=false;	
+	bool haveSeenRevHeader=false;	
 	vector<string> strVec;
 
 	//Read file until we get beyond the range length
@@ -1527,6 +1528,13 @@ unsigned int RangeFile::openENV(FILE *fpRange)
 		if(!s.size())
 			continue;
 
+		//If we have
+		if(!haveSeenRevHeader && (s== "Rev_2.0"))
+		{
+			haveSeenRevHeader=true;
+			continue;
+		}
+
 		//Try different delimiters to split string
 		splitStrsRef(s.c_str(),"\t ",strVec);
 
@@ -2422,6 +2430,24 @@ void RangeFile::rangeByRangeID(vector<IonHit> &ions, unsigned int rangeID)
 	ions.swap(rangedVec);
 }
 
+void RangeFile::rangeByIon(const std::vector<IonHit> & ions,
+			const vector<bool> &selectedIons, vector<IonHit> &output) const
+{
+	output.clear();
+
+	//TODO: Play with openmp, to see if this is faster.
+	// There will be problems with synchronising writes to the output.
+	// Could try a sampling algorithm to estimate output size
+	for(size_t ui=0;ui<ions.size();ui++)
+	{
+		unsigned int id;
+		id=getIonID(ions[ui].getMassToCharge());
+		if(id == (unsigned int)-1)
+			continue;
+		if(selectedIons[id])
+			output.push_back(ions[ui]);
+	}
+}
 
 void RangeFile::printErr(std::ostream &strm) const
 {
diff --git a/src/backend/APT/APTRanges.h b/src/backend/APT/APTRanges.h
index f8dc33d..e8fc556 100644
--- a/src/backend/APT/APTRanges.h
+++ b/src/backend/APT/APTRanges.h
@@ -204,6 +204,11 @@ class RangeFile
 		bool range(std::vector<IonHit> &ionHits,
 				std::string shortIonName);
 
+		//!Clip out only a specific subset of ions
+		// Selected ions *MUST* be of the same size as getNumIons()
+		void rangeByIon(const std::vector<IonHit> & ions,
+			const std::vector<bool> &selectedIons, std::vector<IonHit> &output) const;
+
 		//!Clips out ions that dont lie in the specified range number 
 		/*! Returns false if the range does not exist 
 		 *  any in the rangefile (case sensitive) 
diff --git a/src/backend/APT/ionhit.cpp b/src/backend/APT/ionhit.cpp
index 9641d73..686efc8 100644
--- a/src/backend/APT/ionhit.cpp
+++ b/src/backend/APT/ionhit.cpp
@@ -92,12 +92,15 @@ const IonHit &IonHit::operator=(const IonHit &obj)
 	return *this;
 }
 
-IonHit IonHit::operator+(const Point3D &obj)
+
+float IonHit::operator[](unsigned int idx) const
 {
-	//FIXME: I think this is wrong???
-	ASSERT(false);
-	pos.add(obj);	
-	return *this;
+	ASSERT(idx <4);
+		
+	if(idx < 3)
+		return pos[idx];
+	else
+		return massToCharge; 
 }
 
 //!Create an pos file from a vector of IonHits
@@ -117,27 +120,50 @@ unsigned int IonHit::makePos(const vector<IonHit> &ionVec, const char *filename)
 	return 0;
 }
 
-unsigned int IonHit::appendPos(const vector<IonHit> &points, const char *name)
+unsigned int IonHit::appendFile(const vector<IonHit> &points, const char *name, unsigned int format)
 {
-	std::ofstream posFile(name,std::ios::binary|std::ios::app);	
+	switch(format)
+	{
+		case IONFORMAT_POS:
+		{
+			//Write a "pos" formatted file
+			std::ofstream posFile(name,std::ios::binary|std::ios::app);	
 
 
-	if(!posFile)
-		return 1;
+			if(!posFile)
+				return 1;
 
-	float data[4];	
-	
-	for(unsigned int ui=0; ui< points.size(); ui++)
-	{
-		points[ui].makePosData(data);
-		posFile.write((char *)data, 4*sizeof(float));
-	}
+			float data[4];	
+			
+			for(unsigned int ui=0; ui< points.size(); ui++)
+			{
+				points[ui].makePosData(data);
+				posFile.write((char *)data, 4*sizeof(float));
+			}
 
 
-	if(posFile.good())
-		return 0;
-	else
-		return 1;
+			if(posFile.good())
+				return 0;
+			else
+				return 1;
+		}
+		case IONFORMAT_TEXT:
+		{
+			std::ofstream textFile(name,std::ios::app);
+			if(!textFile)
+				return 1;
+
+			for(unsigned int ui=0;ui<points.size();ui++)
+				textFile << points[ui][0] << " " << points[ui][1] << " " << points[ui][2]  << " " << points[ui][3] << std::endl;
+
+			if(textFile.good())
+				return 0;
+			else
+				return 1;
+		}
+		default:
+			ASSERT(false);
+	}
 }
 
 void IonHit::getPoints(const vector<IonHit> &ions, vector<Point3D> &p)
diff --git a/src/backend/APT/ionhit.h b/src/backend/APT/ionhit.h
index 1b73111..f876135 100644
--- a/src/backend/APT/ionhit.h
+++ b/src/backend/APT/ionhit.h
@@ -22,6 +22,17 @@
 #include "common/basics.h"
 class Point3D;
 
+
+//TODO: Move to member of ionHit itself
+//!Allowable export ion formats
+enum
+{
+	IONFORMAT_POS=1,
+	IONFORMAT_TEXT,
+	IONFORMAT_VTK,
+	IONFORMAT_ENUM_END
+};
+
 //!This is a data holding class for POS file ions, from
 /* Pos ions are typically obtained via reconstructed apt detector hits
  * and are of form (x,y,z mass/charge)
@@ -73,8 +84,8 @@ class IonHit
 		//Get the centroid from a vector of ion hits
 		static void getCentroid(const std::vector<IonHit> &points, Point3D &centroid);
 		
-		//Add these points to a pos file
-		static unsigned int appendPos(const std::vector<IonHit> &points, const char *name);
+		//Add these points to a formatted file
+		static unsigned int appendFile(const std::vector<IonHit> &points, const char *name, const unsigned int format=IONFORMAT_POS);
 
 		//Save a pos file, overwriting any previous data at this location
 		static unsigned int makePos(const std::vector<IonHit> &points, const char *name);
diff --git a/src/backend/animator.cpp b/src/backend/animator.cpp
index c0f10a2..e59ba5c 100644
--- a/src/backend/animator.cpp
+++ b/src/backend/animator.cpp
@@ -43,9 +43,9 @@ PropertyAnimator::PropertyAnimator()
 {
 }
 
-PropertyAnimator::PropertyAnimator(const PropertyAnimator &p)
+PropertyAnimator::PropertyAnimator(const PropertyAnimator &p) : keyFrames(p.keyFrames)
 {
-	keyFrames=p.keyFrames;
+
 }
 
 void PropertyAnimator::getNthKeyFrame(size_t frameNum,FrameProperties &f) const 
diff --git a/src/backend/filter.cpp b/src/backend/filter.cpp
index 52dddd7..bf58399 100644
--- a/src/backend/filter.cpp
+++ b/src/backend/filter.cpp
@@ -25,6 +25,8 @@
 #include "wx/wxcomponents.h"
 
 #include "common/voxels.h"
+#include "backend/APT/vtk.h"
+
 
 #include <set>
 #include <deque>
@@ -154,6 +156,23 @@ void Filter::cacheAsNeeded(FilterStreamData *stream)
 	}
 }
 
+//Used by the setProperties to demultiplex "mux" one values into two separate data points
+// this is a bit of a hack, and decreases the available range to each type to 16 bits 
+void Filter::demuxKey(unsigned int key, unsigned int &keyType, unsigned int &ionOffset)
+{
+	keyType = key >> 16;
+	ionOffset = key & 0xFFFF;
+}
+
+unsigned int Filter::muxKey(unsigned int keyType, unsigned int ionOffset)
+{
+	unsigned int key;
+	key = keyType << 16;
+	key|=ionOffset;
+
+	return key;
+}
+
 std::string Filter::getErrString(unsigned int errCode) const
 {
 	//First see if we have a generic error code, before attempting to
@@ -561,6 +580,8 @@ unsigned int IonStreamData::exportStreams(const std::vector<const FilterStreamDa
 		const std::string &outFile, unsigned int format)
 {
 
+	ASSERT(format < IONFORMAT_ENUM_END);
+
 	//test file open, and truncate file to zero bytes
 	std::ofstream f(outFile.c_str(),std::ios::trunc);
 	
@@ -569,48 +590,174 @@ unsigned int IonStreamData::exportStreams(const std::vector<const FilterStreamDa
 
 	f.close();
 
-	for(unsigned int ui=0; ui<selectedStreams.size(); ui++)
+	if(format != IONFORMAT_VTK)
 	{
-		switch(selectedStreams[ui]->getStreamType())
+		for(unsigned int ui=0; ui<selectedStreams.size(); ui++)
 		{
-			case STREAM_TYPE_IONS:
+			switch(selectedStreams[ui]->getStreamType())
 			{
-				const IonStreamData *ionData;
-				ionData=((const IonStreamData *)(selectedStreams[ui]));
-				switch(format)
+				case STREAM_TYPE_IONS:
 				{
-					case IONFORMAT_POS:
-					{
-						//Append this ion stream to the posfile
-						IonHit::appendPos(ionData->data,outFile.c_str());
+					const IonStreamData *ionData;
+					ionData=((const IonStreamData *)(selectedStreams[ui]));
 
-						break;
-					}
-					default:
-						ASSERT(false);
-						break;
+						//Append this ion stream to the posfile
+						IonHit::appendFile(ionData->data,outFile.c_str(),format);
 				}
 			}
 		}
 	}
+	else
+	{
+		//we don't have an append function, as VTK's legacy
+		// format does not really support this AFAIK.
+		//so we accumulate first.
+		vector<IonHit> ionvec;
+		//--
+		unsigned int numIons=0;
+		for(unsigned int ui=0; ui<selectedStreams.size(); ui++)
+		{
+			switch(selectedStreams[ui]->getStreamType())
+			{
+				case STREAM_TYPE_IONS:
+				{
+					numIons+=selectedStreams[ui]->getNumBasicObjects();
+					break;
+				}
+			}
+		}
+		
+		ionvec.reserve(numIons);
+		for(unsigned int ui=0;ui<selectedStreams.size();ui++)
+		{
+			switch(selectedStreams[ui]->getStreamType())
+			{
+				case STREAM_TYPE_IONS:
+				{
+					const IonStreamData *ionData;
+					ionData=((const IonStreamData *)(selectedStreams[ui]));
+					for(unsigned int uj=0;uj<ionData->data.size();uj++)
+						ionvec.push_back(ionData->data[uj]);
+					break;
+				}
+			}
+		}
 
+		if(vtk_write_legacy(outFile,VTK_ASCII,ionvec))
+			return 1;
+		//--
+	}
 	return 0;
 }
 
-IonStreamData::IonStreamData() : representationType(ION_REPRESENT_POINTS), 
+
+IonStreamData::IonStreamData() : 
 	r(1.0f), g(0.0f), b(0.0f), a(1.0f), 
 	ionSize(2.0f), valueType("Mass-to-Charge (amu/e)")
 {
 	streamType=STREAM_TYPE_IONS;
 }
 
-IonStreamData::IonStreamData(const Filter *f) : FilterStreamData(f), representationType(ION_REPRESENT_POINTS), 
+IonStreamData::IonStreamData(const Filter *f) : FilterStreamData(f), 
 	r(1.0f), g(0.0f), b(0.0f), a(1.0f), 
 	ionSize(2.0f), valueType("Mass-to-Charge (amu/e)")
 {
 	streamType=STREAM_TYPE_IONS;
 }
 
+void IonStreamData::estimateIonParameters(const std::vector<const FilterStreamData *> &inData)
+{
+
+	map<float,unsigned int> ionSizeMap;
+	map<vector<float>, unsigned int> ionColourMap;
+	std::string lastStr;
+
+	//Sum up the relative frequencies
+	for(unsigned int ui=0; ui<inData.size(); ui++)
+	{
+		if(inData[ui]->getStreamType() != STREAM_TYPE_IONS)
+			continue;	
+
+		//Keep a count of the number of times we see a particlar
+		// size/colour combination	
+		map<float,unsigned int>::iterator itSize;
+		map<vector<float> ,unsigned int>::iterator itData;
+	
+		const IonStreamData* p;	
+		p= ((const IonStreamData*)inData[ui]);
+
+		itSize=ionSizeMap.find(p->ionSize);
+		if(itSize == ionSizeMap.end())
+			ionSizeMap[p->ionSize]=1;	
+		else
+			ionSizeMap[p->ionSize]++;
+
+		vector<float> tmpRgba;
+		tmpRgba.push_back(p->r); tmpRgba.push_back(p->g);
+		tmpRgba.push_back(p->b); tmpRgba.push_back(p->a);
+		
+		itData = ionColourMap.find(tmpRgba);
+		if(itData == ionColourMap.end())
+			ionColourMap[tmpRgba]=1;	
+		else
+			ionColourMap[tmpRgba]++;
+			
+		if(lastStr.empty())
+			lastStr=p->valueType ;
+		else
+			lastStr = "Mixed types";	
+		 
+	}
+	
+	const vector<float> *tmp=0;
+	size_t min=0;
+	//find the most frequent ion colour	
+	for(map<vector<float>, unsigned int>::iterator it=ionColourMap.begin();
+		it!=ionColourMap.end(); ++it)
+	{
+		if(it->second > min)
+		{
+			tmp = &(it->first);
+			min=it->second;
+		}
+	}
+
+	//Find the most frequent ion size
+	float tmpSize=1.0;
+	min=0;
+	for(map<float, unsigned int>::iterator it=ionSizeMap.begin();
+		it!=ionSizeMap.end(); ++it)
+	{
+		if(it->second > min)
+		{
+			tmpSize = it->first;
+			min=it->second;
+		}
+	}
+
+	ionSize=tmpSize;
+	if(tmp && tmp->size() == 4)
+	{
+		r=(*tmp)[0];
+		g=(*tmp)[1];
+		b=(*tmp)[2];
+		a=(*tmp)[3];
+	}
+
+
+	if(lastStr.size())
+		valueType=lastStr;
+	else
+		valueType.clear();
+}
+
+void IonStreamData::estimateIonParameters(const IonStreamData *i)
+{
+	vector<const FilterStreamData *> v;
+	v.push_back(i);
+	
+	estimateIonParameters(v);
+}
 
 void IonStreamData::clear()
 {
@@ -622,7 +769,6 @@ IonStreamData *IonStreamData::cloneSampled(float fraction) const
 {
 	IonStreamData *out = new IonStreamData;
 
-	out->representationType=representationType;
 	out->r=r;
 	out->g=g;
 	out->b=b;
diff --git a/src/backend/filter.h b/src/backend/filter.h
index 16a4a0c..c77e2c6 100644
--- a/src/backend/filter.h
+++ b/src/backend/filter.h
@@ -66,7 +66,7 @@ enum
 	FILTER_TYPE_SPECTRUMPLOT, 
 	FILTER_TYPE_IONCLIP,
 	FILTER_TYPE_IONCOLOURFILTER,
-	FILTER_TYPE_COMPOSITION,
+	FILTER_TYPE_PROFILE,
 	FILTER_TYPE_BOUNDBOX,
 	FILTER_TYPE_TRANSFORM,
 	FILTER_TYPE_EXTERNALPROC,
@@ -116,13 +116,6 @@ enum
 
 extern const char *STREAM_NAMES[];
 
-//Representations
-enum 
-{
-	//IonStreamData
-	ION_REPRESENT_POINTS
-	
-};
 
 //Representations
 enum 
@@ -281,9 +274,11 @@ public:
 	IonStreamData *cloneSampled(float fraction) const;
 
 	size_t getNumBasicObjects() const;
-	
-	unsigned int representationType;
+
+	//Ion colour + transparancy in [0,1] colour space. 
 	float r,g,b,a;
+
+	//Ion Size in 2D opengl units
 	float ionSize;
 	
 	//!The name for the type of data -- nominally "mass-to-charge"
@@ -295,6 +290,10 @@ public:
 	//!export given filterstream data pointers as ion data
 	static unsigned int exportStreams(const std::vector<const FilterStreamData *> &selected, 
 							const std::string &outFile, unsigned int format=IONFORMAT_POS);
+
+	//!Use heuristics to guess best display parameters for this ionstream. May attempt to leave them alone 
+	void estimateIonParameters(const std::vector<const FilterStreamData *> &inputData);
+	void estimateIonParameters(const IonStreamData *inputFilter);
 };
 
 //!Point with m-t-c value data
@@ -616,8 +615,7 @@ class Filter
 				std::vector<const FilterStreamData *> &dataOut);
 
 
-		//!Return the XML elements that refer to external entities (i.e. files) which do not move with the XML file
-		//Each element is to be referred to using "/" as entity separator, for the first pair element, and the attribute name for the second.
+		//!Return the XML elements that refer to external entities (i.e. files) which do not move with the XML files. At this time, only files are supported. These will be looked for on the filesystem and moved as needed 
 		virtual void getStateOverrides(std::vector<std::string> &overrides) const {}; 
 
 		//!Enable/disable caching for this filter
@@ -681,6 +679,10 @@ class Filter
 	
 		template<typename T>	
 		static void getStreamsOfType(const std::vector<const FilterStreamData *> &vec, std::vector<const T *> &dataOut);
+
+
+
+
 #ifdef DEBUG
 		//!Run all the registered unit tests for this filter
 		virtual bool runUnitTests() { std::cerr << "No test for " << typeString() << std::endl; return true;} ;
@@ -691,6 +693,16 @@ class Filter
 		
 		static bool helpStringTests() ;
 #endif
+		
+
+//These functions are private for non-debug builds, to allow unit tests to access these
+#ifndef DEBUG
+	protected:
+#endif
+		//!Hack to merge/extract two bits of information into a single property key.
+		//It does this by abusing some bitshifting, to make use of usually unused key range
+		static void demuxKey(unsigned int key, unsigned int &keyType, unsigned int &ionOffset);
+		static unsigned int muxKey(unsigned int keyType, unsigned int ionOffset);
 
 };
 
@@ -745,7 +757,7 @@ bool Filter::applyPropertyNow(T &prop, const std::string &val, bool &needUp)
 class ProgressData
 {
 	public:
-		//!Progress of filter (out of 100) for current filter
+		//!Progress of filter (out of 100, or -1 for no progress information) for current filter
 		unsigned int filterProgress;
 		//!Number of filters (n) that we have processed (n out of m filters)
 		unsigned int totalProgress;
@@ -769,8 +781,8 @@ class ProgressData
 		bool operator==(const ProgressData &o) const;
 		const ProgressData &operator=(const ProgressData &o);
 
-		void reset() { filterProgress=totalProgress=step=maxStep=0;curFilter=0; totalNumFilters=1; stepName.clear();};
-		void clock() { filterProgress=step=maxStep=0;curFilter=0;totalProgress++; stepName.clear();};
+		void reset() { filterProgress=(unsigned int) -1; totalProgress=step=maxStep=0;curFilter=0; totalNumFilters=1; stepName.clear();};
+		void clock() { filterProgress=(unsigned int)-1; step=maxStep=0;curFilter=0;totalProgress++; stepName.clear();};
 };
 
 
diff --git a/src/backend/filters/algorithms/K3DTree-mk2.cpp b/src/backend/filters/algorithms/K3DTree-mk2.cpp
index c8bb50d..72b8b70 100644
--- a/src/backend/filters/algorithms/K3DTree-mk2.cpp
+++ b/src/backend/filters/algorithms/K3DTree-mk2.cpp
@@ -31,6 +31,16 @@ unsigned int *K3DTreeMk2::progress=0;
 //Pointer for aborting during build process
 ATOMIC_BOOL *K3DTreeMk2::abort=0;
 
+class NodeWalk
+{
+	public:
+		size_t index;
+		BoundCube cube;
+		unsigned int depth;
+		NodeWalk(unsigned int idx, BoundCube bc, unsigned int dpth) : 
+			index(idx), cube(bc), depth(dpth) {};
+};
+
 void K3DTreeMk2::resetPts(std::vector<Point3D> &p, bool clear)
 {
 	//Compute bounding box for indexedPoints
@@ -86,6 +96,11 @@ const Point3D *K3DTreeMk2::getPt(size_t index) const
 	return &(indexedPoints[index].first);
 }
 
+const Point3D &K3DTreeMk2::getPtRef(size_t index) const
+{
+	ASSERT(index < indexedPoints.size());
+	return (indexedPoints[index].first);
+}
 size_t K3DTreeMk2::getOrigIndex(size_t treeIndex) const 
 {
 	ASSERT(treeIndex <indexedPoints.size());
@@ -285,103 +300,98 @@ bool K3DTreeMk2::build()
 	return true;
 }
 
-/*
-void K3DTreeMk2::dump(std::ostream &strm) const
+void K3DTreeMk2::ptsInSphere(const Point3D &origin, float radius,
+		vector<size_t> &pts) const
 {
-	enum
-	{
-		PRINT_NONE,
-		PRINT_LEFT,
-		PRINT_BOTH
-	};
-
-	if(!indexedPoints.size())
+	if(!treeBounds.intersects(origin,radius))
 		return;
 
-	stack<char> status;
-	stack<size_t> nodeStack;
-	status.push(PRINT_NONE);
-	nodeStack.push(indexedPoints.size()/2);
+	//parent walking queue. This contains initial parent indices that
+	// lie within the sphere.
+	const float sqrRadius=radius*radius;
+	//contains all completely contained points (these points and children are in sphere)
+	std::queue<size_t> idxQueue;
+	//queue of points whose children are partly in the sphere
+	std::queue<NodeWalk> nodeQueue;
+	nodeQueue.push(NodeWalk(treeRoot,treeBounds,0));
 
-	do
+	while(!nodeQueue.empty())
 	{
-		for(size_t ui=0;ui<status.size(); ui++)
-			strm << "\t";
+		size_t nodeIdx;
+		BoundCube curCube;
+		unsigned int depth,axis;
+
+		nodeIdx = nodeQueue.front().index;
+		curCube=nodeQueue.front().cube;
+		depth = nodeQueue.front().depth;
+		axis=depth %3;	
+		nodeQueue.pop()	;
 	
-		strm << "(" << indexedPoints[nodeStack.top()].getValue(0) 
-			<< "," << indexedPoints[nodeStack.top()].getValue(1) 
-			<< "," << indexedPoints[nodeStack.top()].getValue(2) << ")" << std::endl;
-		switch(status.top())
-		{	
-			case PRINT_NONE:
-				status.top()++;
-				if(nodes[nodeStack.top()].childLeft != -1)
-				{
-					nodeStack.push(nodes[nodeStack.top()].childLeft);
-					status.push(PRINT_NONE);
-				}
-				break;
-			case PRINT_LEFT:
-				status.top()++;
-				if(nodes[nodeStack.top()].childRight != -1)
+
+		//obtain the left and right cubes, and see if they
+		// -exist
+		// -intersect the spehre
+		// - if intersects, are they contained entirely by the sphere 
+		BoundCube leftCube,rightCube;
+		if(nodes[nodeIdx].childLeft != (size_t) -1)
+		{
+			leftCube=curCube;
+			leftCube.bounds[axis][1]=indexedPoints[nodeIdx].first[axis];
+			if(leftCube.intersects(origin,sqrRadius) )
+			{
+				if(leftCube.containedInSphere(origin,sqrRadius))
 				{
-					nodeStack.push(nodes[nodeStack.top()].childRight);
-					status.push(PRINT_NONE);
+					ASSERT(indexedPoints[nodeIdx].first.sqrDist(origin) < radius*radius);
+					idxQueue.push(nodes[nodeIdx].childLeft);
 				}
-				break;
-			case PRINT_BOTH:
-				status.pop();
-				nodeStack.pop();
-		}
-		
-	}while(status.size());
-}
-*/
+				else
+					nodeQueue.push(NodeWalk(nodes[nodeIdx].childLeft,leftCube,depth+1));
+			}
+		}	
 
-void K3DTreeMk2::dump(std::ostream &strm,  size_t depth, size_t offset) const
-{
-	if(offset==(size_t)-1)
-	{
-		for(unsigned int ui=0;ui<indexedPoints.size();ui++)
+		if(nodes[nodeIdx].childRight != (size_t) -1)
 		{
-			strm << ui << " "<< indexedPoints[ui].first << std::endl;
-		}
-
-		strm << "----------------" << std::endl;
-		offset=treeRoot;
-	}
-
-	for(size_t ui=0;ui<depth; ui++)
-		strm << "\t";
+			rightCube=curCube;
+			rightCube.bounds[axis][0]=indexedPoints[nodeIdx].first[axis];
+			if(rightCube.intersects(origin,sqrRadius) )
+			{
+				if(rightCube.containedInSphere(origin,sqrRadius))
+				{
+					//If the right-hand cube is contained within (origin,radius) sphere, then so are all its chilren
 
-	strm << offset << " : (" << indexedPoints[offset].first[0] 
-		<< "," << indexedPoints[offset].first[1] << "," << indexedPoints[offset].first[2]
-		<< ")" << std::endl;
+					ASSERT(indexedPoints[nodeIdx].first.sqrDist(origin) < sqrRadius);
+					idxQueue.push(nodes[nodeIdx].childRight);
+				}
+				else
+					nodeQueue.push(NodeWalk(nodes[nodeIdx].childRight,rightCube,depth+1));
+			}
+		}	
 
+		if(indexedPoints[nodeIdx].first.sqrDist(origin) < sqrRadius)
+			pts.push_back(nodeIdx);
 
+	}	
 
-	for(size_t ui=0;ui<depth; ui++)
-		strm << "\t";
-	strm << "<l>" <<std::endl;
 
-	if(nodes[offset].childLeft!=(size_t)-1)
+	pts.reserve(idxQueue.size());
+	//Walk the idx queue to enumerate all children that are in the sphere
+	while(!idxQueue.empty())
 	{
-		dump(strm,depth+1,nodes[offset].childLeft);
-	}
-	for(size_t ui=0;ui<depth; ui++)
-		strm << "\t";
-	strm << "</l>" <<std::endl;
+		size_t curIdx;
+		curIdx=idxQueue.front();
+		ASSERT(indexedPoints[curIdx].first.sqrDist(origin) < sqrRadius);
+		if(nodes[curIdx].childLeft != (size_t)-1)
+			idxQueue.push(nodes[curIdx].childLeft);
+		
+		if(nodes[curIdx].childRight !=(size_t) -1)
+			idxQueue.push(nodes[curIdx].childRight);
 
-	for(size_t ui=0;ui<depth; ui++)
-		strm << "\t";
-	strm << "<r>" <<std::endl;
 
-	if(nodes[offset].childRight!=(size_t)-1)
-		dump(strm,depth+1,nodes[offset].childRight);
+		ASSERT(curIdx < nodes.size());
+		pts.push_back(curIdx);
+		idxQueue.pop();
+	}
 	
-	for(size_t ui=0;ui<depth; ui++)
-		strm << "\t";
-	strm << "</r>" <<std::endl;
 }
 
 size_t K3DTreeMk2::findNearestUntagged(const Point3D &searchPt,
@@ -635,6 +645,254 @@ size_t K3DTreeMk2::findNearestUntagged(const Point3D &searchPt,
 
 }
 
+size_t K3DTreeMk2::findNearestWithSkip(const Point3D &searchPt,
+				const BoundCube &domainCube, const std::set<size_t> &skipPts, size_t pseudoRoot) const
+{
+	//Tree must be built!
+	ASSERT(treeRoot < nodes.size() && maxDepth <=nodes.size())
+	enum { NODE_FIRST_VISIT, //First visit is when you descend the tree
+		NODE_SECOND_VISIT, //Second visit is when you come back from ->Left()
+		NODE_THIRD_VISIT // Third visit is when you come back from ->Right()
+		};
+	
+	size_t nodeStack[maxDepth+1];
+	float domainStack[maxDepth+1][2];
+	unsigned int visitStack[maxDepth+1];
+
+	size_t bestPoint;
+	size_t curNode;
+
+	BoundCube curDomain;
+	unsigned int visit;
+	unsigned int stackTop;
+	unsigned int curAxis;
+	
+	float bestDistSqr;
+	float tmpEdge;
+
+	if(nodes.empty())
+		return -1;
+
+	bestPoint=(size_t)-1; 
+	bestDistSqr =std::numeric_limits<float>::max();
+	curDomain=domainCube;
+	visit=NODE_FIRST_VISIT;
+	curAxis=0;
+	stackTop=0;
+
+	//Start at median of array, which is top of tree,
+	//by definition, unless an alternative entry point is given
+	size_t startNode;
+	if(pseudoRoot==(size_t) -1)
+		startNode=treeRoot;
+	else
+		startNode=pseudoRoot;
+
+	curNode=startNode;
+
+	//check start node and that we have not seen this already	
+	if(!(nodes[curNode].tagged  || (skipPts.find(curNode) !=skipPts.end() )) )
+	{
+		float tmpDistSqr;
+		tmpDistSqr = indexedPoints[curNode].first.sqrDist(searchPt); 
+		if(tmpDistSqr < bestDistSqr)
+		{
+			bestDistSqr  = tmpDistSqr;
+			bestPoint=curNode;
+		}
+	}
+
+	do
+	{
+		switch(visit)
+		{
+			//Examine left branch
+			case NODE_FIRST_VISIT:
+			{
+				if(searchPt[curAxis] < indexedPoints[curNode].first[curAxis])
+				{
+					if(nodes[curNode].childLeft!=(size_t)-1)
+					{
+						//Check bounding box when shrunk overlaps best
+						//estimate sphere
+						tmpEdge= curDomain.bounds[curAxis][1];
+						curDomain.bounds[curAxis][1] = indexedPoints[curNode].first[curAxis];
+						if(!curDomain.intersects(searchPt,bestDistSqr))
+						{
+							curDomain.bounds[curAxis][1] = tmpEdge; 
+							visit++;
+							continue;		
+						}	
+						//Preserve our current state.
+						nodeStack[stackTop]=curNode;
+						visitStack[stackTop] = NODE_SECOND_VISIT; //Oh, It will be. It will be.
+						domainStack[stackTop][1] = tmpEdge;
+						domainStack[stackTop][0]= curDomain.bounds[curAxis][0];
+						stackTop++;
+
+						//Update the current information
+						curNode=nodes[curNode].childLeft;
+						visit=NODE_FIRST_VISIT;
+						curAxis++;
+						curAxis%=3;
+						continue;
+					}
+				}	
+				else
+				{
+					if(nodes[curNode].childRight!=(size_t)-1)
+					{
+						//Check bounding box when shrunk overlaps best
+						//estimate sphere
+						tmpEdge= curDomain.bounds[curAxis][0];
+						curDomain.bounds[curAxis][0] = indexedPoints[curNode].first[curAxis];
+						
+						if(!curDomain.intersects(searchPt,bestDistSqr))
+						{
+							curDomain.bounds[curAxis][0] =tmpEdge; 
+							visit++;
+							continue;		
+						}	
+
+						//Preserve our current state.
+						nodeStack[stackTop]=curNode;
+						visitStack[stackTop] = NODE_SECOND_VISIT; //Oh, It will be. It will be.
+						domainStack[stackTop][0] = tmpEdge;
+						domainStack[stackTop][1]= curDomain.bounds[curAxis][1];
+						stackTop++;
+
+						//Update the information
+						curNode=nodes[curNode].childRight;
+						visit=NODE_FIRST_VISIT;
+						curAxis++;
+						curAxis%=3;
+						continue;	
+					}
+				}
+				visit++;
+				//Fall through
+			}
+			//Examine right branch
+			case NODE_SECOND_VISIT:
+			{
+				if(searchPt[curAxis]< indexedPoints[curNode].first[curAxis])
+				{
+					if(nodes[curNode].childRight!=(size_t)-1)
+					{
+						//Check bounding box when shrunk overlaps best
+						//estimate sphere
+						tmpEdge= curDomain.bounds[curAxis][0];
+						curDomain.bounds[curAxis][0] = indexedPoints[curNode].first[curAxis];
+						
+						if(!curDomain.intersects(searchPt,bestDistSqr))
+						{
+							curDomain.bounds[curAxis][0] = tmpEdge; 
+							visit++;
+							continue;		
+						}
+	
+						nodeStack[stackTop]=curNode;
+						visitStack[stackTop] = NODE_THIRD_VISIT; 
+						domainStack[stackTop][0] = tmpEdge;
+						domainStack[stackTop][1]= curDomain.bounds[curAxis][1];
+						stackTop++;
+						
+						//Update the information
+						curNode=nodes[curNode].childRight;
+						visit=NODE_FIRST_VISIT;
+						curAxis++;
+						curAxis%=3;
+						continue;	
+
+					}
+				}
+				else
+				{
+					if(nodes[curNode].childLeft!=(size_t)-1)
+					{
+						//Check bounding box when shrunk overlaps best
+						//estimate sphere
+						tmpEdge= curDomain.bounds[curAxis][1];
+						curDomain.bounds[curAxis][1] = indexedPoints[curNode].first[curAxis];
+						
+						if(!curDomain.intersects(searchPt,bestDistSqr))
+						{
+							curDomain.bounds[curAxis][1] = tmpEdge; 
+							visit++;
+							continue;		
+						}	
+						//Preserve our current state.
+						nodeStack[stackTop]=curNode;
+						visitStack[stackTop] = NODE_THIRD_VISIT; 
+						domainStack[stackTop][1] = tmpEdge;
+						domainStack[stackTop][0]= curDomain.bounds[curAxis][0];
+						stackTop++;
+						
+						//Update the information
+						curNode=nodes[curNode].childLeft;
+						visit=NODE_FIRST_VISIT;
+						curAxis++;
+						curAxis%=3;
+						continue;	
+
+					}
+				}
+				visit++;
+				//Fall through
+			}
+			case NODE_THIRD_VISIT:
+			{
+				//Decide if we should promote the current node
+				//to "best" (i.e. nearest untagged) node.
+				//To promote, it mustn't be tagged, and it must
+				//be closer than cur best estimate.
+				if(!(nodes[curNode].tagged || (skipPts.find(curNode) !=skipPts.end()) ) )
+				{
+					float tmpDistSqr;
+					tmpDistSqr = indexedPoints[curNode].first.sqrDist(searchPt); 
+					if(tmpDistSqr < bestDistSqr)
+					{
+						bestDistSqr  = tmpDistSqr;
+						bestPoint=curNode;
+					}
+				}
+
+				//DEBUG
+				ASSERT(stackTop%3 == curAxis)
+				//
+				if(curAxis)
+					curAxis--;
+				else
+					curAxis=2;
+
+
+				
+				ASSERT(stackTop < maxDepth+1);	
+				if(stackTop)
+				{
+					stackTop--;
+					visit=visitStack[stackTop];
+					curNode=nodeStack[stackTop];
+					curDomain.bounds[curAxis][0]=domainStack[stackTop][0];
+					curDomain.bounds[curAxis][1]=domainStack[stackTop][1];
+					ASSERT((stackTop)%3 == curAxis);
+				}
+			
+				break;
+			}
+			default:
+				ASSERT(false);
+
+
+		}
+		
+
+	//Keep going until we meet the root node for the third time (one left, one right, one finish)	
+	}while(!(curNode== startNode &&  visit== NODE_THIRD_VISIT));
+
+	return bestPoint;	
+
+}
 
 void K3DTreeMk2::getTreesInSphere(const Point3D &pt, float sqrDist, const BoundCube &domainCube,
 					vector<pair<size_t,size_t> > &contiguousBlocks ) const
diff --git a/src/backend/filters/algorithms/K3DTree-mk2.h b/src/backend/filters/algorithms/K3DTree-mk2.h
index e570689..38d1a71 100644
--- a/src/backend/filters/algorithms/K3DTree-mk2.h
+++ b/src/backend/filters/algorithms/K3DTree-mk2.h
@@ -19,6 +19,7 @@
 #ifndef K3DTREEMK2_H
 #define K3DTREEMK2_H
 
+#include <set>
 #include <vector>
 #include <utility>
 
@@ -52,9 +53,9 @@ class AxisCompareMk2
 class K3DNodeMk2
 {
 	public:
-		//Index of left child in parent tree array
+		//Index of left child in parent tree array. -1 if no child
 		size_t childLeft;
-		//Index of right child in parent tree array
+		//Index of right child in parent tree array. -1 if no child
 		size_t childRight;
 
 		//Has this point been marked by an external algorithm?
@@ -108,7 +109,7 @@ class K3DTreeMk2
 		
 
 		/*! Builds a balanced KD tree from a list of points
-		 *  previously set by "resetPts". returns false if abort checks return
+		 *  previously set by "resetPts". returns false if callback returns
 		 *  false;
 		 */	
 		bool build();
@@ -128,6 +129,17 @@ class K3DTreeMk2
 		size_t findNearestUntagged(const Point3D &queryPt,
 						const BoundCube &b, bool tag=true,size_t pseudoRoot=(size_t)-1);
 
+		//Find the nearest "untagged" point's internal index.
+		// Skip any of the listed points.
+		size_t findNearestWithSkip(const Point3D &queryPt,
+				const BoundCube &b,const std::set<size_t> &skipPts,
+					size_t pseudoRoot=(size_t)-1) const;
+
+		//Find the indicies of all points that lie within  the
+		// sphere (pts < radius) of given radius, centered upon
+		// this origin
+		void ptsInSphere(const Point3D &origin, float radius,
+			std::vector<size_t> &pts) const;
 	
 		//!Get the contigous node IDs for a subset of points in the tree that are contained
 		// within a sphere positioned about pt, with a sqr radius of sqrDist.
@@ -145,25 +157,35 @@ class K3DTreeMk2
 
 		//Obtain a point from its internal index
 		const Point3D *getPt(size_t index) const ;
+		//Obtain a point from its internal index
+		const Point3D &getPtRef(size_t index) const ;
 
 		//reset the specified "tags" in the tree
 		void clearTags(std::vector<size_t> &tagsToClear);
 
+		//Convert the "tree index" (the position in the tree) into the original point offset in the input array
 		size_t getOrigIndex(size_t treeIndex) const ;
 		
 
 		//Erase tree contents
 		void clear() { nodes.clear(); indexedPoints.clear();};
+
+		//mark a point as "tagged" (or untagged,if tagVal=false) via its tree index.
 		void tag(size_t tagID,bool tagVal=true) ;
 
-		bool getTag(size_t tagID) const ;
+		//obtain the tag status for a given point, using the tree index
+		bool getTag(size_t treeIndex) const ;
 
-		size_t size() const ;
+		//obtain the number of points in the tree
+		size_t size() const; 
 		
+		//Find the position of the root node in the tree
 		size_t rootIdx() const { return treeRoot;}
 
+		//Find the number of tagged items in the tree
 		size_t tagCount() const;
 
+		//reset all tagged points to untagged
 		void clearAllTags();
 };
 
diff --git a/src/backend/filters/algorithms/mass.cpp b/src/backend/filters/algorithms/mass.cpp
index bf4a32d..48fce16 100644
--- a/src/backend/filters/algorithms/mass.cpp
+++ b/src/backend/filters/algorithms/mass.cpp
@@ -87,19 +87,18 @@ unsigned int doFitBackground(const vector<const FilterStreamData*> &dataIn,
 	const unsigned int MIN_REQUIRED_AVG_COUNTS=10;
 	const unsigned int MIN_REQUIRED_BINS=10;
 
-	//CHECKME : The number of bins is the same in TOF as well as in 
-	// m/c space. 	
-	size_t nBins = (backParams.massEnd - backParams.massStart) / backParams.binWidth;
-	float filterStep = (sqrt(backParams.massEnd) - sqrt(backParams.massStart) )/ nBins; 
+	size_t nBinsTof = (sqrt(backParams.massEnd) - sqrt(backParams.massStart)) / backParams.binWidth;
+	float filterStep = (sqrt(backParams.massEnd) - sqrt(backParams.massStart) )/ nBinsTof; 
 
 	//we cannot perform a test with fewer than this number of bins
-	if ( nBins < MIN_REQUIRED_BINS)
+	if ( nBinsTof < MIN_REQUIRED_BINS)
 		return BACKGROUND_PARAMS::FIT_FAIL_MIN_REQ_BINS;
 
-	float averageCounts = sqrtFiltMass.size()/ (float)nBins; 
+	float averageCounts = sqrtFiltMass.size()/ (float)nBinsTof; 
 	if( averageCounts < MIN_REQUIRED_AVG_COUNTS)
 		return BACKGROUND_PARAMS::FIT_FAIL_AVG_COUNTS; 
 
+	//Check that the TOF-space histogram is gaussian
 	vector<float> histogram;
 	makeHistogram(sqrtFiltMass,sqrt(backParams.massStart),
 			sqrt(backParams.massEnd), filterStep,histogram);	
@@ -120,14 +119,34 @@ unsigned int doFitBackground(const vector<const FilterStreamData*> &dataIn,
 	if(andersonStat > STATISTIC_THRESHOLD || undefCount == histogram.size())
 		return BACKGROUND_PARAMS::FIT_FAIL_DATA_NON_GAUSSIAN;
 
-	//Intensity PER AMU
-	//backgroundIntensity= meanVal/filterStep;
 	//Intensity PER BIN in TOF space
 	backParams.intensity= meanVal;
 
 	return 0;
 }
 
+
+//Start and end mass, and step size (to get bin count).
+// tofBackIntensity is the intensity level per unit time in the background, as obtained by doFitBackground
+// the histogram is 
+void createMassBackground(float massStart, float massEnd, unsigned int nBinsMass,
+			float tofBackIntensity, vector<float> &histogram)
+{
+	const float MC_BIN_STEP = (massEnd-massStart)/nBinsMass;
+
+	//compute fitted value analytically
+	histogram.resize(nBinsMass);
+	for(size_t ui=0;ui<histogram.size();ui++)
+	{
+		float mcX;
+		mcX=(float)ui*MC_BIN_STEP+ massStart;
+		if ( mcX <=0)
+			histogram[ui]=0;
+		else
+			histogram[ui]= tofBackIntensity/(2.0*sqrt(mcX))*MC_BIN_STEP;
+	}
+}
+
 #ifdef DEBUG
 #include "common/mathfuncs.h"
 
@@ -163,7 +182,7 @@ bool testAnderson()
 	return true;
 }
 
-bool testBackgroundFit()
+bool testBackgroundFitMaths()
 {
 	RandNumGen rng;
 	rng.initTimer();
@@ -173,15 +192,14 @@ bool testBackgroundFit()
 	
 	ionData = new IonStreamData;
 
-	const unsigned int NUM_IONS =10000;
-	const float SIMULATED_INTENSITY= 100.0f;
+	const unsigned int NUM_IONS =100000;
 	
 	//Simulate a histogram of NUM_IONS
 	// between a lower and upper limit. 
 	// This is flat in TOF space, with mean intensity
 	// given by NUM_IONS/NUM_BINS
 	//---
-	const float TOF_LIMIT[2] = { 1.0,10};	
+	const float TOF_LIMIT[2] = { 0.0,100};	
 	
 	vector<float> rawData;
 	ionData->data.resize(NUM_IONS);
@@ -194,20 +212,7 @@ bool testBackgroundFit()
 		rawData[ui] = simTof;	
 	}
 
-	const float BIN_STEP=0.1f;
-	vector<float> histogramRes;
-	makeHistogram(rawData,TOF_LIMIT[0],TOF_LIMIT[1],
-		BIN_STEP,histogramRes);
-	//---
-
-	//Find the mean and std. deviation for the tof  histogram
-	float meanV,stdV;
-	meanAndStdev(histogramRes,meanV,stdV);
 
-	//check that the TOF histogram's mean matches the expected value 	
-	const float EXPECTED_MEAN = NUM_IONS*BIN_STEP/(TOF_LIMIT[1] - TOF_LIMIT[0]);
-	TEST(meanV > 0.95*EXPECTED_MEAN &&
-		meanV < EXPECTED_MEAN*1.15,"expected mean should fall (well) within anticipated bounds, but does not"); 
 
 
 	//Now perform the fit in m/c space, and after, check that it matches the anticipated m/c histogram.
@@ -217,41 +222,40 @@ bool testBackgroundFit()
 	vector<float> massData;
 	massData.resize(NUM_IONS);
 	for(size_t ui=0;ui<NUM_IONS;ui++)
-		massData[ui] = sqrt(rawData[ui]);
+		massData[ui] = rawData[ui]*rawData[ui];
 	vector<float> massHist;
 	
 	//Recompute the bin step parameter, as the stepping in m/c space to yield 
 	// the same number of bins will e radially different
-	const float NBINS = ( TOF_LIMIT[1] - TOF_LIMIT[0] )/BIN_STEP;
-	const float MC_BIN_STEP = (sqrt(TOF_LIMIT[1])-sqrt(TOF_LIMIT[0]))/NBINS;
-	makeHistogram(massData,sqrt(TOF_LIMIT[0]),sqrt(TOF_LIMIT[1]),MC_BIN_STEP,massHist);	
+	const float NBINS_TOF = 20;
+	const float NBINS_MASS= NBINS_TOF; 
+	const float MASS_LIMIT[2] =  {TOF_LIMIT[0]*TOF_LIMIT[0], TOF_LIMIT[1]*TOF_LIMIT[1]};
+	
+
+	//time-space intensity per unit time
+	const float TOF_MEAN_INT= NUM_IONS/(TOF_LIMIT[1] - TOF_LIMIT[0]);
+
+	const float MC_BIN_STEP = (MASS_LIMIT[1]-MASS_LIMIT[0])/NBINS_MASS;
+	makeHistogram(massData,MASS_LIMIT[0],MASS_LIMIT[1],MC_BIN_STEP,massHist);	
 
 	//compute fitted value analytically
 	vector<float > fittedMassHist;
-	fittedMassHist.resize(NBINS);
-	for(size_t ui=0;ui<histogramRes.size();ui++)
-	{
-		float mcX;
-		mcX=(float)ui*MC_BIN_STEP + sqrtf(TOF_LIMIT[0]);
-		fittedMassHist[ui]= meanV/(2*mcX);
-	}
-	ASSERT(massHist.size() == histogramRes.size());
+	createMassBackground(MASS_LIMIT[0],MASS_LIMIT[1],NBINS_MASS,TOF_MEAN_INT,fittedMassHist);	
 
-	//FIXME: Test appears to be broken
-	WARN(false,"Test non-functional, and algorithm broken. Fixme.");
-	//check that the numerical and analytical results match
-	for(size_t ui=0;ui<massHist.size();ui++)
+	//check that the numerical and analytical results match.
+	// notably, skip the first one as the fit is unstable
+	for(size_t ui=1;ui<massHist.size();ui++)
 	{
 		float midV;
-		midV = massHist[ui] + histogramRes[ui];
+		midV = massHist[ui] + fittedMassHist[ui];
 		midV*=0.5f;
 		float errorFraction;
-		errorFraction= fabs((massHist[ui] - histogramRes[ui])/midV);
-		//ASSERT(errorFraction < 0.5f);
+		errorFraction= fabs((massHist[ui] - fittedMassHist[ui])/midV);
+		ASSERT(errorFraction < 0.5f);
 	}	
 	//---
 
+	delete ionData;
 	return true;	
  }
-
 #endif
diff --git a/src/backend/filters/algorithms/mass.h b/src/backend/filters/algorithms/mass.h
index 41b5828..201b504 100644
--- a/src/backend/filters/algorithms/mass.h
+++ b/src/backend/filters/algorithms/mass.h
@@ -59,7 +59,8 @@ struct BACKGROUND_PARAMS
 
 	//result parameters
 	// for FIT_MODE_CONST_TOF, this uses 
-	float intensity,stdev;
+	float intensity,stdev; //FIXME: the units of this are not fully coherent. Should be in units of (counts/sqrt(amu))
+
 };
 
 template<typename T>
@@ -99,6 +100,13 @@ void meanAndStdev(const std::vector<T > &f,float &meanVal,
 //	- returns zero on success, nonzero on error`
 unsigned int doFitBackground(const std::vector<const FilterStreamData*> &dataIn, BACKGROUND_PARAMS &params) ;
 
+// Build a histogram of the background
+// - Start and end mass, and step size (to get bin count).
+// tofBackIntensity is the intensity level per unit time in the background, as obtained by doFitBackground
+// the histogram is 
+void createMassBackground(float massStart, float massEnd, unsigned int nBinsMass,
+			float tofBackIntensity, vector<float> &histogram);
+
 
 //Anderson. test statistic for gaussian-ness. Returns false if input has insufficient points for test (2 items)
 //Implented for unknown (derived from data) mean & variance
@@ -194,7 +202,7 @@ bool testAnderson();
 
 //Check that the background fitting routine can fit
 // a random TOF data histogram
-bool testBackgroundFit();
+bool testBackgroundFitMaths();
 
 #endif
 #endif
diff --git a/src/backend/filters/algorithms/rdf.cpp b/src/backend/filters/algorithms/rdf.cpp
index ec65877..453b21f 100644
--- a/src/backend/filters/algorithms/rdf.cpp
+++ b/src/backend/filters/algorithms/rdf.cpp
@@ -193,7 +193,7 @@ unsigned int GetReducedHullPts(const vector<Point3D> &points, float reductionDim
 
 	unsigned int dummyProg;
 	vector<Point3D> theHull;
-	if(computeConvexHull(points,progress,wantAbort,theHull,false))
+	if(computeConvexHull(points,progress,wantAbort,theHull,false,false))
 		return 2;
 
 	Point3D midPoint(0,0,0);
@@ -1044,5 +1044,16 @@ void generateKnnTheoreticalDist(const std::vector<float> &radii, float density,
 
 }
 
+bool qhullTest()
+{
+#if defined(__WIN64)
+	//If using a cross-compile (at least)
+	// qhull under win64 must use long long, or we get random crashes
+	// The definition is set in qhull/mem.h
+	COMPILE_ASSERT(sizeof(ptr_intT) == sizeof(long long))
+#endif
+
+	return true;
+}
 
 
diff --git a/src/backend/filters/allFilter.cpp b/src/backend/filters/allFilter.cpp
index fa83474..78a206a 100644
--- a/src/backend/filters/allFilter.cpp
+++ b/src/backend/filters/allFilter.cpp
@@ -80,8 +80,8 @@ Filter *makeFilter(unsigned int ui)
 		case FILTER_TYPE_IONINFO:
 			f=new IonInfoFilter;
 			break;
-		case FILTER_TYPE_COMPOSITION:
-			f=new CompositionProfileFilter;
+		case FILTER_TYPE_PROFILE:
+			f=new ProfileFilter;
 			break;
 		case FILTER_TYPE_BOUNDBOX:
 			f = new BoundingBoxFilter;
diff --git a/src/backend/filters/allFilter.h b/src/backend/filters/allFilter.h
index b3ae895..00b18bb 100644
--- a/src/backend/filters/allFilter.h
+++ b/src/backend/filters/allFilter.h
@@ -20,7 +20,7 @@
 #include "boundingBox.h"
 #include "ionDownsample.h"
 #include "dataLoad.h"
-#include "compositionProfile.h"
+#include "profile.h"
 #include "externalProgram.h"
 #include "ionClip.h"
 #include "ionColour.h"
diff --git a/src/backend/filters/annotation.cpp b/src/backend/filters/annotation.cpp
index f3e253f..c7efaf4 100644
--- a/src/backend/filters/annotation.cpp
+++ b/src/backend/filters/annotation.cpp
@@ -1161,7 +1161,8 @@ bool AnnotateFilter::setProperty(  unsigned int key,
 		case KEY_LINESIZE:
 		{
 			float tmp;
-			stream_cast(tmp,value);
+			if(stream_cast(tmp,value))
+				return false;
 
 			if(tmp == lineSize || tmp <0)
 				return false;
diff --git a/src/backend/filters/boundingBox.cpp b/src/backend/filters/boundingBox.cpp
index 005758d..d42cdd7 100644
--- a/src/backend/filters/boundingBox.cpp
+++ b/src/backend/filters/boundingBox.cpp
@@ -38,7 +38,11 @@ enum
 	KEY_SPACING_X,
 	KEY_SPACING_Y,
 	KEY_SPACING_Z,
-	KEY_STYLE
+	KEY_SHOW_TICKS_X,
+	KEY_SHOW_TICKS_Y,
+	KEY_SHOW_TICKS_Z,
+	KEY_STYLE,
+	KEY_ABSCOORDS
 };
 
 enum
@@ -67,12 +71,14 @@ const char *BOUND_STYLE[] =
 
 
 BoundingBoxFilter::BoundingBoxFilter() : isVisible(true), boundStyle(BOUND_STYLE_TICKS),
-	fixedNumTicks(true), fontSize(5), lineColour(0,0,1.0f), lineWidth(2.0f), threeDText(true)
+	fixedNumTicks(true), fontSize(5), absoluteCoords(false),
+	lineColour(0,0,1.0f), lineWidth(2.0f), threeDText(true)
 {
 	for(unsigned int ui=0;ui<3;ui++)
 	{
 		numTicks[ui]=12;
 		tickSpacing[ui]=5.0f;
+		enableTicks[ui]=true;
 	}
 
 	cacheOK=false;
@@ -87,11 +93,12 @@ Filter *BoundingBoxFilter::cloneUncached() const
 	{
 		p->numTicks[ui]=numTicks[ui];
 		p->tickSpacing[ui]=tickSpacing[ui];
+		p->enableTicks[ui]=enableTicks[ui];
 	}
 
 	p->isVisible=isVisible;
 	p->boundStyle=boundStyle;
-
+	p->absoluteCoords = absoluteCoords;
 
 	p->threeDText=threeDText;	
 
@@ -108,8 +115,8 @@ Filter *BoundingBoxFilter::cloneUncached() const
 
 size_t BoundingBoxFilter::numBytesForCache(size_t nObjects) const
 {
-	//Say we don't know, we are not going to cache anyway.
-	return (size_t)-1;
+	//we don't really know without examining full data. but guess
+	return (size_t)10000;
 }
 
 void BoundingBoxFilter::drawTicks(const BoundCube &bTotal, DrawStreamData *d) const
@@ -147,9 +154,16 @@ void BoundingBoxFilter::drawTicks(const BoundCube &bTotal, DrawStreamData *d) co
 		}
 	}
 
+	//flag to see if we have to draw the 0 corner later on
+	bool tickSet=false;
 	//Draw the ticks on the box perimeter.
 	for(unsigned int ui=0;ui<3;ui++)
 	{
+		if(!enableTicks[ui])
+			continue;
+
+		tickSet=true;
+
 		Point3D tickVector;
 		Point3D tickPosition;
 		Point3D textVector;
@@ -201,7 +215,12 @@ void BoundingBoxFilter::drawTicks(const BoundCube &bTotal, DrawStreamData *d) co
 				else
 					dT = new DrawGLText(getDefaultFontFile().c_str(),FTGL_BITMAP);
 				float f;
-				f = tmpTickSpacing[ui]*uj;
+				if(absoluteCoords)
+				{
+					f = tmpTickSpacing[ui]*uj + tickOrigin[ui];
+				}
+				else
+					f = tmpTickSpacing[ui]*uj;
 				snprintf(buffer,127,"%2.0f",f);
 				dT->setString(buffer);
 				dT->setSize(fontSize);
@@ -219,22 +238,27 @@ void BoundingBoxFilter::drawTicks(const BoundCube &bTotal, DrawStreamData *d) co
 
 	}
 
-	DrawGLText *dT; 
-	if(threeDText)
-		dT = new DrawGLText(getDefaultFontFile().c_str(),FTGL_POLYGON);
-	else
-		dT = new DrawGLText(getDefaultFontFile().c_str(),FTGL_BITMAP);
-	//Handle "0" text value
-	dT->setString("0");
-	
-	dT->setColour(lineColour.r(),lineColour.g(),
-		lineColour.b(),lineColour.a());
-	dT->setSize(fontSize);
-	dT->setOrigin(tickOrigin+ Point3D(-1,-1,-1));
-	dT->setAlignment(DRAWTEXT_ALIGN_RIGHT);
-	dT->setUp(Point3D(0,0,1));	
-	dT->setTextDir(Point3D(-1,-1,0));
-	d->drawables.push_back(dT);
+
+	if(!absoluteCoords && tickSet)
+	{
+		DrawGLText *dT; 
+		if(threeDText)
+			dT = new DrawGLText(getDefaultFontFile().c_str(),FTGL_POLYGON);
+		else
+			dT = new DrawGLText(getDefaultFontFile().c_str(),FTGL_BITMAP);
+
+		//Handle "0" text value
+		dT->setString("0");
+		
+		dT->setColour(lineColour.r(),lineColour.g(),
+			lineColour.b(),lineColour.a());
+		dT->setSize(fontSize);
+		dT->setOrigin(tickOrigin+ Point3D(-1,-1,-1));
+		dT->setAlignment(DRAWTEXT_ALIGN_RIGHT);
+		dT->setUp(Point3D(0,0,1));	
+		dT->setTextDir(Point3D(-1,-1,0));
+		d->drawables.push_back(dT);
+	}
 
 }
 
@@ -284,6 +308,9 @@ void BoundingBoxFilter::drawDimension(const BoundCube &bTotal, DrawStreamData *d
 	//Draw the arrows around the edge of the box
 	for(size_t ui=0;ui<3;ui++)
 	{
+		if(!enableTicks[ui])
+			continue;
+
 		float len;
 		len=(tickEnd[ui]-tickOrigin[ui])*0.5f;
 	
@@ -318,20 +345,34 @@ void BoundingBoxFilter::drawDimension(const BoundCube &bTotal, DrawStreamData *d
 	char *buffer=new char[128];
 	for(size_t ui=0;ui<3;ui++)
 	{
+		if(!enableTicks[ui])
+			continue;
+
 		BoundCube textCube;
 		DrawGLText *dT;
 		dT = new DrawGLText(getDefaultFontFile().c_str(),FTGL_POLYGON);
 
-		float len;
-		len=(tickEnd[ui]-tickOrigin[ui]);
+		if(!absoluteCoords)
+		{
+			float len;
+			len=(tickEnd[ui]-tickOrigin[ui]);
+
+			snprintf(buffer,127,"%5.1f",len);
+		}
+		else
+		{
+			snprintf(buffer,127,"%5.1f , %5.1f",
+				tickOrigin[ui], tickEnd[ui]);
 
-		snprintf(buffer,127,"%5.1f",len);
+		}
 		dT->setString(buffer);
 		dT->setSize(fontSize);
 
 		dT->setColour(lineColour.r(),lineColour.g(),
 				lineColour.b(),lineColour.a());
 		dT->setOrigin(centrePt[ui]);	
+		dT->setAlignment(DRAWTEXT_ALIGN_CENTRE);
+		
 		switch(ui)
 		{
 			case 0:
@@ -349,7 +390,6 @@ void BoundingBoxFilter::drawDimension(const BoundCube &bTotal, DrawStreamData *d
 				break;
 		}
 
-		dT->setAlignment(DRAWTEXT_ALIGN_CENTRE);
 
 		d->drawables.push_back(dT);
 	}
@@ -616,6 +656,34 @@ void BoundingBoxFilter::getProperties(FilterPropGroup &propertyList) const
 				p.helpText=TRANS("Distance between ticks on Z axis");
 				propertyList.addProperty(p,curGroup);
 			}
+		}
+
+		if(boundStyle!=BOUND_STYLE_BOX_ONLY)
+		{	
+			tmpStr=boolStrEnc(enableTicks[0]);	
+			p.name=TRANS("Ticks X");
+			p.data= tmpStr;
+			p.key=KEY_SHOW_TICKS_X;
+			p.type=PROPERTY_TYPE_BOOL;
+			p.helpText=TRANS("Display tick marks on X axis");
+			propertyList.addProperty(p,curGroup);
+
+			tmpStr=boolStrEnc(enableTicks[1]);	
+			p.name=TRANS("Ticks Y");
+			p.data= tmpStr;
+			p.key=KEY_SHOW_TICKS_Y;
+			p.type=PROPERTY_TYPE_BOOL;
+			p.helpText=TRANS("Display tick marks on Y axis");
+			propertyList.addProperty(p,curGroup);
+			
+			tmpStr=boolStrEnc(enableTicks[2]);	
+			p.name=TRANS("Ticks Z");
+			p.data= tmpStr;
+			p.key=KEY_SHOW_TICKS_Z;
+			p.type=PROPERTY_TYPE_BOOL;
+			p.helpText=TRANS("Display tick marks on Z axis");
+			propertyList.addProperty(p,curGroup);
+
 			propertyList.setGroupTitle(curGroup,TRANS("Tick marks"));
 
 		}
@@ -649,6 +717,15 @@ void BoundingBoxFilter::getProperties(FilterPropGroup &propertyList) const
 			p.type=PROPERTY_TYPE_INTEGER;
 			p.helpText=TRANS("Relative size for text");
 			propertyList.addProperty(p,curGroup);
+
+			
+			p.key=KEY_ABSCOORDS;
+			p.name=TRANS("Abs. Coords");
+			p.data = boolStrEnc(absoluteCoords);
+			p.type=PROPERTY_TYPE_BOOL;
+			p.helpText=TRANS("Show labels using aboslute coo-ordinates");
+	
+			propertyList.addProperty(p,curGroup);
 		}
 	}
 	propertyList.setGroupTitle(curGroup,TRANS("Appearance"));
@@ -759,12 +836,30 @@ bool BoundingBoxFilter::setProperty(  unsigned int key,
 			needUpdate=true;
 			break;
 		}
+		case KEY_SHOW_TICKS_X:
+		case KEY_SHOW_TICKS_Y:
+		case KEY_SHOW_TICKS_Z:
+		{
+			bool enabled;
+			if(stream_cast(enabled,value))
+				return false;
+
+			enableTicks[key-KEY_SHOW_TICKS_X]=enabled;
+			needUpdate=true;
+			break;
+		}
 		case KEY_FONTSIZE:
 		{
 			if(!applyPropertyNow(fontSize,value,needUpdate))
 				return false;
 			break;
 		}
+		case KEY_ABSCOORDS:
+		{
+			if(!applyPropertyNow(absoluteCoords,value,needUpdate))
+				return false;
+			break;
+		}
 		default:
 			ASSERT(false);
 	}	
@@ -800,10 +895,13 @@ bool BoundingBoxFilter::writeState(std::ostream &f,unsigned int format, unsigned
 				<< numTicks[1] << "\" z=\""<< numTicks[2] <<"\"/>"  << endl;
 			f << tabs(depth+1) << "<tickspacing x=\""<<tickSpacing[0]<< "\" y=\"" 
 				<< tickSpacing[1] << "\" z=\""<< tickSpacing[2] <<"\"/>"  << endl;
+			f << tabs(depth+1) << "<ticksenabled x=\""<<enableTicks[0]<< "\" y=\"" 
+				<< enableTicks[1] << "\" z=\""<< enableTicks[2] <<"\"/>"  << endl;
 			f << tabs(depth+1) << "<linewidth value=\"" << lineWidth << "\"/>"<<endl;
 			f << tabs(depth+1) << "<fontsize value=\"" << fontSize << "\"/>"<<endl;
 			f << tabs(depth+1) << "<colour r=\"" <<  lineColour.r()<< "\" g=\"" << lineColour.g() << "\" b=\"" <<lineColour.b()  
 								<< "\" a=\"" << lineColour.a() << "\"/>" <<endl;
+			f << tabs(depth+1) << "<absolutecoords value=\"" << boolStrEnc(absoluteCoords) << "\"/>" << endl;
 			f << tabs(depth) << "</" <<trueName()<< ">" << endl;
 			break;
 		}
@@ -957,6 +1055,36 @@ bool BoundingBoxFilter::readState(xmlNodePtr &nodePtr, const std::string &stateF
 		return false;
 	xmlFree(xmlString);
 	//====
+
+	//Retrieve ticks enabled (3Depict > 0.0.18)
+	//===
+	xmlNodePtr tmpNode=nodePtr;
+	if(XMLHelpFwdToElem(nodePtr,"ticksenabled"))
+	{
+		//loading failed, use default (enabled)
+		for(unsigned int ui=0; ui<3; ui++)
+			enableTicks[ui] =true;
+
+		nodePtr=tmpNode;
+	}
+	else
+	{
+		const char *XYZ[]={"x","y","z"};
+		for(unsigned int ui=0;ui<3;ui++)
+		{
+			xmlString=xmlGetProp(nodePtr,(const xmlChar *)XYZ[ui]);
+			if(!xmlString)
+				return false;
+			tmpStr=(char *)xmlString;
+
+			if(!boolStrDec(tmpStr,enableTicks[ui]))
+				return false;
+
+			xmlFree(xmlString);
+		}
+	}
+
+	//===
 	
 	//Retrieve line width 
 	//====
@@ -1005,6 +1133,20 @@ bool BoundingBoxFilter::readState(xmlNodePtr &nodePtr, const std::string &stateF
 	lineColour=tmpCol;
 	//====
 
+	//Retrieve absolute coordinates (only for 3Depict > 0.0.18) 
+	//====
+	if(XMLHelpFwdToElem(nodePtr,"absolutecoords"))
+		absoluteCoords=false;
+	else
+	{
+		std::string s;
+		if(XMLHelpGetProp(s,nodePtr,"value"))
+			return false;
+		if(!boolStrDec(s,absoluteCoords))
+			return false;
+	}
+	//====
+
 	return true;	
 }
 
diff --git a/src/backend/filters/boundingBox.h b/src/backend/filters/boundingBox.h
index db77d65..aeb5cd3 100644
--- a/src/backend/filters/boundingBox.h
+++ b/src/backend/filters/boundingBox.h
@@ -36,9 +36,13 @@ class BoundingBoxFilter : public Filter
 		unsigned int numTicks[3];
 		//!Spacing of ticks (XYZ) if using fixed spacing ticks
 		float tickSpacing[3];
+
+		//!Enable/disable ticks on a given axis
+		bool enableTicks[3];
 		//!Font size
 		unsigned int fontSize;
-
+		//!Should we use absolute coordinate values in box labels?
+		bool absoluteCoords;
 		//!Line colour
 		ColourRGBAf lineColour;
 		//!Line width 
diff --git a/src/backend/filters/clusterAnalysis.cpp b/src/backend/filters/clusterAnalysis.cpp
index 158bde4..7818a3b 100644
--- a/src/backend/filters/clusterAnalysis.cpp
+++ b/src/backend/filters/clusterAnalysis.cpp
@@ -19,6 +19,7 @@
 #include "filterCommon.h"
 
 #include <queue>
+#include <algorithm>
 
 #include <gsl/gsl_linalg.h>
 #include <gsl/gsl_eigen.h>
@@ -54,6 +55,7 @@ enum
 	KEY_SIZE_COUNT_BULK,
 	KEY_CROP_NMIN,
 	KEY_CROP_NMAX,
+	KEY_BULK_ALL,
 	KEY_CORE_OFFSET=100000,
 	KEY_BULK_OFFSET=200000
 };
@@ -90,6 +92,11 @@ using std::vector;
 const float SPHERE_PRESEARCH_CUTOFF = 75;
 
 
+//In link clustering, when we preform size cropping, do we awant to count bulk ions in our analysis?
+const bool WANT_COUNT_BULK_FORCROP=false;
+
+
+
 void makeFrequencyTable(const IonStreamData *i ,const RangeFile *r, 
 				std::vector<std::pair<string,size_t> > &freqTable) 
 {
@@ -102,6 +109,9 @@ void makeFrequencyTable(const IonStreamData *i ,const RangeFile *r,
 #else
 	numThreads=1;
 #endif
+
+	//Create a series of independent vectors,that we can sum into seperately,
+	// based upon the number of threads
 	vector<size_t *> ionHist;
 	ionHist.resize(numThreads);
 
@@ -147,6 +157,8 @@ void makeFrequencyTable(const IonStreamData *i ,const RangeFile *r,
 	for(size_t uj=0;uj<r->getNumIons();uj++)
 		freqTable.push_back(make_pair(r->getName(uj),ionHist[0][uj]));
 
+	for(size_t ui=0;ui<numThreads;ui++)
+		delete[] ionHist[ui];
 }
 
 void makeCompositionTable(const IonStreamData *i ,const RangeFile *r, 
@@ -264,8 +276,6 @@ ClusterAnalysisFilter::ClusterAnalysisFilter() : algorithm(CLUSTER_LINK_ERODE),
 	wantClusterMorphology(false), haveRangeParent(false)
 
 {
-	//haveRangeParent=false; //Initialiser sets this to false, as required by ::initFilter
-
 	cacheOK=false;
 
 	//By default, we should cache, but final decision is made higher up
@@ -557,7 +567,7 @@ unsigned int ClusterAnalysisFilter::refresh(const std::vector<const FilterStream
 		paranoidDebugAssert(clusteredCore,clusteredBulk);
 #endif
 	if(wantCropSize)
-		stripClusterBySize(clusteredCore,clusteredBulk,progress);
+		stripClusterBySize(clusteredCore,clusteredBulk,WANT_COUNT_BULK_FORCROP,progress);
 
 	bool haveBulk,haveCore;
 	haveBulk=clusteredBulk.size();
@@ -800,20 +810,30 @@ ASSERT(!(haveBulk && !haveCore));
 	if(wantClusterID)
 	{
 
+		//To prevent clusters ID from correlatiing with their position
+		// which results in odd visual effects, randomise the ID a litlle;
+		vector<size_t> idShuffle;
+		idShuffle.resize(clusteredCore.size());
+
+		for(unsigned int ui=0;ui<idShuffle.size();ui++)
+			idShuffle[ui]=ui;
+
+		std::random_shuffle(idShuffle.begin(),idShuffle.end());
+
 		#pragma omp parallel
 		{
 		#pragma omp for
 		for(size_t ui=0;ui<clusteredCore.size();ui++)
 		{
 			for(size_t uj=0;uj<clusteredCore[ui].size();uj++)
-				clusteredCore[ui][uj].setMassToCharge(ui);
+				clusteredCore[ui][uj].setMassToCharge(idShuffle[ui]);
 		}
 	
 		#pragma omp for
 		for(size_t ui=0;ui<clusteredBulk.size();ui++)
 		{
 			for(size_t uj=0;uj<clusteredBulk[ui].size();uj++)
-				clusteredBulk[ui][uj].setMassToCharge(ui);
+				clusteredBulk[ui][uj].setMassToCharge(idShuffle[ui]);
 		}
 		}
 	}
@@ -985,23 +1005,23 @@ void ClusterAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 			p.helpText=TRANS("Distance from core points that form cluster that is used to grab surrounding bulk points");
 			p.key=KEY_BULKLINK;
 			propertyList.addProperty(p,curGroup);
-		}
 		
-		p.name=TRANS("Erosion");
-		p.data=boolStrEnc(enableErosion);
-		p.type=PROPERTY_TYPE_BOOL;
-		p.helpText=TRANS("Enable  linking of non-cluster species - eg for composition analysis ");
-		p.key=KEY_ERODE_ENABLE;
-		propertyList.addProperty(p,curGroup);
-		if(enableErosion)
-		{
-			stream_cast(tmpStr,dErosion);
-			p.name=TRANS("Erode Dist");
-			p.data=tmpStr;
-			p.type=PROPERTY_TYPE_REAL;
-			p.helpText=TRANS("Distance from unclustered material in which bulk points are eroded from cluster");
-			p.key=KEY_ERODEDIST;
+			p.name=TRANS("Erosion");
+			p.data=boolStrEnc(enableErosion);
+			p.type=PROPERTY_TYPE_BOOL;
+			p.helpText=TRANS("Enable  linking of non-cluster species - eg for composition analysis ");
+			p.key=KEY_ERODE_ENABLE;
 			propertyList.addProperty(p,curGroup);
+			if(enableErosion)
+			{
+				stream_cast(tmpStr,dErosion);
+				p.name=TRANS("Erode Dist");
+				p.data=tmpStr;
+				p.type=PROPERTY_TYPE_REAL;
+				p.helpText=TRANS("Distance from unclustered material in which bulk points are eroded from cluster");
+				p.key=KEY_ERODEDIST;
+				propertyList.addProperty(p,curGroup);
+			}
 		}
 	}
 	
@@ -1098,7 +1118,7 @@ void ClusterAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 	
 	curGroup++;
 
-	if(haveRangeParent)
+	if(haveRangeParent && ionNames.size())
 	{	
 		//Offset markers are used elsewhere. Must be in sync with
 		//this code	
@@ -1123,6 +1143,16 @@ void ClusterAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 
 		if(enableBulkLink)
 		{
+			
+			p.name=TRANS("Enable/Disable All");
+			bool allEnabled=false;
+			allEnabled=(std::find(ionBulkEnabled.begin(),ionBulkEnabled.end(),false) == ionBulkEnabled.end());
+			p.data=boolStrEnc(allEnabled);
+			p.type=PROPERTY_TYPE_BOOL;
+			p.helpText=TRANS("Enable/disable all ions");
+			p.key=KEY_BULK_ALL;
+			propertyList.addProperty(p,curGroup);
+
 			for(size_t ui=0;ui<ionNames.size();ui++)
 			{
 				if(ionBulkEnabled[ui])
@@ -1483,6 +1513,20 @@ bool ClusterAnalysisFilter::setProperty(unsigned int key,
 			
 			break;
 		}
+		case KEY_BULK_ALL:
+		{
+			ASSERT(enableBulkLink);
+			bool bVal;
+			boolStrDec(value,bVal);
+			std::fill(ionBulkEnabled.begin(),ionBulkEnabled.end(),bVal);
+		
+			//we have to maintain the core selection, so that
+			//both core and bulk are not set at the same time
+			if(bVal)
+				std::fill(ionCoreEnabled.begin(),ionCoreEnabled.end(),!bVal);
+
+			break;
+		}
 		default:
 		{
 			ASSERT( key >=KEY_CORE_OFFSET);
@@ -1864,12 +1908,13 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 	//
 	// In the implementation, there are more steps, due to data structure construction
 	// and other computational concerns
+
 	
 	bool needErosion=enableErosion && enableBulkLink;
 	unsigned int numClusterSteps=4;
 	if(enableBulkLink)
 		numClusterSteps+=2;
-	if(needErosion)
+	if(needErosion && enableBulkLink)
 		numClusterSteps++;
 	if(enableCoreClassify)
 		numClusterSteps++;
@@ -1961,13 +2006,10 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 		
 
 	vector<vector<size_t> > allCoreClusters,allBulkClusters;
-	const float linkDistSqr=linkDist*linkDist;
-	
 	//When this queue is exhausted, move to the next cluster
 	for(size_t ui=0;ui<coreTree.size();ui++)
 	{
 		size_t curPt;
-		float curDistSqr;
 		//Indicies of each cluster
 		vector<size_t> soluteCluster,dummy;
 		//Queue for atoms in this cluster waiting to be checked
@@ -1981,66 +2023,51 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 		coreTree.tag(ui);
 
 	
-	
-		size_t clustIdx;
+		//If the atom is not clustered, use it as a point from 
+		//which we start a search	
 		thisClusterQueue.push(ui);
 		soluteCluster.push_back(ui);
+	
+		//Keep looping throughe queue until it is exhausted
 		do
 		{
+			//search atom's position
 			curPt=thisClusterQueue.front();
-			const Point3D *thisPt;
-			thisPt=coreTree.getPt(curPt);
-			curDistSqr=0;
 
+			//Find all the points in a sphere around this one
+			vector<size_t> nnIdxs;
+			coreTree.ptsInSphere(*(coreTree.getPt(curPt)),linkDist,nnIdxs);
 
-
-			//Now loop over this solute's NNs not found by prev. method
-			while(true)
+			//Loop over this solute's NNs
+			for(size_t uj=0;uj<nnIdxs.size();uj++)
 			{
+				size_t clustIdx;
 				ASSERT(curPt < coreTree.size());
-				//Find the next point that we have not yet retrieved
+				//Find the next point that we have not yet retreived
 				//the find will tag the point, so we won't see it again
 				ASSERT(bCore.isValid());
-				clustIdx=coreTree.findNearestUntagged(
-						*thisPt,bCore, true);
-
-
-				ASSERT(clustIdx == (size_t)-1 || coreTree.getTag(clustIdx));
-				if(clustIdx != (size_t)-1)
-				{
-					curDistSqr=coreTree.getPt(clustIdx)->sqrDist(
-							*(coreTree.getPt(curPt)) );
+				clustIdx=nnIdxs[uj];
 
-				}
+				//Record it as part of the cluster	
 
-				//Point out of clustering range, or no more points
-				if(clustIdx == (size_t)-1 || curDistSqr > linkDistSqr)
-				{
-					//If the point was not tagged,
-					//Un-tag the point; as it was too far away
-					if(clustIdx !=(size_t)-1)
-						coreTree.tag(clustIdx,false);
-					
-					thisClusterQueue.pop();
-					break;
-				}
-				else
+				if(!coreTree.getTag(clustIdx))
 				{
-					//Record it as part of the cluster	
 					thisClusterQueue.push(clustIdx);
 					soluteCluster.push_back(clustIdx);
+					//tag point as visited
+					coreTree.tag(clustIdx);
 				}
-			
-
-				//Progress may be a little non-linear if cluster sizes are not random
-				progress.filterProgress= (unsigned int)(((float)ui/(float)coreTree.size())*100.0f);
-				if(*Filter::wantAbort)
-					return FILTER_ERR_ABORT;
 			}
 
 
-		} // Keep looping whilst we have coreTree to cluster.
-		while(!thisClusterQueue.empty() && clustIdx !=(size_t)-1);
+			//Progress may be a little non-linear if cluster sizes are not random
+			progress.filterProgress= (unsigned int)(((float)ui/(float)coreTree.size())*100.0f);
+			if(*Filter::wantAbort)
+				return FILTER_ERR_ABORT;
+
+			thisClusterQueue.pop();
+
+		}while(!thisClusterQueue.empty());
 			
 
 		if(soluteCluster.size())
@@ -2059,7 +2086,7 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 		return FILTER_ERR_ABORT;
 
 	//NOTE : Speedup trick. If we know the cluster size at this point
-	// and we know we don't want to count the bulk, we can strip out clusters
+	// we can strip out clusters
 	// now, as we are going to do that anyway as soon as we return from our cluster
 	// computation.
 	// The advantage to doing it now is that we can (potentially) drop lots of clusters
@@ -2070,7 +2097,9 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 		{
 			size_t count;
 			count =allCoreClusters[ui].size();
-			if(count < nMin || count > nMax)
+			//If we are not counting the bulk, then we can check nMin,
+			// as we know the cluster wont get any larger
+			if( (!WANT_COUNT_BULK_FORCROP && count < nMin ) || count > nMax)
 			{
 				allCoreClusters.back().swap(allCoreClusters[ui]);
 				allCoreClusters.pop_back();
@@ -2102,19 +2131,13 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 		{
 			bulkTree.getBoundCube(bBulk);
 
-			//Compute the expected number of points that we would encapsulate
-			//if we were to place  a sphere of size bulkLink in the KD domain.
-			// This allows us to choose whether to use a bulk "grab" approach, or not.
-			bool expectedPtsInSearchEnough;
-			expectedPtsInSearchEnough=((float)bulkTree.size())/bBulk.volume()*4.0/3.0*M_PI*pow(bulkLink,3.0f)> SPHERE_PRESEARCH_CUTOFF;
-
 			//So-called "envelope" step.
-			float bulkLinkSqr=bulkLink*bulkLink;
 			size_t prog=PROGRESS_REDUCE;
 			//Now do the same thing with the matrix, but use the clusters as the "seed"
 			//positions
 			for(size_t ui=0;ui<allCoreClusters.size();ui++)
 			{
+
 				//The bulkTree component of the cluster
 				vector<size_t> thisBulkCluster,dummy;
 				for(size_t uj=0;uj<allCoreClusters[ui].size();uj++)
@@ -2122,84 +2145,38 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 					size_t curIdx;
 					curIdx=allCoreClusters[ui][uj];
 
-					const Point3D *curPt;
-					curPt=(coreTree.getPt(curIdx));
-
+					//Scan for bulkTree NNs.
+					vector<size_t> nnIdxs;
+					bulkTree.ptsInSphere(*(coreTree.getPt(curIdx)),bulkLink,nnIdxs);
 
-					//First do a grab of any sub-regions for cur pt
-					// based upon intersecting KD regions
-					// For readability, I have not factored this
-					// out of the loop; it should not have  a giant performance
-					// cost.
-					//---
-					if(expectedPtsInSearchEnough)
+					//loop over the points we found
+					for(unsigned int uj=0;uj<nnIdxs.size();uj++)
 					{
-						vector<pair<size_t,size_t> > blocks;
-						bulkTree.getTreesInSphere(*curPt,bulkLinkSqr,bBulk,blocks);
-
-						for(size_t uj=0; uj<blocks.size();uj++)
-						{
-							for(size_t uk=blocks[uj].first; uk<=blocks[uj].second;uk++)
-							{
-								if(!bulkTree.getTag(uk))
-								{
-									//Tag, then record it as part of the cluster	
-									bulkTree.tag(uk);
-									thisBulkCluster.push_back(uk);
-								}
-							}
-
-						}
+						size_t bulkTreeIdx;
+						bulkTreeIdx=nnIdxs[uj];
+				
+						ASSERT(bulkTree.getPt(nnIdxs[uj])->sqrDist(
+						*(coreTree.getPt(curIdx)))< bulkLink*bulkLink);
+						if(bulkTree.getTag(bulkTreeIdx))
+							continue;
+
+						//Record as part of the cluster	
+						thisBulkCluster.push_back(bulkTreeIdx);
+						bulkTree.tag(bulkTreeIdx);
 					}
 
-					//--
-
-
-
-					//Scan for bulkTree NN.
-					while(true)
+						
+					//Update progress data as needed	
+					if(prog <=nnIdxs.size())
 					{
-						size_t bulkTreeIdx;
-						float curDistSqr;
-						//Find the next point that we have not yet retrieved
-						//the find will tag the point, so we won't see it again
-						bulkTreeIdx=bulkTree.findNearestUntagged(
-								*curPt,bBulk, true);
-			
-
-						if(bulkTreeIdx !=(size_t)-1)
-						{
-							curDistSqr=bulkTree.getPt(
-								bulkTreeIdx)->sqrDist(*curPt);
-						}
-
-						//Point out of clustering range, or no more points
-						if(bulkTreeIdx == (size_t)-1 || curDistSqr > bulkLinkSqr )
-						{
-							//Un-tag the point; as it was too far away
-							if(bulkTreeIdx !=(size_t)-1)
-								bulkTree.tag(bulkTreeIdx,false);
-							break;
-						}
-						else
-						{
-							//Record it as part of the cluster	
-							thisBulkCluster.push_back(bulkTreeIdx);
-						}
-					
-						prog--;	
-						if(!prog)
-						{
-							prog=PROGRESS_REDUCE;
-							//Progress may be a little non-linear if cluster sizes are not random
-							progress.filterProgress= (unsigned int)(((float)ui/(float)allCoreClusters.size())*100.0f);
-							if(*Filter::wantAbort)
-								return FILTER_ERR_ABORT;
-
-						}
+						prog=PROGRESS_REDUCE;
+						//Progress may be a little non-linear if cluster sizes are not random
+						progress.filterProgress= (unsigned int)(((float)ui/(float)allCoreClusters.size())*100.0f);
+						if(*Filter::wantAbort)
+							return FILTER_ERR_ABORT;
 					}
-
-					
+					else
+						prog-=nnIdxs.size();	
 
 				}
 
@@ -2219,7 +2196,7 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 	//Step 4 in the  Process : Bulk erosion 
 	//====
 	//Check if we need the erosion step
-	if(needErosion)
+	if(needErosion && enableBulkLink)
 	{
 		//Update progress stuff
 		progress.step++;
@@ -2296,13 +2273,14 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 	}
 	//===
 
+	if(*Filter::wantAbort)
+		return FILTER_ERR_ABORT;
+
+	//update progress
 	progress.step++;
 	progress.filterProgress=0;
 	progress.stepName=TRANS("Re-Collate");
 
-	//update progress
-	if(*Filter::wantAbort)
-		return FILTER_ERR_ABORT;
 	clusteredCore.resize(allCoreClusters.size());
 	clusteredBulk.resize(allBulkClusters.size());
 
@@ -2332,6 +2310,7 @@ unsigned int ClusterAnalysisFilter::refreshLinkClustering(const std::vector<cons
 		}
 	}
 
+	progress.filterProgress=100;
 
 	return 0;	
 }
@@ -2574,9 +2553,10 @@ void ClusterAnalysisFilter::createRangedIons(const std::vector<const FilterStrea
 	buildRangeEnabledMap(r,rangeEnabledMap);
 	ASSERT(rangeEnabledMap.size() == ionCoreEnabled.size());
 
-	bool needBulk = bulkLink > std::numeric_limits<float>::epsilon();
 
-	if(needBulk)
+	unsigned int numIonsRanged=0;
+
+	if(enableBulkLink)
 	{
 		for(size_t ui=0;ui<dataIn.size();ui++)
 		{
@@ -2603,6 +2583,7 @@ void ClusterAnalysisFilter::createRangedIons(const std::vector<const FilterStrea
 						}
 					}
 				}
+				numIonsRanged++;
 			}
 		
 		
@@ -2626,6 +2607,7 @@ void ClusterAnalysisFilter::createRangedIons(const std::vector<const FilterStrea
 						#pragma omp critical 
 						core.push_back(d->data[ui]);
 					}
+					numIonsRanged++;
 				}
 			}
 		}
@@ -2708,6 +2690,7 @@ PlotStreamData* ClusterAnalysisFilter::clusterSizeDistribution(const vector<vect
 
 bool ClusterAnalysisFilter::stripClusterBySize(vector<vector<IonHit> > &clusteredCore,
 						vector<vector<IonHit> > &clusteredBulk,
+							bool countBulk,
 							ProgressData &progress) const
 
 {
@@ -2725,7 +2708,10 @@ bool ClusterAnalysisFilter::stripClusterBySize(vector<vector<IonHit> > &clustere
 			ui--;
 			//Count both bulk and core, and operate on both.
 			size_t count;
-			count =clusteredCore[ui].size() + clusteredBulk[ui].size() ;
+			if(countBulk)
+				count =clusteredCore[ui].size() + clusteredBulk[ui].size() ;
+			else
+				count =clusteredCore[ui].size();
 
 			if(count < nMin || count > nMax)
 			{
diff --git a/src/backend/filters/clusterAnalysis.h b/src/backend/filters/clusterAnalysis.h
index 0ffa88e..448fad3 100644
--- a/src/backend/filters/clusterAnalysis.h
+++ b/src/backend/filters/clusterAnalysis.h
@@ -105,6 +105,7 @@ class ClusterAnalysisFilter : public Filter
 		//Strip out clusters with a given number of elements
 		bool stripClusterBySize(std::vector<std::vector<IonHit> > &clusteredCore,
 						std::vector<std::vector<IonHit> > &clusteredBulk,
+							bool countBulk,
 							ProgressData &p) const;
 		//Build a plot that is the cluster size distribution as a function of cluster size
 		PlotStreamData *clusterSizeDistribution(const std::vector<std::vector<IonHit> > &solutes, 
diff --git a/src/backend/filters/compositionProfile.cpp b/src/backend/filters/compositionProfile.cpp
deleted file mode 100644
index b613e37..0000000
--- a/src/backend/filters/compositionProfile.cpp
+++ /dev/null
@@ -1,1972 +0,0 @@
-/*
- *	compositionProfile.cpp - Compute composition profiles from valued point clouds
- *	Copyright (C) 2015, D Haley 
-
- *	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 3 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/>.
-*/
-#include "compositionProfile.h"
-#include "../plot.h"
-
-#include "filterCommon.h"
-#include "geometryHelpers.h"
-
-using std::vector;
-using std::string;
-using std::pair;
-using std::make_pair;
-using std::map;
-
-
-//!Possible primitive types for composition profiles
-enum
-{
-	PRIMITIVE_CYLINDER_AXIAL,
-	PRIMITIVE_CYLINDER_RADIAL,
-	PRIMITIVE_SPHERE,
-	PRIMITIVE_END, //Not actually a primitive, just end of enum
-};
-
-
-//!Error codes
-enum
-{
-	ERR_NUMBINS=1,
-	ERR_MEMALLOC,
-	ERR_ABORT,
-	ERR_COMP_ENUM_END
-};
-
-const char *PRIMITIVE_NAME[]={
-	NTRANS("Cylinder (axial)"),
-	NTRANS("Cylinder (radial)"),
-	NTRANS("Sphere")
-};
-
-const float DEFAULT_RADIUS = 10.0f;
-
-const unsigned int MINEVENTS_DEFAULT =10;
-
-
-CompositionProfileFilter::CompositionProfileFilter() : primitiveType(PRIMITIVE_CYLINDER_AXIAL),
-	showPrimitive(true), lockAxisMag(false),normalise(true), fixedBins(0),
-	nBins(1000), binWidth(0.5f), minEvents(MINEVENTS_DEFAULT), rgba(0,0,1), plotStyle(0)
-{
-	COMPILE_ASSERT(THREEDEP_ARRAYSIZE(PRIMITIVE_NAME) == PRIMITIVE_END);
-	
-	errMode.mode=PLOT_ERROR_NONE;
-	errMode.movingAverageNum=4;
-	
-	vectorParams.push_back(Point3D(0.0,0.0,0.0));
-	vectorParams.push_back(Point3D(0,20.0,0.0));
-	scalarParams.push_back(DEFAULT_RADIUS);
-
-	haveRangeParent=false;
-}
-
-//Puts an ion in its appropriate range position, given ionID mapping,
-//range data (if any), mass to charge and the output table
-void CompositionProfileFilter::binIon(unsigned int targetBin, const RangeStreamData* rng, 
-	const map<unsigned int,unsigned int> &ionIDMapping,
-	vector<vector<size_t> > &frequencyTable, float massToCharge) 
-{
-	//if we have no range data, then simply increment its position in a 1D table
-	//which will later be used as "count" data (like some kind of density plot)
-	if(!rng)
-	{
-		ASSERT(frequencyTable.size() == 1);
-		//There is a really annoying numerical boundary case
-		//that makes the target bin equate to the table size. 
-		//disallow this.
-		if(targetBin < frequencyTable[0].size())
-		{
-			vector<size_t>::iterator it;
-			it=frequencyTable[0].begin()+targetBin;
-			#pragma omp critical
-			(*it)++;
-		}
-		return;
-	}
-
-
-	//We have range data, we need to use it to classify the ion and then increment
-	//the appropriate position in the table
-	unsigned int rangeID = rng->rangeFile->getRangeID(massToCharge);
-
-	if(rangeID != (unsigned int)(-1) && rng->enabledRanges[rangeID])
-	{
-		unsigned int ionID=rng->rangeFile->getIonID(rangeID); 
-		unsigned int pos;
-		pos = ionIDMapping.find(ionID)->second;
-		vector<size_t>::iterator it;
-		it=frequencyTable[pos].begin()+targetBin;
-		#pragma omp critical
-		(*it)++;
-	}
-}
-
-
-Filter *CompositionProfileFilter::cloneUncached() const
-{
-	CompositionProfileFilter *p = new CompositionProfileFilter();
-
-	p->primitiveType=primitiveType;
-	p->showPrimitive=showPrimitive;
-	p->vectorParams.resize(vectorParams.size());
-	p->scalarParams.resize(scalarParams.size());
-
-	std::copy(vectorParams.begin(),vectorParams.end(),p->vectorParams.begin());
-	std::copy(scalarParams.begin(),scalarParams.end(),p->scalarParams.begin());
-
-	p->normalise=normalise;	
-	p->fixedBins=fixedBins;
-	p->lockAxisMag=lockAxisMag;
-	
-	p->rgba=rgba;
-	p->binWidth=binWidth;
-	p->nBins = nBins;
-	p->plotStyle=plotStyle;
-	p->errMode=errMode;
-	//We are copying whether to cache or not,
-	//not the cache itself
-	p->cache=cache;
-	p->cacheOK=false;
-	p->userString=userString;
-	return p;
-}
-
-void CompositionProfileFilter::initFilter(const std::vector<const FilterStreamData *> &dataIn,
-				std::vector<const FilterStreamData *> &dataOut)
-{
-	//Check for range file parent
-	for(unsigned int ui=0;ui<dataIn.size();ui++)
-	{
-		if(dataIn[ui]->getStreamType() == STREAM_TYPE_RANGE)
-		{
-			haveRangeParent=true;
-			return;
-		}
-	}
-	haveRangeParent=false;
-}
-
-unsigned int CompositionProfileFilter::refresh(const std::vector<const FilterStreamData *> &dataIn,
-			std::vector<const FilterStreamData *> &getOut, ProgressData &progress) 
-{
-	//Clear selection devices
-	// FIXME: Leaking drawables.
-	clearDevices();
-	
-	if(showPrimitive)
-	{
-		//TODO: This is a near-copy of ionClip.cpp - refactor
-		//construct a new primitive, do not cache
-		DrawStreamData *drawData=new DrawStreamData;
-		drawData->parent=this;
-		switch(primitiveType)
-		{
-			case PRIMITIVE_CYLINDER_AXIAL:
-			case PRIMITIVE_CYLINDER_RADIAL:
-			{
-				//Origin + normal
-				ASSERT(vectorParams.size() == 2);
-				//Add drawable components
-				DrawCylinder *dC = new DrawCylinder;
-				dC->setOrigin(vectorParams[0]);
-				dC->setRadius(scalarParams[0]);
-				dC->setColour(0.5,0.5,0.5,0.3);
-				dC->setSlices(40);
-				dC->setLength(sqrtf(vectorParams[1].sqrMag())*2.0f);
-				dC->setDirection(vectorParams[1]);
-				dC->wantsLight=true;
-				drawData->drawables.push_back(dC);
-				
-					
-				//Set up selection "device" for user interaction
-				//====
-				//The object is selectable
-				dC->canSelect=true;
-				//Start and end radii must be the same (not a
-				//tapered cylinder)
-				dC->lockRadii();
-
-				SelectionDevice *s = new SelectionDevice(this);
-				SelectionBinding b;
-				//Bind the drawable object to the properties we wish
-				//to be able to modify
-
-				//Bind left + command button to move
-				b.setBinding(SELECT_BUTTON_LEFT,FLAG_CMD,DRAW_CYLINDER_BIND_ORIGIN,
-					BINDING_CYLINDER_ORIGIN,dC->getOrigin(),dC);	
-				b.setInteractionMode(BIND_MODE_POINT3D_TRANSLATE);
-				s->addBinding(b);
-
-				//Bind left + shift to change orientation
-				b.setBinding(SELECT_BUTTON_LEFT,FLAG_SHIFT,DRAW_CYLINDER_BIND_DIRECTION,
-					BINDING_CYLINDER_DIRECTION,dC->getDirection(),dC);	
-				if(lockAxisMag)
-					b.setInteractionMode(BIND_MODE_POINT3D_ROTATE_LOCK);
-				else
-					b.setInteractionMode(BIND_MODE_POINT3D_ROTATE);
-				s->addBinding(b);
-
-				//Bind right button to changing position 
-				b.setBinding(SELECT_BUTTON_RIGHT,0,DRAW_CYLINDER_BIND_ORIGIN,
-					BINDING_CYLINDER_ORIGIN,dC->getOrigin(),dC);	
-				b.setInteractionMode(BIND_MODE_POINT3D_TRANSLATE);
-				s->addBinding(b);
-					
-				//Bind middle button to changing orientation
-				b.setBinding(SELECT_BUTTON_MIDDLE,0,DRAW_CYLINDER_BIND_DIRECTION,
-					BINDING_CYLINDER_DIRECTION,dC->getDirection(),dC);	
-				if(lockAxisMag)
-					b.setInteractionMode(BIND_MODE_POINT3D_ROTATE_LOCK);
-				else
-					b.setInteractionMode(BIND_MODE_POINT3D_ROTATE);
-				s->addBinding(b);
-					
-				//Bind left button to changing radius
-				b.setBinding(SELECT_BUTTON_LEFT,0,DRAW_CYLINDER_BIND_RADIUS,
-					BINDING_CYLINDER_RADIUS,dC->getRadius(),dC);
-				b.setInteractionMode(BIND_MODE_FLOAT_TRANSLATE);
-				b.setFloatLimits(0,std::numeric_limits<float>::max());
-				s->addBinding(b); 
-				
-				devices.push_back(s);
-				//=====
-				
-				break;
-			}
-			case PRIMITIVE_SPHERE:
-			{
-				//Add drawable components
-				DrawSphere *dS = new DrawSphere;
-				dS->setOrigin(vectorParams[0]);
-				dS->setRadius(scalarParams[0]);
-				//FIXME: Alpha blending is all screwed up. May require more
-				//advanced drawing in scene. (front-back drawing).
-				//I have set alpha=1 for now.
-				dS->setColour(0.5,0.5,0.5,1.0);
-				dS->setLatSegments(40);
-				dS->setLongSegments(40);
-				dS->wantsLight=true;
-				drawData->drawables.push_back(dS);
-
-				//Set up selection "device" for user interaction
-				//Note the order of s->addBinding is critical,
-				//as bindings are selected by first match.
-				//====
-				//The object is selectable
-				dS->canSelect=true;
-
-				SelectionDevice *s = new SelectionDevice(this);
-				SelectionBinding b[3];
-
-				//Apple doesn't have right click, so we need
-				//to hook up an additional system for them.
-				//Don't use ifdefs, as this would be useful for
-				//normal laptops and the like.
-				b[0].setBinding(SELECT_BUTTON_LEFT,FLAG_CMD,DRAW_SPHERE_BIND_ORIGIN,
-							BINDING_SPHERE_ORIGIN,dS->getOrigin(),dS);
-				b[0].setInteractionMode(BIND_MODE_POINT3D_TRANSLATE);
-				s->addBinding(b[0]);
-
-				//Bind the drawable object to the properties we wish
-				//to be able to modify
-				b[1].setBinding(SELECT_BUTTON_LEFT,0,DRAW_SPHERE_BIND_RADIUS,
-					BINDING_SPHERE_RADIUS,dS->getRadius(),dS);
-				b[1].setInteractionMode(BIND_MODE_FLOAT_TRANSLATE);
-				b[1].setFloatLimits(0,std::numeric_limits<float>::max());
-				s->addBinding(b[1]);
-
-				b[2].setBinding(SELECT_BUTTON_RIGHT,0,DRAW_SPHERE_BIND_ORIGIN,
-					BINDING_SPHERE_ORIGIN,dS->getOrigin(),dS);	
-				b[2].setInteractionMode(BIND_MODE_POINT3D_TRANSLATE);
-				s->addBinding(b[2]);
-					
-				devices.push_back(s);
-				//=====
-				break;
-			}
-			default:
-				ASSERT(false);
-		}
-		drawData->cached=0;	
-		getOut.push_back(drawData);
-	}
-
-
-	//Propagate all the incoming data (excluding ions)
-	propagateStreams(dataIn,getOut,STREAM_TYPE_IONS,true);
-	
-	//use the cached copy of the data if we have it.
-	if(cacheOK)
-	{
-		//propagate our cached plot data.
-		propagateCache(getOut);
-
-		ASSERT(filterOutputs.back()->getStreamType() == STREAM_TYPE_PLOT);
-
-		progress.filterProgress=100;
-		return 0;
-	}
-			
-
-	//Ion Frequencies (composition specific if rangefile present)
-	vector<vector<size_t> > ionFrequencies;
-	
-	RangeStreamData *rngData=0;
-	for(unsigned int ui=0;ui<dataIn.size() ;ui++)
-	{
-		if(dataIn[ui]->getStreamType() == STREAM_TYPE_RANGE)
-		{
-			rngData =((RangeStreamData *)dataIn[ui]);
-			break;
-		}
-	}
-
-	unsigned int numBins, errCode;
-	{
-	float length;
-	errCode=getBinData(numBins,length);
-
-	if(!numBins)
-		return 0;
-	}
-
-	if(errCode)
-		return errCode;
-
-	//Indirection vector to convert ionFrequencies position to ionID mapping.
-	//Should only be used in conjunction with rngData == true
-	std::map<unsigned int,unsigned int> ionIDMapping,inverseIDMapping;
-	//Allocate space for the frequency table
-	if(rngData)
-	{
-		ASSERT(rngData->rangeFile);
-		unsigned int enabledCount=0;
-		for(unsigned int ui=0;ui<rngData->rangeFile->getNumIons();ui++)
-		{
-			//TODO: Might be nice to detect if an ions ranges
-			//are all, disabled then if they are, enter this "if"
-			//anyway
-			if(rngData->enabledIons[ui])
-			{
-				//Keep the forwards mapping for binning
-				ionIDMapping.insert(make_pair(ui,enabledCount));
-				//Keep the inverse mapping for labelling
-				inverseIDMapping.insert(make_pair(enabledCount,ui));
-				enabledCount++;
-			}
-
-		
-
-		}
-
-		//Nothing to do.
-		if(!enabledCount)
-			return 0;
-
-		try
-		{
-			ionFrequencies.resize(enabledCount);
-			//Allocate and Initialise all elements to zero
-			#pragma omp parallel for
-			for(unsigned int ui=0;ui<ionFrequencies.size(); ui++)
-				ionFrequencies[ui].resize(numBins,0);
-		}
-		catch(std::bad_alloc)
-		{
-			return ERR_MEMALLOC;
-		}
-
-	}
-	else
-	{
-		try
-		{
-			ionFrequencies.resize(1);
-			ionFrequencies[0].resize(numBins,0);
-		}
-		catch(std::bad_alloc)
-		{
-			return ERR_MEMALLOC;
-		}
-	}
-
-
-	size_t n=0;
-	size_t totalSize=numElements(dataIn);
-
-	map<size_t,size_t> primitiveMap;
-	primitiveMap[PRIMITIVE_CYLINDER_AXIAL] = CROP_CYLINDER_INSIDE_AXIAL;
-	primitiveMap[PRIMITIVE_CYLINDER_RADIAL] = CROP_CYLINDER_INSIDE_RADIAL;
-	primitiveMap[PRIMITIVE_SPHERE] = CROP_SPHERE_INSIDE;
-
-	CropHelper dataMapping(totalSize,primitiveMap[primitiveType], 
-					vectorParams,scalarParams  );
-	dataMapping.setMapMaxima(numBins);
-
-	unsigned int curProg=NUM_CALLBACK;
-	for(unsigned int ui=0;ui<dataIn.size() ;ui++)
-	{
-		//Loop through each element data set
-		switch(dataIn[ui]->getStreamType())
-		{
-			case STREAM_TYPE_IONS:
-			{
-				const IonStreamData *dIon = (const IonStreamData*)dataIn[ui];
-#ifdef _OPENMP
-				bool spin=false;
-#endif
-				//Process ion streams
-			
-				size_t nIons=dIon->data.size();	
-				#pragma omp parallel for
-				for(size_t uj=0;uj<nIons;uj++)
-				{
-#ifdef _OPENMP
-					//if parallelised, abort computaiton
-					if(spin) continue;
-#endif
-					unsigned int targetBin;
-					targetBin=dataMapping.mapIon1D(dIon->data[uj]);
-
-					//Keep ion if inside cylinder 
-					if(targetBin!=(unsigned int)-1)
-					{
-						//Push data into the correct bin.
-						// based upon eg ranging information and target 1D bin
-						binIon(targetBin,rngData,ionIDMapping,ionFrequencies,
-								dIon->data[uj].getMassToCharge());
-					}
-
-#ifdef _OPENMP
-					if(omp_get_thread_num() == 0)	
-					{
-#endif
-					//update progress every CALLBACK ions
-					if(!curProg--)
-					{
-						n+=NUM_CALLBACK;
-						progress.filterProgress= (unsigned int)((float)(n)/((float)totalSize)*100.0f);
-						curProg=NUM_CALLBACK;
-						if(*Filter::wantAbort)
-						{
-							#ifdef _OPENMP
-								spin=true;
-							#else
-							return ERR_ABORT;
-							#endif 
-						}
-					}
-#ifdef _OPENMP
-					}
-#endif
-				}
-
-#ifdef _OPENMP
-				if(spin)
-					return ERR_ABORT;
-#endif
-					
-				break;
-			}
-			default:
-				//Do not propagate other types.
-				break;
-		}
-				
-	}
-
-#ifdef DEBUG
-	ASSERT(ionFrequencies.size());
-	//Ion frequencies must be of equal length
-	for(unsigned int ui=1;ui<ionFrequencies.size();ui++)
-	{
-		ASSERT(ionFrequencies[ui].size() == ionFrequencies[0].size());
-	}
-#endif
-	
-
-	vector<float> normalisationFactor;
-	vector<unsigned int> normalisationCount;
-	normalisationFactor.resize(ionFrequencies[0].size());
-	normalisationCount.resize(ionFrequencies[0].size());
-	bool needNormalise=false;
-
-	//Perform the appropriate normalisation
-	if(!rngData && normalise)
-	{
-		// For density plots, normalise by
-		//  the volume of the primitive's shell
-		switch(primitiveType)
-		{
-			case PRIMITIVE_CYLINDER_AXIAL:
-			case PRIMITIVE_CYLINDER_RADIAL:
-			{
-
-				float dx;
-				if(fixedBins)
-					dx=(sqrtf(vectorParams[1].sqrMag())/(float)numBins);
-
-				else
-					dx=binWidth;
-				needNormalise=true;
-				float nFact;
-				//Normalise by cylinder slice volume, pi*r^2*h.
-				// This is the same in both radial and axial mode as the radial slices are equi-volume, 
-				// same as axial mode
-				nFact=1.0/(M_PI*scalarParams[0]*scalarParams[0]*dx);
-				for(unsigned int uj=0;uj<normalisationFactor.size(); uj++)
-					normalisationFactor[uj] = nFact;
-				break;
-			}
-			case PRIMITIVE_SPHERE:
-			{
-				float dx;
-				if(fixedBins)
-					dx=(scalarParams[0]/(float)numBins);
-
-				else
-					dx=binWidth;
-				for(unsigned int uj=0;uj<normalisationFactor.size(); uj++)
-				{
-					//Normalise by sphere shell volume, 
-					// 4/3 *PI*dx^3*((n+1)^3-n^3)
-					//  note -> (n+1)^3 -n^3  = (3*n^2) + (3*n) + 1
-					normalisationFactor[uj] = 1.0/(4.0/3.0*M_PI*
-						dx*(3.0*((float)uj*(float)uj + uj) + 1.0));
-				}
-				break;
-			}
-			default:
-				ASSERT(false);
-		}
-	}
-	else if(normalise && rngData) //compute normalisation values, if we are in composition mode
-	{
-		// the loops' nesting is reversed as we need to sum over distinct plots
-		//Density profiles (non-ranged plots) have a fixed normalisation factor
-		needNormalise=true;
-
-		for(unsigned int uj=0;uj<ionFrequencies[0].size(); uj++)
-		{
-			float sum;
-			sum=0;
-			//Loop across each bin type, summing result
-			for(unsigned int uk=0;uk<ionFrequencies.size();uk++)
-				sum +=(float)ionFrequencies[uk][uj];
-			normalisationCount[uj]=sum;
-
-	
-			//Compute the normalisation factor
-			if(sum)
-				normalisationFactor[uj]=1.0/sum;
-			else
-				normalisationFactor[uj] = 0;
-		}
-
-	}
-
-	
-	//Create the plots
-	PlotStreamData *plotData[ionFrequencies.size()];
-	for(unsigned int ui=0;ui<ionFrequencies.size();ui++)
-	{
-		plotData[ui] = new PlotStreamData;
-
-		plotData[ui]->index=ui;
-		plotData[ui]->parent=this;
-		plotData[ui]->xLabel= TRANS("Distance");
-		plotData[ui]->errDat=errMode;
-		if(normalise)
-		{
-			//If we have composition, normalise against 
-			//sum composition = 1 otherwise use volume of bin
-			//as normalisation factor
-			if(rngData)
-				plotData[ui]->yLabel= TRANS("Fraction");
-			else
-				plotData[ui]->yLabel= TRANS("Density (\\frac{\\#}{len^3})");
-		}
-		else
-			plotData[ui]->yLabel= TRANS("Count");
-
-		//Give the plot a title like TRANS("Myplot:Mg" (if have range) or "MyPlot") (no range)
-		if(rngData)
-		{
-			unsigned int thisIonID;
-			thisIonID = inverseIDMapping.find(ui)->second;
-			plotData[ui]->dataLabel = getUserString() + string(":") 
-					+ rngData->rangeFile->getName(thisIonID);
-
-		
-			//Set the plot colour to the ion colour	
-			RGBf col;
-			col=rngData->rangeFile->getColour(thisIonID);
-
-			plotData[ui]->r =col.red;
-			plotData[ui]->g =col.green;
-			plotData[ui]->b =col.blue;
-
-		}
-		else
-		{
-			//If it only has one component, then 
-			//it's not really a composition profile is it?
-			plotData[ui]->dataLabel= TRANS("Freq. Profile");
-			plotData[ui]->r = rgba.r();
-			plotData[ui]->g = rgba.g();
-			plotData[ui]->b = rgba.b();
-			plotData[ui]->a = rgba.a();
-		}
-
-		plotData[ui]->xyData.reserve(ionFrequencies[ui].size());
-	
-
-		//Go through each bin, then perform the appropriate normalisation
-		for(unsigned int uj=0;uj<ionFrequencies[ui].size(); uj++)
-		{
-			float xPos;
-			xPos = getBinPosition(uj);
-
-			if(ionFrequencies[ui][uj] < minEvents)
-				continue;
-
-			//Recompute normalisation value for this bin, if needed
-			if(needNormalise)
-			{
-				float normFactor=normalisationFactor[uj];
-
-				//keep the data if we are not using minimum threshold for normalisation, or we met the 
-				// threhsold
-				plotData[ui]->xyData.push_back(
-					std::make_pair(xPos,
-					normFactor*(float)ionFrequencies[ui][uj]));
-			}
-			else
-			{	
-				plotData[ui]->xyData.push_back(
-					std::make_pair(xPos,ionFrequencies[ui][uj]) );
-			}
-		}
-
-
-
-
-		plotData[ui]->plotStyle = plotStyle;
-		plotData[ui]->plotMode=PLOT_MODE_1D;
-
-		//If we ended up with any data, display it
-		// otherwise, trash the plot info
-		if(plotData[ui]->xyData.size())
-		{
-			cacheAsNeeded(plotData[ui]);
-			getOut.push_back(plotData[ui]);
-		}
-		else
-		{
-			consoleOutput.push_back(TRANS("No data remained in profile - cannot display result"));
-			delete plotData[ui];
-		}
-	}
-
-	return 0;
-}
-
-std::string  CompositionProfileFilter::getSpecificErrString(unsigned int code) const
-{
-	const char *errCodes[] =   { "",
-		"Too many bins in comp. profile.",
-		"Not enough memory for comp. profile.",
-		"Aborted composition prof." }; 
-
-	COMPILE_ASSERT(THREEDEP_ARRAYSIZE(errCodes) == ERR_COMP_ENUM_END);
-	ASSERT(code < ERR_COMP_ENUM_END);
-
-	return errCodes[code];
-}
-
-bool CompositionProfileFilter::setProperty( unsigned int key, 
-					const std::string &value, bool &needUpdate) 
-{
-
-			
-	switch(key)
-	{
-		case COMPOSITION_KEY_BINWIDTH:
-		{
-			float newBinWidth;
-			if(stream_cast(newBinWidth,value))
-				return false;
-
-			if(newBinWidth < sqrtf(std::numeric_limits<float>::epsilon()))
-				return false;
-
-			binWidth=newBinWidth;
-			clearCache();
-			needUpdate=true;
-			break;
-		}
-		case COMPOSITION_KEY_FIXEDBINS:
-		{
-			if(!applyPropertyNow(fixedBins,value,needUpdate))
-				return false;
-			break;	
-		}
-		case COMPOSITION_KEY_NORMAL:
-		{
-			Point3D newPt;
-			if(!newPt.parse(value))
-				return false;
-
-			if(primitiveType == PRIMITIVE_CYLINDER_AXIAL)
-			{
-				if(lockAxisMag && 
-					newPt.sqrMag() > sqrtf(std::numeric_limits<float>::epsilon()))
-				{
-					newPt.normalise();
-					newPt*=sqrtf(vectorParams[1].sqrMag());
-				}
-			}
-			if(newPt.sqrMag() < sqrtf(std::numeric_limits<float>::epsilon()))
-				return false;
-
-			if(!(vectorParams[1] == newPt ))
-			{
-				vectorParams[1] = newPt;
-				needUpdate=true;
-				clearCache();
-			}
-			return true;
-		}
-		case COMPOSITION_KEY_MINEVENTS:
-		{
-			if(!applyPropertyNow(minEvents,value,needUpdate))
-				return false;
-			break;	
-		}
-		case COMPOSITION_KEY_NUMBINS:
-		{
-			unsigned int newNumBins;
-			if(stream_cast(newNumBins,value))
-				return false;
-
-			//zero bins disallowed
-			if(!newNumBins)
-				return false;
-
-			nBins=newNumBins;
-
-			clearCache();
-			needUpdate=true;
-			break;
-		}
-		case COMPOSITION_KEY_ORIGIN:
-		{
-			if(!applyPropertyNow(vectorParams[0],value,needUpdate))
-				return false;
-			return true;
-		}
-		case COMPOSITION_KEY_PRIMITIVETYPE:
-		{
-			unsigned int newPrimitive;
-			newPrimitive=getPrimitiveId(value);
-			if(newPrimitive >= PRIMITIVE_END)
-				return false;
-
-			//set the new primitive type
-			primitiveType=newPrimitive;
-
-			//set up the values for the new primitive type,
-			// preserving data where possible
-			switch(primitiveType)
-			{
-				case PRIMITIVE_CYLINDER_AXIAL:
-				case PRIMITIVE_CYLINDER_RADIAL:
-				{
-					if(vectorParams.size() != 2)
-					{
-						if(vectorParams.size() <2 )
-						{
-							vectorParams.clear();
-							vectorParams.push_back(Point3D(0,0,0));
-							vectorParams.push_back(Point3D(0,20,0));
-						}
-						else
-							vectorParams.resize(2);
-					}
-
-					if(scalarParams.size() != 1)
-					{
-						if (scalarParams.size() > 1)
-						{
-							scalarParams.clear();
-							scalarParams.push_back(DEFAULT_RADIUS);
-						}
-						else
-							scalarParams.resize(1);
-					}
-
-					if(primitiveType == PRIMITIVE_CYLINDER_RADIAL)
-						fixedBins=true;
-
-					break;
-				}
-				case PRIMITIVE_SPHERE:
-				{
-					if(vectorParams.size() !=1)
-					{
-						if(vectorParams.size() >1)
-							vectorParams.resize(1);
-						else
-							vectorParams.push_back(Point3D(0,0,0));
-					}
-
-					if(scalarParams.size() !=1)
-					{
-						if(scalarParams.size() > 1)
-							scalarParams.resize(1);
-						else
-							scalarParams.push_back(DEFAULT_RADIUS);
-					}
-					break;
-				}
-
-				default:
-					ASSERT(false);
-			}
-	
-			clearCache();	
-			needUpdate=true;	
-			return true;	
-		}
-		case COMPOSITION_KEY_RADIUS:
-		{
-			float newRad;
-			if(stream_cast(newRad,value))
-				return false;
-
-			if(newRad < sqrtf(std::numeric_limits<float>::epsilon()))
-				return false;
-
-			if(scalarParams[0] != newRad )
-			{
-				scalarParams[0] = newRad;
-				needUpdate=true;
-				clearCache();
-			}
-			return true;
-		}
-		case COMPOSITION_KEY_SHOWPRIMITIVE:
-		{
-			if(!applyPropertyNow(showPrimitive,value,needUpdate))
-				return false;
-			break;	
-		}
-		case COMPOSITION_KEY_NORMALISE:
-		{
-			if(!applyPropertyNow(normalise,value,needUpdate))
-				return false;
-			break;	
-		}
-		case COMPOSITION_KEY_LOCKAXISMAG:
-		{
-			if(!applyPropertyNow(lockAxisMag,value,needUpdate))
-				return false;
-			break;
-		}
-		case COMPOSITION_KEY_PLOTTYPE:
-		{
-			unsigned int tmpPlotType;
-
-			tmpPlotType=plotID(value);
-
-			if(tmpPlotType >= PLOT_LINE_NONE)
-				return false;
-
-			plotStyle = tmpPlotType;
-			needUpdate=true;	
-			break;
-		}
-		case COMPOSITION_KEY_COLOUR:
-		{
-			ColourRGBA tmpRgba;
-			if(!tmpRgba.parse(value))
-				return false;
-			
-			rgba=tmpRgba.toRGBAf();
-			needUpdate=true;
-			break;	
-		}
-		case COMPOSITION_KEY_ERRMODE:
-		{
-			unsigned int tmpMode;
-			tmpMode=plotErrmodeID(value);
-
-			if(tmpMode >= PLOT_ERROR_ENDOFENUM)
-				return false;
-
-			errMode.mode= tmpMode;
-			needUpdate=true;
-
-			break;
-		}
-		case COMPOSITION_KEY_AVGWINSIZE:
-		{
-			unsigned int tmpNum;
-			if(stream_cast(tmpNum,value))
-				return false;
-
-			if(tmpNum<=1)
-				return false;
-
-			errMode.movingAverageNum=tmpNum;
-			needUpdate=true;
-			break;
-		}
-		default:
-			ASSERT(false);	
-	}
-
-	if(needUpdate)
-		clearCache();
-
-	return true;
-}
-
-void CompositionProfileFilter::getProperties(FilterPropGroup &propertyList) const
-{
-	string str,tmpStr;
-	FilterProperty p;
-	size_t curGroup=0;
-
-	//Allow primitive selection if we have more than one primitive
-	if(PRIMITIVE_END > 1)
-	{
-		//Choices for primitive type
-		vector<pair<unsigned int,string> > choices;
-		for(unsigned int ui=0;ui<PRIMITIVE_END;ui++)
-		{
-			str =TRANS(PRIMITIVE_NAME[ui]);
-			choices.push_back(make_pair(ui,str));
-		}
-		p.name=TRANS("Primitive type");
-		p.data=choiceString(choices,primitiveType);
-		p.key=COMPOSITION_KEY_PRIMITIVETYPE;
-		p.type=PROPERTY_TYPE_CHOICE;
-		p.helpText=TRANS("Basic shape to use for profile");
-		propertyList.addProperty(p,curGroup);
-		propertyList.setGroupTitle(curGroup,TRANS("Primitive"));	
-		curGroup++;
-	}
-
-	
-	stream_cast(tmpStr,showPrimitive);
-	p.name=TRANS("Show Primitive");	
-	p.data=tmpStr;
-	p.key=COMPOSITION_KEY_SHOWPRIMITIVE;
-	p.type=PROPERTY_TYPE_BOOL;
-	p.helpText=TRANS("Display the 3D composition profile interaction object");
-	propertyList.addProperty(p,curGroup);
-
-	switch(primitiveType)
-	{
-		case PRIMITIVE_CYLINDER_AXIAL:
-		case PRIMITIVE_CYLINDER_RADIAL:
-		{
-			ASSERT(vectorParams.size() == 2);
-			ASSERT(scalarParams.size() == 1);
-			stream_cast(str,vectorParams[0]);
-			p.key=COMPOSITION_KEY_ORIGIN;
-			p.name=TRANS("Origin");
-			p.data=str;
-			p.type=PROPERTY_TYPE_POINT3D;
-			p.helpText=TRANS("Position for centre of cylinder");
-			propertyList.addProperty(p,curGroup);
-			
-			stream_cast(str,vectorParams[1]);
-			p.key=COMPOSITION_KEY_NORMAL;
-			p.name=TRANS("Axis");
-			p.data=str;
-			p.type=PROPERTY_TYPE_POINT3D;
-			p.helpText=TRANS("Vector between ends of cylinder");
-			propertyList.addProperty(p,curGroup);
-
-			str=boolStrEnc(lockAxisMag);
-			p.key=COMPOSITION_KEY_LOCKAXISMAG;
-			p.name=TRANS("Lock Axis Mag.");
-			p.data= str;
-			p.type=PROPERTY_TYPE_BOOL;
-			p.helpText=TRANS("Prevent length of cylinder changing during interaction");
-			propertyList.addProperty(p,curGroup);
-			
-			stream_cast(str,scalarParams[0]);
-			p.key=COMPOSITION_KEY_RADIUS;
-			p.name=TRANS("Radius");
-			p.data= str;
-			p.type=PROPERTY_TYPE_POINT3D;
-			p.helpText=TRANS("Radius of cylinder");
-			propertyList.addProperty(p,curGroup);
-			break;
-		}
-		case PRIMITIVE_SPHERE:
-		{
-			
-			ASSERT(vectorParams.size() == 1);
-			ASSERT(scalarParams.size() == 1);
-			stream_cast(str,vectorParams[0]);
-			p.key=COMPOSITION_KEY_ORIGIN;
-			p.name=TRANS("Origin");
-			p.data=str;
-			p.type=PROPERTY_TYPE_POINT3D;
-			p.helpText=TRANS("Position for centre of sphere");
-			propertyList.addProperty(p,curGroup);
-			
-			stream_cast(str,scalarParams[0]);
-			p.key=COMPOSITION_KEY_RADIUS;
-			p.name=TRANS("Radius");
-			p.data= str;
-			p.type=PROPERTY_TYPE_POINT3D;
-			p.helpText=TRANS("Radius of sphere");
-			propertyList.addProperty(p,curGroup);
-			break;
-		}
-		default:
-			ASSERT(false);
-	}
-
-	//Must be fixed bin num in radial mode. Disallow turning this off
-	if(primitiveType!= PRIMITIVE_CYLINDER_RADIAL)
-	{
-		p.key=COMPOSITION_KEY_FIXEDBINS;
-		stream_cast(str,fixedBins);
-		p.name=TRANS("Fixed Bin Num");
-		p.data=str;
-		p.type=PROPERTY_TYPE_BOOL;
-		p.helpText=TRANS("If true, use a fixed number of bins for profile, otherwise use fixed step size");
-		propertyList.addProperty(p,curGroup);
-	}
-
-	if(fixedBins)
-	{
-		stream_cast(tmpStr,nBins);
-		str = TRANS("Num Bins");
-		p.name=str;
-		p.data=tmpStr;
-		p.key=COMPOSITION_KEY_NUMBINS;
-		p.type=PROPERTY_TYPE_INTEGER;
-		p.helpText=TRANS("Number of bins to use for profile");
-		propertyList.addProperty(p,curGroup);
-	}
-	else
-	{
-		ASSERT(primitiveType!=PRIMITIVE_CYLINDER_RADIAL);
-		str = TRANS("Bin width");
-		stream_cast(tmpStr,binWidth);
-		p.name=str;
-		p.data=tmpStr;
-		p.key=COMPOSITION_KEY_BINWIDTH;
-		p.type=PROPERTY_TYPE_REAL;
-		p.helpText=TRANS("Size of each bin in profile");
-		propertyList.addProperty(p,curGroup);
-	}
-
-	stream_cast(tmpStr,normalise);
-	p.name= TRANS("Normalise");	
-	p.data=tmpStr;
-	p.key=COMPOSITION_KEY_NORMALISE;
-	p.type=PROPERTY_TYPE_BOOL;
-	p.helpText=TRANS("Convert bin counts into relative frequencies in each bin");
-	propertyList.addProperty(p,curGroup);
-
-	stream_cast(tmpStr,minEvents);
-	p.name= TRANS("Min. events");	
-	p.data=tmpStr;
-	p.key=COMPOSITION_KEY_MINEVENTS;
-	p.type=PROPERTY_TYPE_INTEGER;
-	p.helpText=TRANS("Drop data that does not have this many events");
-	propertyList.addProperty(p,curGroup);
-
-	propertyList.setGroupTitle(curGroup,TRANS("Settings"));	
-
-
-
-	curGroup++;
-	
-	//use set 2 to store the plot properties
-	stream_cast(str,plotStyle);
-	//Let the user know what the valid values for plot type are
-	vector<pair<unsigned int,string> > choices;
-
-
-	tmpStr=plotString(PLOT_LINE_LINES);
-	choices.push_back(make_pair((unsigned int) PLOT_LINE_LINES,tmpStr));
-	tmpStr=plotString(PLOT_LINE_BARS);
-	choices.push_back(make_pair((unsigned int)PLOT_LINE_BARS,tmpStr));
-	tmpStr=plotString(PLOT_LINE_STEPS);
-	choices.push_back(make_pair((unsigned int)PLOT_LINE_STEPS,tmpStr));
-	tmpStr=plotString(PLOT_LINE_STEM);
-	choices.push_back(make_pair((unsigned int)PLOT_LINE_STEM,tmpStr));
-
-	tmpStr= choiceString(choices,plotStyle);
-	p.name=TRANS("Plot Type");
-	p.data=tmpStr;
-	p.type=PROPERTY_TYPE_CHOICE;
-	p.helpText=TRANS("Visual style for plot");
-	p.key=COMPOSITION_KEY_PLOTTYPE;
-	propertyList.addProperty(p,curGroup);
-	//Convert the colour to a hex string
-	if(!haveRangeParent)
-	{
-
-		p.name=TRANS("Colour");
-		p.data=rgba.toColourRGBA().rgbString();
-		p.type=PROPERTY_TYPE_COLOUR;
-		p.helpText=TRANS("Colour of plot");
-		p.key=COMPOSITION_KEY_COLOUR;
-		propertyList.addProperty(p,curGroup);
-	}
-
-
-	propertyList.setGroupTitle(curGroup,TRANS("Appearance"));
-	curGroup++;
-	
-	choices.clear();
-	tmpStr=plotErrmodeString(PLOT_ERROR_NONE);
-	choices.push_back(make_pair((unsigned int) PLOT_ERROR_NONE,tmpStr));
-	tmpStr=plotErrmodeString(PLOT_ERROR_MOVING_AVERAGE);
-	choices.push_back(make_pair((unsigned int) PLOT_ERROR_MOVING_AVERAGE,tmpStr));
-
-	tmpStr= choiceString(choices,errMode.mode);
-	p.name=TRANS("Err. Estimator");
-	p.data=tmpStr;
-	p.type=PROPERTY_TYPE_CHOICE;
-	p.helpText=TRANS("Method of estimating error associated with each bin");
-	p.key=COMPOSITION_KEY_ERRMODE;
-	propertyList.addProperty(p,curGroup);
-
-	if(errMode.mode == PLOT_ERROR_MOVING_AVERAGE)
-	{
-		stream_cast(tmpStr,errMode.movingAverageNum);
-		p.name=TRANS("Avg. Window");
-		p.data=tmpStr;
-		p.type=PROPERTY_TYPE_INTEGER;
-		p.helpText=TRANS("Number of bins to include in moving average filter");
-		p.key=COMPOSITION_KEY_AVGWINSIZE;
-		propertyList.addProperty(p,curGroup);
-	}	
-	propertyList.setGroupTitle(curGroup,TRANS("Error analysis"));
-}
-
-unsigned int CompositionProfileFilter::getBinData(unsigned int &numBins, float &length) const
-{
-	//Number of bins, having determined if we are using
-	//fixed bin count or not
-	switch(primitiveType)
-	{
-		case PRIMITIVE_SPHERE:
-			//radius of sphere
-			length=scalarParams[0];
-			break;
-		case PRIMITIVE_CYLINDER_AXIAL:
-			//length of cylinder, full axis length
-			length=sqrtf(vectorParams[1].sqrMag());
-			break;
-		case PRIMITIVE_CYLINDER_RADIAL:
-			//radius of cylinder
-			length =scalarParams[0];
-			break;
-		default:
-			ASSERT(false);
-	}
-	
-	if(fixedBins)
-		numBins=nBins;
-	else
-	{
-		switch(primitiveType)
-		{
-			case PRIMITIVE_CYLINDER_AXIAL:
-			case PRIMITIVE_CYLINDER_RADIAL:
-			case PRIMITIVE_SPHERE:
-			{
-
-				ASSERT(binWidth > std::numeric_limits<float>::epsilon());
-
-				//Check for possible overflow
-				if(length/binWidth > (float)std::numeric_limits<unsigned int>::max())
-					return ERR_NUMBINS;
-
-				numBins=(unsigned int)(length/binWidth);
-				break;
-			}
-			default:
-				ASSERT(false);
-		}
-		
-	}
-	
-	return 0;
-}
-
-float CompositionProfileFilter::getBinPosition(unsigned int nBin) const
-{
-	unsigned int nBinsMax; float fullLen, xPos;
-	getBinData(nBinsMax,fullLen);	
-	ASSERT(nBin < nBinsMax)
-	xPos = ((float) nBin + 0.5)/(float)nBinsMax;
-	if( primitiveType == PRIMITIVE_CYLINDER_RADIAL)
-	{
-		float maxPosSqr = fullLen*fullLen;
-		//compute fraction
-		xPos = sqrt ( xPos*maxPosSqr);
-	}
-	else
-	{
-		xPos = xPos*fullLen;
-	}			
-
-	return xPos;
-}
-
-//!Get approx number of bytes for caching output
-size_t CompositionProfileFilter::numBytesForCache(size_t nObjects) const
-{
-	float length;
-	unsigned int errCode, numBins;
-	errCode=getBinData(numBins,length);
-
-	if(errCode)
-		return (unsigned int)-1;
-	
-	return (numBins*2*sizeof(float));
-}
-
-bool CompositionProfileFilter::writeState(std::ostream &f,unsigned int format, unsigned int depth) const
-{
-	using std::endl;
-	switch(format)
-	{
-		case STATE_FORMAT_XML:
-		{	
-			f << tabs(depth) << "<" << trueName() << ">" << endl;
-			f << tabs(depth+1) << "<userstring value=\""<< escapeXML(userString) << "\"/>"  << endl;
-
-			f << tabs(depth+1) << "<primitivetype value=\"" << primitiveType<< "\"/>" << endl;
-			f << tabs(depth+1) << "<showprimitive value=\"" << showPrimitive << "\"/>" << endl;
-			f << tabs(depth+1) << "<lockaxismag value=\"" << lockAxisMag<< "\"/>" << endl;
-			f << tabs(depth+1) << "<vectorparams>" << endl;
-			for(unsigned int ui=0; ui<vectorParams.size(); ui++)
-			{
-				f << tabs(depth+2) << "<point3d x=\"" << vectorParams[ui][0] << 
-					"\" y=\"" << vectorParams[ui][1] << "\" z=\"" << vectorParams[ui][2] << "\"/>" << endl;
-			}
-			f << tabs(depth+1) << "</vectorparams>" << endl;
-
-			f << tabs(depth+1) << "<scalarparams>" << endl;
-			for(unsigned int ui=0; ui<scalarParams.size(); ui++)
-				f << tabs(depth+2) << "<scalar value=\"" << scalarParams[0] << "\"/>" << endl; 
-			
-			f << tabs(depth+1) << "</scalarparams>" << endl;
-			f << tabs(depth+1) << "<normalise value=\"" << normalise << "\" minevents=\"" << minEvents << "\" />" << endl;
-			f << tabs(depth+1) << "<fixedbins value=\"" << (int)fixedBins << "\"/>" << endl;
-			f << tabs(depth+1) << "<nbins value=\"" << nBins << "\"/>" << endl;
-			f << tabs(depth+1) << "<binwidth value=\"" << binWidth << "\"/>" << endl;
-			f << tabs(depth+1) << "<colour r=\"" <<  rgba.r() << "\" g=\"" << rgba.g() << "\" b=\"" << rgba.b()
-				<< "\" a=\"" << rgba.a() << "\"/>" <<endl;
-
-			f << tabs(depth+1) << "<plottype value=\"" << plotStyle << "\"/>" << endl;
-			f << tabs(depth) << "</" << trueName()  << ">" << endl;
-			break;
-		}
-		default:
-			ASSERT(false);
-			return false;
-	}
-
-	return true;
-}
-
-
-void CompositionProfileFilter::setUserString(const std::string &str)
-{
-	if(userString != str)
-	{
-		userString=str;
-		clearCache();
-	}	
-}
-
-bool CompositionProfileFilter::readState(xmlNodePtr &nodePtr, const std::string &stateFileDir)
-{
-	//Retrieve user string
-	//===
-	if(XMLHelpFwdToElem(nodePtr,"userstring"))
-		return false;
-
-	xmlChar *xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	userString=(char *)xmlString;
-	xmlFree(xmlString);
-	//===
-
-	std::string tmpStr;	
-	//Retrieve primitive type 
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"primitivetype"))
-		return false;
-
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-	//convert from string to digit
-	if(stream_cast(primitiveType,tmpStr))
-		return false;
-
-	//FIXME: DEPRECATE 3Depict versions <=0.0.17 had only two primitives,
-	// cylinder and sphere. 
-/*	if(versionCheckGreater(Filter::stateWriterVersion,("0.0.17")))
-	{
-		//remap the primitive type as needed
-		if(primitiveType == PRIMITIVE_CYLINDER_RADIAL)
-			primitiveType=PRIMITIVE_SPHERE;
-
-	}
-*/
-	if(primitiveType >= PRIMITIVE_END)
-	       return false;	
-	xmlFree(xmlString);
-	//====
-	
-	//Retrieve primitive visibility 
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"showprimitive"))
-		return false;
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-	if(!boolStrDec(tmpStr,showPrimitive))
-		return false;
-
-	xmlFree(xmlString);
-	//====
-	
-	//Retrieve axis lock mode 
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"lockaxismag"))
-		return false;
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-	if(!boolStrDec(tmpStr,lockAxisMag))
-		return false;
-
-	xmlFree(xmlString);
-	//====
-	
-	//Retrieve vector parameters
-	//===
-	if(XMLHelpFwdToElem(nodePtr,"vectorparams"))
-		return false;
-	xmlNodePtr tmpNode=nodePtr;
-
-	nodePtr=nodePtr->xmlChildrenNode;
-
-	vectorParams.clear();
-	while(!XMLHelpFwdToElem(nodePtr,"point3d"))
-	{
-		float x,y,z;
-		//--Get X value--
-		xmlString=xmlGetProp(nodePtr,(const xmlChar *)"x");
-		if(!xmlString)
-			return false;
-		tmpStr=(char *)xmlString;
-		xmlFree(xmlString);
-
-		//Check it is streamable
-		if(stream_cast(x,tmpStr))
-			return false;
-
-		//--Get Z value--
-		xmlString=xmlGetProp(nodePtr,(const xmlChar *)"y");
-		if(!xmlString)
-			return false;
-		tmpStr=(char *)xmlString;
-		xmlFree(xmlString);
-
-		//Check it is streamable
-		if(stream_cast(y,tmpStr))
-			return false;
-
-		//--Get Y value--
-		xmlString=xmlGetProp(nodePtr,(const xmlChar *)"z");
-		if(!xmlString)
-			return false;
-		tmpStr=(char *)xmlString;
-		xmlFree(xmlString);
-
-		//Check it is streamable
-		if(stream_cast(z,tmpStr))
-			return false;
-
-		vectorParams.push_back(Point3D(x,y,z));
-	}
-	//===	
-
-	nodePtr=tmpNode;
-	//Retrieve scalar parameters
-	//===
-	if(XMLHelpFwdToElem(nodePtr,"scalarparams"))
-		return false;
-	
-	tmpNode=nodePtr;
-	nodePtr=nodePtr->xmlChildrenNode;
-
-	scalarParams.clear();
-	while(!XMLHelpFwdToElem(nodePtr,"scalar"))
-	{
-		float v;
-		//Get value
-		xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-		if(!xmlString)
-			return false;
-		tmpStr=(char *)xmlString;
-		xmlFree(xmlString);
-
-		//Check it is streamable
-		if(stream_cast(v,tmpStr))
-			return false;
-		scalarParams.push_back(v);
-	}
-	//===	
-
-	//Check the scalar params match the selected primitive	
-	switch(primitiveType)
-	{
-		case PRIMITIVE_CYLINDER_AXIAL:
-		case PRIMITIVE_CYLINDER_RADIAL:
-			if(vectorParams.size() != 2 || scalarParams.size() !=1)
-				return false;
-			break;
-		case PRIMITIVE_SPHERE:
-			if(vectorParams.size() != 1 || scalarParams.size() !=1)
-				return false;
-			break;
-
-		default:
-			ASSERT(false);
-			return false;
-	}
-
-	nodePtr=tmpNode;
-
-	//Retrieve normalisation on/off 
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"normalise"))
-		return false;
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-
-	if(!boolStrDec(tmpStr,normalise))
-		return false;
-
-	xmlFree(xmlString);
-	//====
-
-	//Retrieve fixed bins on/off 
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"fixedbins"))
-		return false;
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-	if(!boolStrDec(tmpStr,fixedBins))
-		return false;
-
-
-	xmlFree(xmlString);
-	//====
-
-	//Retrieve num bins
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"nbins"))
-		return false;
-
-	
-	if(XMLHelpGetProp(nBins,nodePtr,"value"))
-		return false;
-
-
-	if(XMLHelpGetProp(minEvents,nodePtr,"minevents"))
-	{
-		//FIXME: Deprecate me.
-		minEvents=MINEVENTS_DEFAULT;
-	}
-	//====
-
-	//Retrieve bin width
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"binwidth"))
-		return false;
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-	if(stream_cast(binWidth,tmpStr))
-		return false;
-
-	xmlFree(xmlString);
-	//====
-
-	//Retrieve colour
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"colour"))
-		return false;
-	if(!parseXMLColour(nodePtr,rgba))
-		return false;
-	//====
-	
-	//Retrieve plot type 
-	//====
-	if(XMLHelpFwdToElem(nodePtr,"plottype"))
-		return false;
-
-	xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
-	if(!xmlString)
-		return false;
-	tmpStr=(char *)xmlString;
-
-	//convert from string to digit
-	if(stream_cast(plotStyle,tmpStr))
-		return false;
-
-	if(plotStyle >= PLOT_LINE_NONE)
-	       return false;	
-	xmlFree(xmlString);
-	//====
-
-	return true;
-}
-
-unsigned int CompositionProfileFilter::getRefreshBlockMask() const
-{
-	//Absolutely anything can go through this filter.
-	return 0;
-}
-
-unsigned int CompositionProfileFilter::getRefreshEmitMask() const
-{
-	if(showPrimitive)
-		return STREAM_TYPE_PLOT | STREAM_TYPE_DRAW;
-	else
-		return STREAM_TYPE_PLOT;
-}
-
-unsigned int CompositionProfileFilter::getRefreshUseMask() const
-{
-	return STREAM_TYPE_IONS | STREAM_TYPE_RANGE;
-}
-
-void CompositionProfileFilter::setPropFromBinding(const SelectionBinding &b)
-{
-	switch(b.getID())
-	{
-		case BINDING_CYLINDER_RADIUS:
-		case BINDING_SPHERE_RADIUS:
-			b.getValue(scalarParams[0]);
-			break;
-		case BINDING_CYLINDER_ORIGIN:
-		case BINDING_SPHERE_ORIGIN:
-			b.getValue(vectorParams[0]);
-			break;
-		case BINDING_CYLINDER_DIRECTION:
-		{
-			Point3D pOld=vectorParams[1];
-			b.getValue(vectorParams[1]);
-			//Test getting the bin data.
-			// if something is wrong, abort
-			float length;
-			unsigned int numBins;
-			unsigned int errCode= getBinData(numBins,length);
-			if(errCode || !numBins)
-			{
-				vectorParams[1]=pOld;
-				return;
-			}
-
-			break;
-		}
-		default:
-			ASSERT(false);
-	}
-
-	clearCache();
-}
-
-unsigned int CompositionProfileFilter::getPrimitiveId(const std::string &primitiveName) 
-{
-	for(size_t ui=0;ui<PRIMITIVE_END; ui++)
-	{
-		if( TRANS(PRIMITIVE_NAME[ui]) == primitiveName)
-			return ui;
-	}
-
-	ASSERT(false);
-}
-
-#ifdef DEBUG
-
-bool testDensityCylinder();
-bool testCompositionCylinder();
-void synthComposition(const vector<pair<float,float> > &compositionData,
-			vector<IonHit> &h);
-IonStreamData *synthLinearProfile(const Point3D &start, const Point3D &end,
-					float radialSpread,unsigned int numPts);
-
-bool CompositionProfileFilter::runUnitTests()
-{
-	if(!testDensityCylinder())
-		return false;
-
-	if(!testCompositionCylinder())
-		return false;
-
-	return true;
-}
-
-bool testCompositionCylinder()
-{
-	IonStreamData *d;
-	const size_t NUM_PTS=10000;
-
-	//Create a cylinder of data, forming a linear profile
-	Point3D startPt(-1.0f,-1.0f,-1.0f),endPt(1.0f,1.0f,1.0f);
-	d= synthLinearProfile(startPt,endPt,
-			0.5f, NUM_PTS);
-
-	//Generate two compositions for the test dataset
-	{
-	vector<std::pair<float,float>  > vecCompositions;
-	vecCompositions.push_back(make_pair(2.0f,0.5f));
-	vecCompositions.push_back(make_pair(3.0f,0.5f));
-	synthComposition(vecCompositions,d->data);
-	}
-
-	//Build a faux rangestream
-	RangeStreamData *rngStream;
-	rngStream = new RangeStreamData;
-	rngStream->rangeFile = new RangeFile;
-	
-	RGBf rgb; rgb.red=rgb.green=rgb.blue=1.0f;
-
-	unsigned int aIon,bIon;
-	std::string tmpStr;
-	tmpStr="A";
-	aIon=rngStream->rangeFile->addIon(tmpStr,tmpStr,rgb);
-	tmpStr="B";
-	bIon=rngStream->rangeFile->addIon(tmpStr,tmpStr,rgb);
-	rngStream->rangeFile->addRange(1.5,2.5,aIon);
-	rngStream->rangeFile->addRange(2.5,3.5,bIon);
-	rngStream->enabledIons.resize(2,true);
-	rngStream->enabledRanges.resize(2,true);
-
-	//Construct the composition filter
-	CompositionProfileFilter *f = new CompositionProfileFilter;
-
-	//Build some points to pass to the filter
-	vector<const FilterStreamData*> streamIn,streamOut;
-	
-	bool needUp; std::string s;
-	stream_cast(s,Point3D((startPt+endPt)*0.5f));
-	TEST(f->setProperty(COMPOSITION_KEY_ORIGIN,s,needUp),"set origin");
-	TEST(f->setProperty(COMPOSITION_KEY_MINEVENTS,"0",needUp),"set origin");
-	
-	stream_cast(s,Point3D((endPt-startPt)*0.5f));
-	TEST(f->setProperty(COMPOSITION_KEY_NORMAL,s,needUp),"set direction");
-	TEST(f->setProperty(COMPOSITION_KEY_SHOWPRIMITIVE,"1",needUp),"Set cylinder visibility");
-	TEST(f->setProperty(COMPOSITION_KEY_NORMALISE,"1",needUp),"Disable normalisation");
-	TEST(f->setProperty(COMPOSITION_KEY_RADIUS,"5",needUp),"Set radius");
-	
-	//Inform the filter about the range stream
-	streamIn.push_back(rngStream);
-	f->initFilter(streamIn,streamOut);
-	
-	streamIn.push_back(d);
-	f->setCaching(false);
-
-
-	ProgressData p;
-	TEST(!f->refresh(streamIn,streamOut,p),"Refresh error code");
-
-	//2* plot, 1*rng, 1*draw
-	TEST(streamOut.size() == 4, "output stream count");
-
-	delete d;
-
-	std::map<unsigned int, unsigned int> countMap;
-	countMap[STREAM_TYPE_PLOT] = 0;
-	countMap[STREAM_TYPE_DRAW] = 0;
-	countMap[STREAM_TYPE_RANGE] = 0;
-
-	for(unsigned int ui=0;ui<streamOut.size();ui++)
-	{
-		ASSERT(countMap.find(streamOut[ui]->getStreamType()) != countMap.end());
-		countMap[streamOut[ui]->getStreamType()]++;
-	}
-
-	TEST(countMap[STREAM_TYPE_PLOT] == 2,"Plot count");
-	TEST(countMap[STREAM_TYPE_DRAW] == 1,"Draw count");
-	TEST(countMap[STREAM_TYPE_RANGE] == 1,"Range count");
-	
-	const PlotStreamData* plotData=0;
-	for(unsigned int ui=0;ui<streamOut.size();ui++)
-	{
-		if(streamOut[ui]->getStreamType() == STREAM_TYPE_PLOT)
-		{
-			plotData = (const PlotStreamData *)streamOut[ui];
-			break;
-		}
-	}
-	TEST(plotData,"Should have plot data");
-	TEST(plotData->xyData.size(),"Plot data size");
-
-	for(size_t ui=0;ui<plotData->xyData.size(); ui++)
-	{
-		TEST(plotData->xyData[ui].second <= 1.0f && 
-			plotData->xyData[ui].second >=0.0f,"normalised data range test"); 
-	}
-
-	delete rngStream->rangeFile;
-	for(unsigned int ui=0;ui<streamOut.size();ui++)
-		delete streamOut[ui];
-
-
-	delete f;
-
-	return true;
-}
-
-bool testDensityCylinder()
-{
-	IonStreamData *d;
-	const size_t NUM_PTS=10000;
-
-	//Create a cylinder of data, forming a linear profile
-	Point3D startPt(-1.0f,-1.0f,-1.0f),endPt(1.0f,1.0f,1.0f);
-	d= synthLinearProfile(startPt,endPt,
-			0.5f, NUM_PTS);
-
-	//Generate two compositions for the test dataset
-	{
-	vector<std::pair<float,float>  > vecCompositions;
-	vecCompositions.push_back(make_pair(2.0f,0.5f));
-	vecCompositions.push_back(make_pair(3.0f,0.5f));
-	synthComposition(vecCompositions,d->data);
-	}
-
-	CompositionProfileFilter *f = new CompositionProfileFilter;
-	f->setCaching(false);
-
-	//Build some points to pass to the filter
-	vector<const FilterStreamData*> streamIn,streamOut;
-	streamIn.push_back(d);
-	
-	bool needUp; std::string s;
-	stream_cast(s,Point3D((startPt+endPt)*0.5f));
-	TEST(f->setProperty(COMPOSITION_KEY_ORIGIN,s,needUp),"set origin");
-	
-	stream_cast(s,Point3D((endPt-startPt)));
-	TEST(f->setProperty(COMPOSITION_KEY_NORMAL,s,needUp),"set direction");
-	
-	TEST(f->setProperty(COMPOSITION_KEY_SHOWPRIMITIVE,"1",needUp),"Set cylinder visibility");
-
-	TEST(f->setProperty(COMPOSITION_KEY_NORMALISE,"0",needUp),"Disable normalisation");
-	TEST(f->setProperty(COMPOSITION_KEY_RADIUS,"5",needUp),"Set radius");
-
-	ProgressData p;
-	TEST(!f->refresh(streamIn,streamOut,p),"Refresh error code");
-	delete f;
-	delete d;
-
-
-	TEST(streamOut.size() == 2, "output stream count");
-
-	std::map<unsigned int, unsigned int> countMap;
-	countMap[STREAM_TYPE_PLOT] = 0;
-	countMap[STREAM_TYPE_DRAW] = 0;
-
-	for(unsigned int ui=0;ui<streamOut.size();ui++)
-	{
-		ASSERT(countMap.find(streamOut[ui]->getStreamType()) != countMap.end());
-		countMap[streamOut[ui]->getStreamType()]++;
-	}
-
-	TEST(countMap[STREAM_TYPE_PLOT] == 1,"Plot count");
-	TEST(countMap[STREAM_TYPE_DRAW] == 1,"Draw count");
-
-	
-	const PlotStreamData* plotData=0;
-	for(unsigned int ui=0;ui<streamOut.size();ui++)
-	{
-		if(streamOut[ui]->getStreamType() == STREAM_TYPE_PLOT)
-		{
-			plotData = (const PlotStreamData *)streamOut[ui];
-			break;
-		}
-	}
-
-	float sum=0;
-	for(size_t ui=0;ui<plotData->xyData.size(); ui++)
-		sum+=plotData->xyData[ui].second;
-
-
-	TEST(sum > NUM_PTS/1.2f,"Number points roughly OK");
-	TEST(sum <= NUM_PTS,"No overcounting");
-	
-	for(unsigned int ui=0;ui<streamOut.size();ui++)
-		delete streamOut[ui];
-
-	return true;
-}
-
-
-//first value in pair is target mass, second value is target composition
-void synthComposition(const vector<std::pair<float,float> > &compositionData,
-			vector<IonHit> &h)
-{
-	float fractionSum=0;
-	for(size_t ui=0;ui<compositionData.size(); ui++)
-		fractionSum+=compositionData[ui].second;
-
-	//build the spacings between 0 and 1, so we can
-	//randomly select ions by uniform deviates
-	vector<std::pair<float,float> > ionCuts;
-	ionCuts.resize(compositionData.size());
-	//ionCuts.resize[compositionData.size()];
-	float runningSum=0;
-	for(size_t ui=0;ui<ionCuts.size(); ui++)
-	{
-		runningSum+=compositionData[ui].second;
-		ionCuts[ui]=make_pair(compositionData[ui].first, 
-				runningSum/fractionSum);
-	}
-
-	RandNumGen rngHere;
-	rngHere.initTimer();
-	for(size_t ui=0;ui<h.size();ui++)
-	{
-
-		float newMass;
-		bool haveSetMass;
-		
-		//keep generating random selections until we hit something.
-		// This is to prevent any fp fallthrough
-		do
-		{
-			float uniformDeviate;
-			uniformDeviate=rngHere.genUniformDev();
-
-			haveSetMass=false;
-			//This is not efficient -- data is sorted,
-			//so binary search would work, but whatever.
-			for(size_t uj=0;uj<ionCuts.size();uj++)	
-			{
-				if(uniformDeviate >=ionCuts[uj].second)
-				{
-					newMass=ionCuts[uj].first;
-					haveSetMass=true;
-					break;
-				}
-			}
-		}while(!haveSetMass);
-
-
-		h[ui].setMassToCharge(newMass);
-	}
-}
-
-
-//Create a line of points of fixed mass (1), with a top-hat radial spread function
-// so we end up with a cylinder of unit mass data along some start-end axis
-//you must free the returned value by calling "delete"
-IonStreamData *synthLinearProfile(const Point3D &start, const Point3D &end,
-					float radialSpread,unsigned int numPts)
-{
-
-	ASSERT((start-end).sqrMag() > std::numeric_limits<float>::epsilon());
-	IonStreamData *d = new IonStreamData;
-
-	IonHit h;
-	h.setMassToCharge(1.0f);
-
-	Point3D delta; 
-	delta=(end-start)*1.0f/(float)numPts;
-
-	RandNumGen rngAxial;
-	rngAxial.initTimer();
-	
-	Point3D unitDelta;
-	unitDelta=delta;
-	unitDelta.normalise();
-	
-	
-	d->data.resize(numPts);
-	for(size_t ui=0;ui<numPts;ui++)
-	{
-		//generate a random offset vector
-		//that is normal to the axis of the simulation
-		Point3D randomVector;
-		do
-		{
-			randomVector=Point3D(rngAxial.genUniformDev(),
-					rngAxial.genUniformDev(),
-					rngAxial.genUniformDev());
-		}while(randomVector.sqrMag() < std::numeric_limits<float>::epsilon() &&
-			randomVector.angle(delta) < std::numeric_limits<float>::epsilon());
-
-		
-		randomVector=randomVector.crossProd(unitDelta);
-		randomVector.normalise();
-
-		//create the point
-		Point3D pt;
-		pt=delta*(float)ui + start; //true location
-		pt+=randomVector*radialSpread;
-		h.setPos(pt);
-		d->data[ui] =h;
-	}
-
-	return d;
-}
-#endif
diff --git a/src/backend/filters/compositionProfile.h b/src/backend/filters/compositionProfile.h
deleted file mode 100644
index 73e1eb0..0000000
--- a/src/backend/filters/compositionProfile.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- *	compositionProfile.h - Composition profiles of 3D point clouds
- *	Copyright (C) 2015, D Haley 
-
- *	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 3 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/>.
-*/
-#ifndef COMPPROFILE_H
-#define COMPPROFILE_H
-#include "../filter.h"
-#include "../../common/translation.h"
-
-#include <map>
-
-enum
-{
-	COMPOSITION_KEY_BINWIDTH=1,
-	COMPOSITION_KEY_FIXEDBINS,
-	COMPOSITION_KEY_NORMAL,
-	COMPOSITION_KEY_MINEVENTS,
-	COMPOSITION_KEY_NUMBINS,
-	COMPOSITION_KEY_ORIGIN,
-	COMPOSITION_KEY_PLOTTYPE,
-	COMPOSITION_KEY_PRIMITIVETYPE,
-	COMPOSITION_KEY_RADIUS,
-	COMPOSITION_KEY_SHOWPRIMITIVE,
-	COMPOSITION_KEY_NORMALISE,
-	COMPOSITION_KEY_COLOUR,
-	COMPOSITION_KEY_ERRMODE,
-	COMPOSITION_KEY_AVGWINSIZE,
-	COMPOSITION_KEY_LOCKAXISMAG
-};
-//!Filter that does composition profiles for various primitives
-class CompositionProfileFilter : public Filter
-{
-	private:
-
-		//!Number explaining basic primitive type
-		/* Possible Modes:
-		 * Cylindrical (origin + axis + length)
-		 */
-		unsigned int primitiveType;
-		//!Whether to show the primitive or not
-		bool showPrimitive;
-		//Lock the primitive axis during for cylinder?
-		bool lockAxisMag; 
-		//!Vector parameters for different primitives
-		std::vector<Point3D> vectorParams;
-		//!Scalar parameters for different primitives
-		std::vector<float> scalarParams;
-
-		//!Frequency or percentile mode (0 - frequency; 1-normalised (ion freq))
-		bool normalise;
-		//!Use fixed bins?
-		bool fixedBins;
-		
-		//!number of bins (if using fixed bins)
-		unsigned int nBins;
-		//!Width of each bin (if using fixed width)
-		float binWidth;
-
-		//!Number of events required for an entry to be logged in a normalised
-		// histogram
-		unsigned int minEvents;
-		
-		//Plotting stuff
-		//--
-		//colour of plot
-		ColourRGBAf rgba;
-		//Mode for plotting (eg lines, steps)
-		unsigned int plotStyle;
-	
-		PLOT_ERROR errMode;
-
-		//!Do we have a range file above us in our filter tree? This is set by ::initFilter
-		bool haveRangeParent;
-		//--
-		
-		//!internal function for binning an ion dependant upon range data
-		static void binIon(unsigned int targetBin, const RangeStreamData* rng, const std::map<unsigned int,unsigned int> &ionIDMapping,
-			std::vector<std::vector<size_t> > &frequencyTable, float massToCharge);
-
-		static unsigned int getPrimitiveId(const std::string &s);;
-
-		//obtain the size of each bin, and number of bins required for profile
-		unsigned int getBinData(unsigned int &numBins, float &binLength) const;
-
-		//Obtain the X coordinate of a given bin's centre, given the bin value
-		float getBinPosition(unsigned int nBin) const;
-
-	public:
-		CompositionProfileFilter();
-		//!Duplicate filter contents, excluding cache.
-		Filter *cloneUncached() const;
-		//!Returns FILTER_TYPE_COMPOSITION
-		unsigned int getType() const { return FILTER_TYPE_COMPOSITION;};
-
-		//!Get approx number of bytes for caching output
-		size_t numBytesForCache(size_t nObjects) const;
-		
-
-		//!Initialise filter, check for upstream range
-		virtual void initFilter(const std::vector<const FilterStreamData *> &dataIn,
-				std::vector<const FilterStreamData *> &dataOut);
-		//!update filter
-		unsigned int refresh(const std::vector<const FilterStreamData *> &dataIn,
-						std::vector<const FilterStreamData *> &getOut, 
-						ProgressData &progress);
-		
-		virtual std::string typeString() const { return std::string(TRANS("Comp. Prof."));};
-
-		//!Get the properties of the filter, in key-value form. First vector is for each output.
-		void getProperties(FilterPropGroup &propertyList) const;
-
-		//!Set the properties for the nth filter. Returns true if prop set OK
-		bool setProperty(unsigned int key, 
-				const std::string &value, bool &needUpdate);
-		//!Get the human readable error string associated with a particular error code during refresh(...)
-		std::string getSpecificErrString(unsigned int code) const;
-		
-		//!Dump state to output stream, using specified format
-		bool writeState(std::ostream &f,unsigned int format, 
-						unsigned int depth=0) const;
-		//!Read the state of the filter from XML file. If this
-		//fails, filter will be in an undefined state.
-		bool readState(xmlNodePtr &node, const std::string &packDir);
-		//!Get the stream types that will be dropped during ::refresh	
-		unsigned int getRefreshBlockMask() const;
-
-		//!Get the stream types that will be generated during ::refresh	
-		unsigned int getRefreshEmitMask() const;	
-		
-		//!Get the stream types that may be utilised in computation during ::refresh
-		unsigned int getRefreshUseMask() const;	
-	
-		//!Set internal property value using a selection binding  
-		void setPropFromBinding(const SelectionBinding &b) ;
-
-		void setUserString(const std::string &s); 
-
-#ifdef DEBUG
-		bool runUnitTests() ;
-#endif
-};
-
-#endif
diff --git a/src/backend/filters/dataLoad.cpp b/src/backend/filters/dataLoad.cpp
index 0fd76bb..4210007 100644
--- a/src/backend/filters/dataLoad.cpp
+++ b/src/backend/filters/dataLoad.cpp
@@ -67,7 +67,7 @@ const char *AVAILABLE_FILEDATA_TYPES[] = { 	NTRANS("POS Data"),
 					NTRANS("Text Data"),
 					NTRANS("ATO Data"),
 					};
-const char *DEFAULT_LABEL="Mass-to-Charge (amu/e)";
+const char *DEFAULT_LABEL="Mass-to-Charge (Da/e)";
 
 
 
diff --git a/src/backend/filters/filterCommon.cpp b/src/backend/filters/filterCommon.cpp
index aa3e8e8..8ddf727 100644
--- a/src/backend/filters/filterCommon.cpp
+++ b/src/backend/filters/filterCommon.cpp
@@ -54,6 +54,9 @@ void writeIonsEnabledXML(ostream &f, const char *containerName,
 		const vector<bool> &enabledState, const vector<string> &names, 
 			unsigned int depth)
 {
+	if(enabledState.size()!=names.size())
+		return;
+
 	f << tabs(depth) << "<" << containerName << ">"  << endl;
 	for(size_t ui=0;ui<enabledState.size();ui++)
 	{
@@ -63,6 +66,31 @@ void writeIonsEnabledXML(ostream &f, const char *containerName,
 	f << tabs(depth) << "</" << containerName << ">"  << endl;
 }
 
+void readIonsEnabledXML(xmlNodePtr nodePtr,  vector<bool> &enabledStatus,vector<string> &ionNames)
+{
+	//skip conatainer name
+	nodePtr=nodePtr->xmlChildrenNode;
+
+	if(!nodePtr)
+		return;
+
+	enabledStatus.clear();
+	while(!XMLHelpFwdToElem(nodePtr,"ion"))
+	{
+		int enabled;
+		if(!XMLGetAttrib(nodePtr,enabled,"enabled"))
+			return ;
+
+		std::string tmpName;
+		if(!XMLGetAttrib(nodePtr,tmpName,"name"))
+			return;
+	
+		enabledStatus.push_back(enabled);
+		
+		ionNames.push_back(tmpName);
+	}
+	
+}
 bool readVectorsXML(xmlNodePtr nodePtr,	std::vector<Point3D> &vectorParams) 
 {
 	nodePtr=nodePtr->xmlChildrenNode;
@@ -246,63 +274,6 @@ unsigned int getIonstreamIonID(const IonStreamData *d, const RangeFile *r)
 	return tentativeRange;	
 }
 
-//!Extend a point data vector using some ion data
-unsigned int extendPointVector(std::vector<Point3D> &dest, const std::vector<IonHit> &vIonData,
-				unsigned int &progress, size_t offset)
-{
-	unsigned int curProg=NUM_CALLBACK;
-	unsigned int n =offset;
-#ifdef _OPENMP
-	//Parallel version
-	bool spin=false;
-	#pragma omp parallel for shared(spin)
-	for(size_t ui=0;ui<vIonData.size();ui++)
-	{
-		if(spin)
-			continue;
-		dest[offset+ ui] = vIonData[ui].getPosRef();
-		
-		//update progress every CALLBACK entries
-		if(!curProg--)
-		{
-			#pragma omp critical
-			{
-			n+=NUM_CALLBACK;
-			progress= (unsigned int)(((float)n/(float)dest.size())*100.0f);
-			if(!omp_get_thread_num())
-			{
-				if(*Filter::wantAbort)
-					spin=true;
-			}
-			}
-		}
-
-	}
-
-	if(spin)
-		return 1;
-#else
-
-	for(size_t ui=0;ui<vIonData.size();ui++)
-	{
-		dest[offset+ ui] = vIonData[ui].getPosRef();
-		
-		//update progress every CALLBACK ions
-		if(!curProg--)
-		{
-			n+=NUM_CALLBACK;
-			progress= (unsigned int)(((float)n/(float)dest.size())*100.0f);
-			if(*(Filter::wantAbort))
-				return 1;
-		}
-
-	}
-#endif
-
-
-	return 0;
-}
-
 
 //FIXME: Abort pointer?
 unsigned int computeConvexHull(const vector<const FilterStreamData*> &data, unsigned int *progress,
diff --git a/src/backend/filters/filterCommon.h b/src/backend/filters/filterCommon.h
index e1bbf36..56a98e8 100644
--- a/src/backend/filters/filterCommon.h
+++ b/src/backend/filters/filterCommon.h
@@ -48,17 +48,23 @@ enum
 	HULL_ERR_ENUM_END
 };
 
+//TODO: Namespace this into the filter base class?
+
 const size_t PROGRESS_REDUCE=5000;
 
 //serialise 3D std::vectors to specified output stream in XML format
 void writeVectorsXML(std::ostream &f, const char *containerName,
 		const std::vector<Point3D> &vectorParams, unsigned int depth);
 
-//Serialise out "enabled" ions as XML
+//Serialise out "enabled" ions as XML. If the iput vectors are not of equal length,
+// no data will be written
 void writeIonsEnabledXML(std::ostream &f, const char *containerName, 
 		const std::vector<bool> &enabledState, const std::vector<std::string> &names, 
 			unsigned int depth);
 
+//Read an enabled ions file as XML
+void readIonsEnabledXML(xmlNodePtr nodePtr, vector<bool> &enabledStatus, vector<string> &names);
+
 //serialise 3D scalars to specified output stream in XML format
 // - depth is tab indentation depth
 // - container name for : <container> (newline) <scalar .../><scalar ... /> </container>
@@ -68,7 +74,7 @@ void writeScalarsXML(std::ostream &f, const char *containerName,
 {
 	f << tabs(depth) << "<"  << containerName << ">" << std::endl;
 	for(unsigned int ui=0; ui<scalarParams.size(); ui++)
-		f << tabs(depth+1) << "<scalar value=\"" << scalarParams[0] << "\"/>" << std::endl; 
+		f << tabs(depth+1) << "<scalar value=\"" << scalarParams[ui] << "\"/>" << std::endl; 
 	
 	f << tabs(depth) << "</" << containerName << ">" << std::endl;
 }
@@ -113,9 +119,77 @@ bool parseXMLColour(xmlNodePtr &nodePtr, ColourRGBAf &rgbaf);
 // is ranged tht way. Otherwise returns -1.
 unsigned int getIonstreamIonID(const IonStreamData *d, const RangeFile *r);
 
-//!Extend a point data vector using some ion data
-unsigned int extendPointVector(std::vector<Point3D> &dest, const std::vector<IonHit> &vIonData,
-				unsigned int &progress, size_t offset);
+inline 
+void assignIonData(Point3D &p, const IonHit &h)
+{
+	p = h.getPosRef();
+}
+
+inline
+void assignIonData(IonHit &p, const IonHit &h)
+{
+	p = h;
+}
+
+//!Extend a point data vector using some ion data. 
+// Offset is the position to start inserting in the destination array.
+// Will fail if user abort is detected 
+template<class T>
+unsigned int extendDataVector(std::vector<T> &dest, const std::vector<IonHit> &vIonData,
+				unsigned int &progress, size_t offset)
+{
+	unsigned int curProg=NUM_CALLBACK;
+	unsigned int n =offset;
+#ifdef _OPENMP
+	//Parallel version
+	bool spin=false;
+	#pragma omp parallel for shared(spin)
+	for(size_t ui=0;ui<vIonData.size();ui++)
+	{
+		if(spin)
+			continue;
+		assignIonData(dest[offset+ ui],vIonData[ui]);
+		
+		//update progress every CALLBACK entries
+		if(!curProg--)
+		{
+			#pragma omp critical
+			{
+			n+=NUM_CALLBACK;
+			progress= (unsigned int)(((float)n/(float)dest.size())*100.0f);
+			if(!omp_get_thread_num())
+			{
+				if(*Filter::wantAbort)
+					spin=true;
+			}
+			}
+		}
+
+	}
+
+	if(spin)
+		return 1;
+#else
+
+	for(size_t ui=0;ui<vIonData.size();ui++)
+	{
+		assignIonData(dest[offset+ ui],vIonData[ui]);
+		
+		//update progress every CALLBACK ions
+		if(!curProg--)
+		{
+			n+=NUM_CALLBACK;
+			progress= (unsigned int)(((float)n/(float)dest.size())*100.0f);
+			if(*(Filter::wantAbort))
+				return 1;
+		}
+
+	}
+#endif
+
+
+	return 0;
+}
 
 const RangeFile *getRangeFile(const std::vector<const FilterStreamData*> &dataIn);
 
diff --git a/src/backend/filters/geometryHelpers.cpp b/src/backend/filters/geometryHelpers.cpp
index e7aaf31..6dff855 100644
--- a/src/backend/filters/geometryHelpers.cpp
+++ b/src/backend/filters/geometryHelpers.cpp
@@ -455,18 +455,21 @@ unsigned int CropHelper::mapCylinderInsideRadial( const Point3D &testPt) const
 		//rotate ion position into cylindrical coordinates
 		quat_rot_apply_quat(&p,&qA);
 
+		fSqrRad=p.fx*p.fx + p.fy*p.fy;
 		//Check inside upper and lower bound of cylinder
 		// and check inside cylinder radius
-		if(!(p.fz < fA && p.fz > -fA && 
-				p.fx*p.fx+p.fy*p.fy < fB))
+		if(!( (p.fz < fA && p.fz > -fA ) &&  
+					fSqrRad < fB))
 			return (unsigned int)-1;
 
-		fSqrRad=ptmp[0]*ptmp[0] + ptmp[1]*ptmp[1];
-		
 	}
 
+	unsigned int mapPos;
+	mapPos=(unsigned int)(fSqrRad/fB*(float)mapMax);
+	ASSERT(mapPos < mapMax);
+
 	//Area is constant in square space
-	return (unsigned int)(fSqrRad/fB*(float)mapMax);
+	return mapPos;
 
 }
 
@@ -523,8 +526,11 @@ unsigned int CropHelper::mapIon1D(const IonHit &ionIn) const
 	ASSERT(!invertedClip);
 	ASSERT(mapFunc);
 	ASSERT(mapMax);
-	//return the 1D mapping for the ion
-	return (this->*mapFunc)(ionIn.getPosRef());
+	//return the 1D mapping for the ion, or -1 for not mappable
+	unsigned int mappingPos;
+	mappingPos=(this->*mapFunc)(ionIn.getPosRef());
+	ASSERT(mappingPos < mapMax || mappingPos == (unsigned int) -1);
+	return mappingPos; 
 }
 
 void CropHelper::setFilterMode(size_t filterMode)
diff --git a/src/backend/filters/ionClip.cpp b/src/backend/filters/ionClip.cpp
index d0d1276..3ec3e77 100644
--- a/src/backend/filters/ionClip.cpp
+++ b/src/backend/filters/ionClip.cpp
@@ -442,7 +442,6 @@ unsigned int IonClipFilter::refresh(const std::vector<const FilterStreamData *>
 						d->b =((IonStreamData *)dataIn[ui])->b;
 						d->a =((IonStreamData *)dataIn[ui])->a;
 						d->ionSize =((IonStreamData *)dataIn[ui])->ionSize;
-						d->representationType=((IonStreamData *)dataIn[ui])->representationType;
 
 						//getOut is const, so shouldn't be modified
 						cacheAsNeeded(d);
@@ -467,6 +466,8 @@ unsigned int IonClipFilter::refresh(const std::vector<const FilterStreamData *>
 			delete d;
 		return BAD_ALLOC;
 	}
+
+	progress.filterProgress=100;
 	return 0;
 
 }
diff --git a/src/backend/filters/ionColour.cpp b/src/backend/filters/ionColour.cpp
index 72aba88..c3803ec 100644
--- a/src/backend/filters/ionColour.cpp
+++ b/src/backend/filters/ionColour.cpp
@@ -92,16 +92,6 @@ unsigned int IonColourFilter::refresh(const std::vector<const FilterStreamData *
 
 		propagateCache(getOut);
 
-		if(filterOutputs.size() && showColourBar)
-		{
-			//TODO:  Can I remove this? Caching for drawables now should work, right?
-			DrawStreamData *d = new DrawStreamData;
-			d->parent=this;
-			d->drawables.push_back(makeColourBar(mapBounds[0],
-					mapBounds[1],nColours,colourMap,alpha));
-			d->cached=0;
-			getOut.push_back(d);
-		}
 		return 0;
 	}
 
@@ -160,6 +150,8 @@ unsigned int IonColourFilter::refresh(const std::vector<const FilterStreamData *
 				for(vector<IonHit>::const_iterator it=((const IonStreamData *)dataIn[ui])->data.begin();
 					       it!=((const IonStreamData *)dataIn[ui])->data.end(); ++it)
 				{
+					//Work out the colour map assignment from the mass to charge.
+					// linear assignment in range
 					unsigned int colour;
 
 					float tmp;	
@@ -200,7 +192,7 @@ unsigned int IonColourFilter::refresh(const std::vector<const FilterStreamData *
 		DrawStreamData *d = new DrawStreamData;
 		d->drawables.push_back(makeColourBar(mapBounds[0],mapBounds[1],nColours,colourMap,reverseMap,alpha));
 		d->parent=this;
-		d->cached=0;
+		cacheAsNeeded(d);
 		getOut.push_back(d);
 	}
 
@@ -355,7 +347,9 @@ bool IonColourFilter::setProperty(  unsigned int key,
 		case KEY_IONCOLOURFILTER_MAPSTART:
 		{
 			float tmpBound;
-			stream_cast(tmpBound,value);
+			if(stream_cast(tmpBound,value))
+				return false;
+
 			if(tmpBound >=mapBounds[1])
 				return false;
 
diff --git a/src/backend/filters/ionDownsample.cpp b/src/backend/filters/ionDownsample.cpp
index b6e6bfc..100bfa0 100644
--- a/src/backend/filters/ionDownsample.cpp
+++ b/src/backend/filters/ionDownsample.cpp
@@ -91,8 +91,8 @@ void IonDownsampleFilter::initFilter(const std::vector<const FilterStreamData *>
 			if(ionFractions.size() != c->rangeFile->getNumIons())
 			{
 				//set up some defaults; seeded from normal
-				ionFractions.resize(c->rangeFile->getNumIons(),fraction);
-				ionLimits.resize(c->rangeFile->getNumIons(),maxAfterFilter);
+				ionFractions.resize(c->rangeFile->getNumIons()+1,fraction);
+				ionLimits.resize(c->rangeFile->getNumIons()+1,maxAfterFilter);
 			}
 		}
 		else
@@ -110,15 +110,15 @@ void IonDownsampleFilter::initFilter(const std::vector<const FilterStreamData *>
 				rsdIncoming = new RangeStreamData;
 				*rsdIncoming=*c;
 
-				ionFractions.resize(c->rangeFile->getNumIons(),fraction);
-				ionLimits.resize(c->rangeFile->getNumIons(),maxAfterFilter);
+				ionFractions.resize(c->rangeFile->getNumIons()+1,fraction);
+				ionLimits.resize(c->rangeFile->getNumIons()+1,maxAfterFilter);
 			}
 			else if(ionFractions.size() !=c->rangeFile->getNumIons())
 			{
 				//well its the same range, but somehow the number of ions 
 				//have changed. Could be range was reloaded.
-				ionFractions.resize(rsdIncoming->rangeFile->getNumIons(),fraction);
-				ionLimits.resize(rsdIncoming->rangeFile->getNumIons(),maxAfterFilter);
+				ionFractions.resize(rsdIncoming->rangeFile->getNumIons()+1,fraction);
+				ionLimits.resize(rsdIncoming->rangeFile->getNumIons()+1,maxAfterFilter);
 			}
 
 			//Ensure what is enabled and is disabled is up-to-date	
@@ -268,7 +268,6 @@ unsigned int IonDownsampleFilter::refresh(const std::vector<const FilterStreamDa
 					d->b =((IonStreamData *)dataIn[ui])->b;
 					d->a =((IonStreamData *)dataIn[ui])->a;
 					d->ionSize =((IonStreamData *)dataIn[ui])->ionSize;
-					d->representationType=((IonStreamData *)dataIn[ui])->representationType;
 					d->valueType=((IonStreamData *)dataIn[ui])->valueType;
 
 					//getOut is const, so shouldn't be modified
@@ -292,9 +291,9 @@ unsigned int IonDownsampleFilter::refresh(const std::vector<const FilterStreamDa
 
 		//Construct two vectors. One with the ion IDs for each input
 		//ion stream. the other with the total number of ions in the input
-		//for each ion type 
+		//for each ion type. There is an extra slot for unranged data
 		vector<size_t> numIons,ionIDVec;
-		numIons.resize(rsdIncoming->rangeFile->getNumIons(),0);
+		numIons.resize(rsdIncoming->rangeFile->getNumIons()+1,0);
 
 		for(unsigned int uj=0;uj<dataIn.size() ;uj++)
 		{
@@ -303,14 +302,22 @@ unsigned int IonDownsampleFilter::refresh(const std::vector<const FilterStreamDa
 				input=(const IonStreamData*)dataIn[uj];
 				if(input->data.size())
 				{
+					//Use the first ion to guess the identity of the entire stream
 					unsigned int ionID;
 					ionID=rsdIncoming->rangeFile->getIonID(
 						input->data[0].getMassToCharge()); 
-
 					if(ionID != (unsigned int)-1)
+					{
 						numIons[ionID]+=input->data.size();
-					
-					ionIDVec.push_back(ionID);
+						ionIDVec.push_back(ionID);
+					}
+					else
+					{
+						numIons[numIons.size()-1]+=input->data.size();
+						ionIDVec.push_back(numIons.size()-1);
+					}
+
+
 				}
 			}
 		}
@@ -329,12 +336,6 @@ unsigned int IonDownsampleFilter::refresh(const std::vector<const FilterStreamDa
 					if(input->data.empty())
 						continue;
 
-					//FIXME: Allow processing of unranged data
-					//Don't process streams that are not ranged, as we cannot get their desired fractions
-					//at this time
-					if(ionIDVec[idPos]==(unsigned int)-1)
-						continue;
-
 					IonStreamData *d;
 					d=new IonStreamData;
 					d->parent=this;
@@ -403,7 +404,6 @@ unsigned int IonDownsampleFilter::refresh(const std::vector<const FilterStreamDa
 						d->b =input->b;
 						d->a =input->a;
 						d->ionSize =input->ionSize;
-						d->representationType=input->representationType;
 						d->valueType=input->valueType;
 
 
@@ -472,9 +472,9 @@ void IonDownsampleFilter::getProperties(FilterPropGroup &propertyList) const
 		else
 			typeVal=PROPERTY_TYPE_REAL;
 
-		bool haveProp=false;
+		unsigned int numIons=rsdIncoming->enabledIons.size();
 		//create a  single line for each
-		for(unsigned  int ui=0; ui<rsdIncoming->enabledIons.size(); ui++)
+		for(unsigned  int ui=0; ui<numIons; ui++)
 		{
 			if(rsdIncoming->enabledIons[ui])
 			{
@@ -490,11 +490,19 @@ void IonDownsampleFilter::getProperties(FilterPropGroup &propertyList) const
 				p.key=KEY_IONDOWNSAMPLE_DYNAMIC+ui;
 				propertyList.addProperty(p,curGroup);
 				
-				haveProp=true;
 			}
 		}
-		if(haveProp)
-			propertyList.setGroupTitle(curGroup,TRANS("Sampling rates"));
+
+		p.name=TRANS("Unranged");
+		if(fixedNumOut)
+			stream_cast(tmpStr,ionLimits[numIons]);
+		else
+			stream_cast(tmpStr,ionFractions[numIons]);
+		p.data=tmpStr;
+		p.key=KEY_IONDOWNSAMPLE_DYNAMIC+numIons;
+		propertyList.addProperty(p,curGroup);
+
+		propertyList.setGroupTitle(curGroup,TRANS("Sampling rates"));
 	}
 	else
 	{
diff --git a/src/backend/filters/rangeFile.cpp b/src/backend/filters/rangeFile.cpp
index 479a92f..5a1a978 100644
--- a/src/backend/filters/rangeFile.cpp
+++ b/src/backend/filters/rangeFile.cpp
@@ -116,6 +116,11 @@ unsigned int RangeFileFilter::refresh(const std::vector<const FilterStreamData *
 		return 0;
 	}
 
+	progress.filterProgress=0;
+	progress.stepName=TRANS("Ranging");
+	progress.step=1;
+	progress.maxStep=1;	
+
 
 	ASSERT(enabledRanges.size() == rng.getNumRanges());
 	ASSERT(enabledIons.size() == rng.getNumIons());
@@ -148,11 +153,6 @@ unsigned int RangeFileFilter::refresh(const std::vector<const FilterStreamData *
 		sameSize=true;
 
 
-		progress.step=1;
-		progress.filterProgress=0;
-		progress.stepName=TRANS("Pre-Allocate");
-		progress.maxStep=2;	
-
 		vector<size_t> dSizes;
 		dSizes.resize(d.size(),0);
 		size_t totalSize=numElements(dataIn);
@@ -249,7 +249,12 @@ unsigned int RangeFileFilter::refresh(const std::vector<const FilterStreamData *
 						}
 
 						if(spin)
+						{
+#ifdef _OPENMP
+							delete[] dSizeArr;
+#endif
 							return RANGEFILE_ABORT_FAIL;
+						}
 #ifdef _OPENMP
 						//Merge the arrays back together
 						for(unsigned int uk=0;uk<nT;uk++)
@@ -270,7 +275,7 @@ unsigned int RangeFileFilter::refresh(const std::vector<const FilterStreamData *
 		{
 			//slightly over-allocate to allow for any variance
 			for(size_t ui=0;ui<d.size();ui++)
-				d[ui]->data.reserve(dSizes[ui]*1.f*RANGE_ALLOC_STEP+10);
+				d[ui]->data.reserve(dSizes[ui]*1.05f*RANGE_ALLOC_STEP+10);
 		}
 		catch(std::bad_alloc)
 		{
@@ -282,12 +287,6 @@ unsigned int RangeFileFilter::refresh(const std::vector<const FilterStreamData *
 		dSizes.clear();
 		//===================================
 
-		//Update progress info
-		progress.step=2;
-		progress.filterProgress=0;
-		progress.stepName=TRANS("Range");
-
-
 		
 
 		//Step 2: Go through each data stream, if it is an ion stream, range it.
@@ -507,6 +506,9 @@ unsigned int RangeFileFilter::refresh(const std::vector<const FilterStreamData *
 	getOut.push_back(rngData);
 		
 	cacheOK=cache;
+
+	progress.filterProgress=100;
+
 	return 0;
 }
 
diff --git a/src/backend/filters/spatialAnalysis.cpp b/src/backend/filters/spatialAnalysis.cpp
index 8d67790..a24aa7e 100644
--- a/src/backend/filters/spatialAnalysis.cpp
+++ b/src/backend/filters/spatialAnalysis.cpp
@@ -30,6 +30,7 @@
 #include "../APT/APTFileIO.h"
 
 using std::vector;
+using std::set;
 using std::string;
 using std::pair;
 using std::make_pair;
@@ -50,8 +51,10 @@ enum
 	KEY_RETAIN_UPPER,
 	KEY_CUTOFF,
 	KEY_COLOUR,
-	KEY_ENABLE_SOURCE,
-	KEY_ENABLE_TARGET,
+	KEY_ENABLE_SOURCE_ALL,
+	KEY_ENABLE_TARGET_ALL,
+	KEY_ENABLE_NUMERATOR_ALL,
+	KEY_ENABLE_DENOMINATOR_ALL,
 	KEY_ORIGIN,
 	KEY_NORMAL,
 	KEY_RADIUS,
@@ -68,6 +71,14 @@ enum
 	KEY_REPLACE_VALUE,
 };
 
+enum 
+{ 
+	KEYTYPE_ENABLE_SOURCE=1,
+	KEYTYPE_ENABLE_TARGET,
+	KEYTYPE_ENABLE_NUMERATOR,
+	KEYTYPE_ENABLE_DENOMINATOR,
+};
+
 enum {
 	ALGORITHM_DENSITY, //Local density analysis
 	ALGORITHM_DENSITY_FILTER, //Local density filtering
@@ -75,6 +86,7 @@ enum {
 	ALGORITHM_AXIAL_DF, //Axial Distribution Function (aka atomvicinity, sdm, 1D rdf)
 	ALGORITHM_BINOMIAL, //Binomial block method for statistical randomness testing
 	ALGORITHM_REPLACE, //Remove, set or modify points using an external file
+	ALGORITHM_LOCAL_CONCENTRATION, //Obtain a local concentration plot, as described by Hyde and Marquis (TODO : REF)
 	ALGORITHM_ENUM_END,
 };
 
@@ -97,7 +109,7 @@ enum
 {
 	ERR_ABORT_FAIL=1,
 	ERR_BINOMIAL_NO_MEM,
-	ERR_BINOMIAL_NO_RANGE,
+	ERR_NO_RANGE,
 	ERR_BINOMIAL_BIN_FAIL,
 	INSUFFICIENT_SIZE_ERR,
 	ERR_FILE_READ_FAIL,
@@ -113,7 +125,8 @@ const char *SPATIAL_ALGORITHMS[] = {
 	NTRANS("Radial Distribution"),
 	NTRANS("Axial Distribution"),
 	NTRANS("Binomial Distribution"),
-	NTRANS("Point Em/Replacement")
+	NTRANS("Point Em/Replacement"),
+	NTRANS("Local Concentration"),
 	};
 
 const char *STOP_MODES[] = {
@@ -135,12 +148,15 @@ const bool WANT_RANGE_PROPAGATION[] = { false,
 					false,
 					false,
 					true,
+					false,
 					};
 
 
 //Default distance to use when performing axial distance computations
 const float DEFAULT_AXIAL_DISTANCE = 1.0f;
 
+const float DISTANCE_EPSILON=sqrt(std::numeric_limits<float>::epsilon());
+
 
 //Helper function for computing a weighted mean
 float weightedMean(const vector<float> &x, const vector<float> &y,bool zeroOutSingularity=true)
@@ -164,6 +180,140 @@ float weightedMean(const vector<float> &x, const vector<float> &y,bool zeroOutSi
 	return num/denom;
 }
 
+//Scan input datastreams to build two point vectors,
+// one of those with points specified as "target" 
+// which is a copy of the input points
+//Returns 0 on no error, otherwise nonzero
+template<class T>
+size_t buildSplitPoints(const vector<const FilterStreamData *> &dataIn,
+				ProgressData &progress, size_t totalDataSize,
+				const RangeFile *rngF, const vector<bool> &pSourceEnabled, const vector<bool> &pTargetEnabled,
+				vector<T> &pSource, vector<T> &pTarget
+				)
+{
+	size_t sizeNeeded[2];
+	sizeNeeded[0]=sizeNeeded[1]=0;
+
+	//Presize arrays
+	for(unsigned int ui=0; ui<dataIn.size() ; ui++)
+	{
+		switch(dataIn[ui]->getStreamType())
+		{
+			case STREAM_TYPE_IONS:
+			{
+				unsigned int ionID;
+
+				const IonStreamData *d;
+				d=((const IonStreamData *)dataIn[ui]);
+				ionID=getIonstreamIonID(d,rngF);
+
+				if(ionID == (unsigned int)-1)
+				{
+
+					//we have ungrouped ions, so work out size individually
+					for(unsigned int uj=0;uj<d->data.size();uj++)
+					{
+						ionID = rngF->getIonID(d->data[uj].getMassToCharge());
+
+						if(ionID == (unsigned int)-1)
+							continue;
+
+						if(pSourceEnabled[ionID])
+							sizeNeeded[0]++;
+						if(pTargetEnabled[ionID])
+							sizeNeeded[1]++;
+					}
+					
+					break;
+				}
+
+				if(pSourceEnabled[ionID])
+					sizeNeeded[0]+=d->data.size();
+
+				if(pTargetEnabled[ionID])
+					sizeNeeded[1]+=d->data.size();
+
+				break;
+			}
+			default:
+				break;
+		}
+	}
+
+	pSource.resize(sizeNeeded[0]);
+	pTarget.resize(sizeNeeded[1]);
+
+	//Fill arrays
+	size_t curPos[2];
+	curPos[0]=curPos[1]=0;
+
+	for(unsigned int ui=0; ui<dataIn.size() ; ui++)
+	{
+		switch(dataIn[ui]->getStreamType())
+		{
+			case STREAM_TYPE_IONS:
+			{
+				unsigned int ionID;
+				const IonStreamData *d;
+				d=((const IonStreamData *)dataIn[ui]);
+				ionID=getIonstreamIonID(d,rngF);
+
+				if(ionID==(unsigned int)(-1))
+				{
+					//we have ungrouped ions, so work out size individually
+					for(unsigned int uj=0;uj<d->data.size();uj++)
+					{
+						ionID = rngF->getIonID(d->data[uj].getMassToCharge());
+
+						if(ionID == (unsigned int)-1)
+							continue;
+
+						if(pSourceEnabled[ionID])
+						{
+							assignIonData(pSource[curPos[0]],d->data[uj]);
+							curPos[0]++;
+						}
+
+						if(pTargetEnabled[ionID])
+						{
+							assignIonData(pTarget[curPos[1]],d->data[uj]);
+							curPos[1]++;
+						}
+					}
+					
+					break;
+				}
+
+				unsigned int dummyProgress=0;
+				if(pSourceEnabled[ionID])
+				{
+					if(extendDataVector(pSource,d->data,
+					                     dummyProgress,curPos[0]))
+						return ERR_ABORT_FAIL;
+
+					curPos[0]+=d->data.size();
+				}
+
+				if(pTargetEnabled[ionID])
+				{
+					if(extendDataVector(pTarget,d->data,
+					                     dummyProgress,curPos[1]))
+						return ERR_ABORT_FAIL;
+
+					curPos[1]+=d->data.size();
+				}
+
+				break;
+			}
+			default:
+				break;
+		}
+	}
+
+
+	return 0;
+}
+
 SpatialAnalysisFilter::SpatialAnalysisFilter()
 {
 	COMPILE_ASSERT(THREEDEP_ARRAYSIZE(STOP_MODES) == STOP_MODE_ENUM_END);
@@ -256,6 +406,11 @@ Filter *SpatialAnalysisFilter::cloneUncached() const
 	p->vectorParams=vectorParams;
 	p->scalarParams=scalarParams;
 
+	p->ionSourceEnabled=ionSourceEnabled;
+	p->ionTargetEnabled=ionTargetEnabled;
+	p->ionNumeratorEnabled=ionNumeratorEnabled;
+	p->ionDenominatorEnabled=ionDenominatorEnabled;
+	
 	return p;
 }
 
@@ -306,9 +461,12 @@ void SpatialAnalysisFilter::initFilter(const std::vector<const FilterStreamData
 								break;
 							}
 							pos++;
+			
 						}
 					}
 				}
+				else
+					different=true;
 			}
 			haveRangeParent=true;
 
@@ -327,6 +485,9 @@ void SpatialAnalysisFilter::initFilter(const std::vector<const FilterStreamData
 
 				ionSourceEnabled.resize(ionNames.size(),true);
 				ionTargetEnabled.resize(ionNames.size(),true);
+				
+				ionNumeratorEnabled.resize(ionNames.size(),true);
+				ionDenominatorEnabled.resize(ionNames.size(),true);
 			}
 
 			return;
@@ -441,9 +602,8 @@ unsigned int SpatialAnalysisFilter::refresh(const std::vector<const FilterStream
 		case ALGORITHM_BINOMIAL:
 		{
 			if(!rngF)
-			{
-				return ERR_BINOMIAL_NO_RANGE;
-			}
+				return ERR_NO_RANGE;
+			
 			result=algorithmBinomial(progress,totalDataSize,
 						dataIn,getOut,rngF);
 			break;
@@ -452,6 +612,12 @@ unsigned int SpatialAnalysisFilter::refresh(const std::vector<const FilterStream
 			result=algorithmReplace(progress,totalDataSize,
 						dataIn,getOut);
 			break;
+		case ALGORITHM_LOCAL_CONCENTRATION:
+			if(!rngF)
+				return ERR_NO_RANGE;
+			result=algorithmLocalConcentration(progress,totalDataSize,
+						dataIn,getOut,rngF);
+			break;
 		default:
 			ASSERT(false);
 	}
@@ -463,13 +629,25 @@ size_t SpatialAnalysisFilter::algorithmReplace(ProgressData &progress, size_t to
 			const vector<const FilterStreamData *>  &dataIn, 
 			vector<const FilterStreamData * > &getOut)
 {
+	progress.maxStep=4;
+
+	progress.step=1;
+	progress.stepName=TRANS("Collate");
+	progress.filterProgress=0;
+
 	//Merge the ions form the incoming streams
 	vector<IonHit> inIons;
 	Filter::collateIons(dataIn,inIons,progress,totalDataSize);
 	
+	progress.step=2;
+	progress.stepName=TRANS("Load");
+	progress.filterProgress=0;
+
 	vector<IonHit> fileIons;
 	const unsigned int loadPositions[] = {
 						0,1,2,3};
+
+	//Load the other dataset
 	unsigned int errCode=GenericLoadFloatFile(4,4,loadPositions,
 			fileIons,replaceFile.c_str(),progress.filterProgress,*Filter::wantAbort);
 
@@ -477,9 +655,16 @@ size_t SpatialAnalysisFilter::algorithmReplace(ProgressData &progress, size_t to
 		return ERR_FILE_READ_FAIL;
 
 
+
+	progress.step=3;
+	progress.stepName=TRANS("Build");
+	progress.filterProgress=0;
+
+	//Build the search tree we will use to perform replacement
 	K3DTreeMk2 tree;
 	tree.resetPts(fileIons,false);
-	tree.build();
+	if(!tree.build())
+		return ERR_ABORT_FAIL;
 	BoundCube b;
 	tree.getBoundCube(b);
 
@@ -492,31 +677,40 @@ size_t SpatialAnalysisFilter::algorithmReplace(ProgressData &progress, size_t to
 	// as we can use it in sequence, and can use openmp
 	map<size_t,size_t> matchedMap;
 
-	#pragma omp parallel
-	{
 	//Find the nearest point for all points in the dataset
 
-	#pragma omp for 
+	#pragma omp parallel for 
 	for(size_t ui=0;ui<inIons.size();ui++)
 	{
 		nearestVec[ui]=tree.findNearestUntagged(inIons[ui].getPos(),b,false);
 	}
 
+	float sqrReplaceTol=replaceTolerance*replaceTolerance;
+
 	//Filter this to only points that had an NN within range
+	#pragma omp parallel for 
 	for(size_t ui=0;ui<inIons.size();ui++)
 	{
-		if(nearestVec[ui]!=(size_t)-1 && inIons[ui].getPos().sqrDist(*tree.getPt(nearestVec[ui])) <=replaceTolerance)
+		if(nearestVec[ui]!=(size_t)-1 && inIons[ui].getPos().sqrDist(*tree.getPt(nearestVec[ui])) <=sqrReplaceTol)
 		{
 			#pragma omp critical
-			matchedMap[ui]=nearestVec[ui];
+			matchedMap[ui]=tree.getOrigIndex(nearestVec[ui]);
 		}
 	}
-	}
 
 	nearestVec.clear();
 
+
+	progress.step=4;
+	progress.stepName=TRANS("Compute");
+	progress.filterProgress=0;
+
+	//Finish if no matches
 	if(matchedMap.empty())
-		return 1;
+	{
+		progress.filterProgress=100;
+		return 0;
+	}
 
 	vector<IonHit> outIons;
 	switch(replaceMode)
@@ -551,6 +745,7 @@ size_t SpatialAnalysisFilter::algorithmReplace(ProgressData &progress, size_t to
 				for(map<size_t,size_t>::const_iterator it=matchedMap.begin();it!=matchedMap.end();++it)
 				{
 					outIons.push_back(fileIons[it->second]);
+					ASSERT(fileIons[it->second].getPosRef().sqrDist(inIons[it->first].getPosRef()) < sqrReplaceTol);
 				}
 			}
 			else
@@ -620,7 +815,8 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 	if(algorithm ==  ALGORITHM_RDF
 		||  algorithm == ALGORITHM_DENSITY 
 		|| algorithm == ALGORITHM_DENSITY_FILTER 
-		|| algorithm == ALGORITHM_AXIAL_DF)
+		|| algorithm == ALGORITHM_AXIAL_DF
+		|| algorithm == ALGORITHM_LOCAL_CONCENTRATION)
 	{
 		tmpStr=TRANS(STOP_MODES[STOP_MODE_NEIGHBOUR]);
 
@@ -679,6 +875,7 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 			propertyList.addProperty(p,curGroup);
 		}
 
+		propertyList.setGroupTitle(curGroup,TRANS("Stop Mode"));
 	}
 	
 	//Extra options for specific algorithms 
@@ -741,7 +938,7 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 				p.data=sTmp;
 				p.type=PROPERTY_TYPE_BOOL;
 				p.helpText=TRANS("Ions to use for initiating RDF search");
-				p.key=KEY_ENABLE_SOURCE;
+				p.key=KEY_ENABLE_SOURCE_ALL;
 				propertyList.addProperty(p,curGroup);
 
 					
@@ -754,8 +951,7 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 					p.data=sTmp;
 					p.type=PROPERTY_TYPE_BOOL;
 					p.helpText=TRANS("Enable/disable ion as source");
-					//FIXME: This is a hack...
-					p.key=KEY_ENABLE_SOURCE*1000+ui;
+					p.key=muxKey(KEYTYPE_ENABLE_SOURCE,ui);
 					propertyList.addProperty(p,curGroup);
 				}
 				
@@ -770,7 +966,7 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 				p.data=sTmp;
 				p.type=PROPERTY_TYPE_BOOL;
 				p.helpText=TRANS("Enable/disable all ions as target");
-				p.key=KEY_ENABLE_TARGET;
+				p.key=KEY_ENABLE_TARGET_ALL;
 				propertyList.addProperty(p,curGroup);
 				
 				//Loop over the possible incoming ranges,
@@ -782,8 +978,7 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 					p.data=sTmp;
 					p.type=PROPERTY_TYPE_BOOL;
 					p.helpText=TRANS("Enable/disable this ion as target");
-					//FIXME: This is a hack...
-					p.key=KEY_ENABLE_TARGET*1000+ui;
+					p.key=muxKey(KEYTYPE_ENABLE_TARGET,ui);
 					propertyList.addProperty(p,curGroup);
 				}
 				propertyList.setGroupTitle(curGroup,TRANS("Target Ion"));
@@ -995,6 +1190,98 @@ void SpatialAnalysisFilter::getProperties(FilterPropGroup &propertyList) const
 			propertyList.setGroupTitle(curGroup,TRANS("Replacement"));
 			break;
 		}
+		case ALGORITHM_LOCAL_CONCENTRATION:
+		{
+			if(haveRangeParent)
+			{
+				ASSERT(ionSourceEnabled.size() == ionNames.size());
+				ASSERT(ionNames.size() == ionTargetEnabled.size());
+				curGroup++;
+
+				
+				string sTmp;
+
+				sTmp = boolStrEnc((size_t)std::count(ionSourceEnabled.begin(),
+					ionSourceEnabled.end(),true) == ionSourceEnabled.size());
+
+				p.name=TRANS("Source");
+				p.data=sTmp;
+				p.type=PROPERTY_TYPE_BOOL;
+				p.helpText=TRANS("Enable/disable all ions as source");
+				p.key=KEY_ENABLE_SOURCE_ALL;
+				propertyList.addProperty(p,curGroup);
+
+					
+				//Loop over the possible incoming ranges,
+				//once to set sources, once to set targets
+				for(unsigned int ui=0;ui<ionSourceEnabled.size();ui++)
+				{
+					sTmp=boolStrEnc(ionSourceEnabled[ui]);
+					p.name=ionNames[ui];
+					p.data=sTmp;
+					p.type=PROPERTY_TYPE_BOOL;
+					p.helpText=TRANS("Enable/disable ion as source");
+					p.key=muxKey(KEYTYPE_ENABLE_SOURCE,ui);
+					propertyList.addProperty(p,curGroup);
+				}
+				
+				propertyList.setGroupTitle(curGroup,TRANS("Source Ion"));
+				curGroup++;
+
+				sTmp = boolStrEnc((size_t)std::count(ionNumeratorEnabled.begin(),
+					ionNumeratorEnabled.end(),true) == ionNumeratorEnabled.size());
+				p.name=TRANS("Numerator");
+				p.data=sTmp;
+				p.type=PROPERTY_TYPE_BOOL;
+				p.helpText=TRANS("Ions to use as Numerator for conc. calculation");
+				p.key=KEY_ENABLE_NUMERATOR_ALL;
+				propertyList.addProperty(p,curGroup);
+
+					
+				//Loop over the possible incoming ranges,
+				//once to set sources, once to set targets
+				for(unsigned int ui=0;ui<ionNumeratorEnabled.size();ui++)
+				{
+					sTmp=boolStrEnc(ionNumeratorEnabled[ui]);
+					p.name=ionNames[ui];
+					p.data=sTmp;
+					p.type=PROPERTY_TYPE_BOOL;
+					p.helpText=TRANS("Enable/disable ion as source");
+					p.key=muxKey(KEYTYPE_ENABLE_NUMERATOR,ui);
+					propertyList.addProperty(p,curGroup);
+				}
+				
+				propertyList.setGroupTitle(curGroup,TRANS("Numerator"));
+				curGroup++;
+
+				
+				sTmp = boolStrEnc((size_t)std::count(ionTargetEnabled.begin(),
+					ionTargetEnabled.end(),true) == ionTargetEnabled.size());
+				
+				p.name=TRANS("Denominator");
+				p.data=sTmp;
+				p.type=PROPERTY_TYPE_BOOL;
+				p.helpText=TRANS("Enable/disable all ions as target");
+				p.key=KEY_ENABLE_TARGET_ALL;
+				propertyList.addProperty(p,curGroup);
+				
+				//Loop over the possible incoming ranges,
+				//once to set sources, once to set targets
+				for(unsigned int ui=0;ui<ionTargetEnabled.size();ui++)
+				{
+					sTmp=boolStrEnc(ionTargetEnabled[ui]);
+					p.name=ionNames[ui];
+					p.data=sTmp;
+					p.type=PROPERTY_TYPE_BOOL;
+					p.helpText=TRANS("Enable/disable this ion as target");
+					p.key=muxKey(KEYTYPE_ENABLE_TARGET,ui);
+					propertyList.addProperty(p,curGroup);
+				}
+				propertyList.setGroupTitle(curGroup,TRANS("Denominator")); 
+			}
+	
+			break;
+		}	
 		default:
 			ASSERT(false);
 	}
@@ -1025,7 +1312,13 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 			
 			if(ltmp>=ALGORITHM_ENUM_END)
 				return false;
-			
+		
+			if(ltmp == ALGORITHM_LOCAL_CONCENTRATION &&
+				nnMax < 2)
+			{
+				nnMax=2;
+			}
+	
 			algorithm=ltmp;
 			resetParamsAsNeeded();
 			needUpdate=true;
@@ -1041,6 +1334,7 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 				case ALGORITHM_DENSITY_FILTER:
 				case ALGORITHM_RDF:
 				case ALGORITHM_AXIAL_DF:
+				case ALGORITHM_LOCAL_CONCENTRATION:
 				{
 					size_t ltmp=STOP_MODE_ENUM_END;
 
@@ -1088,8 +1382,10 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 			unsigned int ltmp;
 			if(stream_cast(ltmp,value))
 				return false;
-			
-			if(ltmp==0)
+		
+			//NNmax should be nonzero at all times. For local concentration
+			// should be at least 2 (as 1 == 100% all the time)	
+			if(ltmp==0 || (algorithm == ALGORITHM_LOCAL_CONCENTRATION  && ltmp < 2))
 				return false;
 			
 			nnMax=ltmp;
@@ -1181,7 +1477,7 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 
 			break;
 		}
-		case KEY_ENABLE_SOURCE:
+		case KEY_ENABLE_SOURCE_ALL:
 		{
 			ASSERT(haveRangeParent);
 			bool allEnabled=true;
@@ -1203,7 +1499,7 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 			clearCache();
 			break;
 		}
-		case KEY_ENABLE_TARGET:
+		case KEY_ENABLE_TARGET_ALL:
 		{
 			ASSERT(haveRangeParent);
 			bool allEnabled=true;
@@ -1225,6 +1521,28 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 			clearCache();
 			break;
 		}
+		case KEY_ENABLE_NUMERATOR_ALL:
+		{
+			ASSERT(haveRangeParent);
+			bool allEnabled=true;
+			for(unsigned int ui=0;ui<ionNumeratorEnabled.size();ui++)
+			{
+				if(!ionNumeratorEnabled[ui])
+				{
+					allEnabled=false;
+					break;
+				}
+			}
+
+			//Invert the result and assign
+			allEnabled=!allEnabled;
+			for(unsigned int ui=0;ui<ionNumeratorEnabled.size();ui++)
+				ionNumeratorEnabled[ui]=allEnabled;
+
+			needUpdate=true;
+			clearCache();
+			break;
+		}
 		case KEY_CUTOFF:
 		{
 			string stripped=stripWhite(value);
@@ -1412,65 +1730,49 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 			//The incoming range keys are dynamically allocated to a 
 			//position beyond any reasonable key. Its a hack,
 			//but it works, and is entirely contained within the filter code.
-			if(key >=KEY_ENABLE_SOURCE*1000 &&
-				key < KEY_ENABLE_TARGET*1000)
-			{
-				size_t offset;
-				offset = key-KEY_ENABLE_SOURCE*1000;
-				
-				string stripped=stripWhite(value);
-
-				if(!(stripped == "1"|| stripped == "0"))
-					return false;
-				bool lastVal = ionSourceEnabled[offset]; 
-				
-
-				if(stripped=="1")
-					ionSourceEnabled[offset]=true;
-				else
-					ionSourceEnabled[offset]=false;
+			unsigned int ionOffset,keyType;
+			demuxKey(key,keyType,ionOffset);
 
-				//if the result is different, the
-				//cache should be invalidated
-				if(lastVal!=ionSourceEnabled[offset])
-				{
-					needUpdate=true;
-					clearCache();
-				}
+			bool doEnable;
+			if(!boolStrDec(value,doEnable))
+				return false;
 
+			vector<bool> *vBool=0;
 				
-
-			}	
-			else if ( key >=KEY_ENABLE_TARGET*1000)
+			switch(keyType)
 			{
-				size_t offset;
-				offset = key-KEY_ENABLE_TARGET*1000;
-				
-				string stripped=stripWhite(value);
-
-				if(!(stripped == "1"|| stripped == "0"))
-					return false;
-				bool lastVal = ionTargetEnabled[offset]; 
+				case KEYTYPE_ENABLE_SOURCE:
+					vBool=&ionSourceEnabled;
+					break;
+				case KEYTYPE_ENABLE_TARGET:
+					vBool=&ionTargetEnabled;
+					break;
+				case KEYTYPE_ENABLE_NUMERATOR:
+					vBool=&ionNumeratorEnabled;
+					break;
+				case KEYTYPE_ENABLE_DENOMINATOR:
+					vBool=&ionDenominatorEnabled;
+					break;
+				default:	
+					ASSERT(false);
+			}
 				
-
-				if(stripped=="1")
-					ionTargetEnabled[offset]=true;
+			if(vBool)
+			{
+				bool lastVal = (*vBool)[ionOffset]; 
+				if(doEnable)
+					(*vBool)[ionOffset]=true;
 				else
-					ionTargetEnabled[offset]=false;
-
+					(*vBool)[ionOffset]=false;
+				
 				//if the result is different, the
 				//cache should be invalidated
-				if(lastVal!=ionTargetEnabled[offset])
+				if(lastVal!=(*vBool)[ionOffset])
 				{
 					needUpdate=true;
 					clearCache();
 				}
-			}	
-			else
-			{
-				ASSERT(false);
 			}
-
 		}
 
 	}	
@@ -1480,12 +1782,12 @@ bool SpatialAnalysisFilter::setProperty(  unsigned int key,
 std::string  SpatialAnalysisFilter::getSpecificErrString(unsigned int code) const
 {
 	const char *errStrings[] = {"",
-				"Spatial analysis aborted by user",
-				"Insufficient memory to complete analysis",
-				"Insufficient bins in histogram for analysis",
-				"Insufficient memory for binomial. Reduce input size?",
-				"Binomial requires a parent range file",
-				"File read failed",
+				TRANS("Spatial analysis aborted by user"),
+				TRANS("Insufficient memory to complete analysis"),
+				TRANS("Required range data not present"), 
+				TRANS("Insufficient memory for binomial. Reduce input size?"),
+				TRANS("Insufficient points to continue"),
+				TRANS("Unable to load file")
 				};
 	COMPILE_ASSERT(THREEDEP_ARRAYSIZE(errStrings) == SPAT_ERR_END_OF_ENUM);
 	
@@ -1498,7 +1800,7 @@ std::string  SpatialAnalysisFilter::getSpecificErrString(unsigned int code) cons
 void SpatialAnalysisFilter::setUserString(const std::string &str)
 {
 	//Which algorithms have plot outputs?
-	const bool ALGORITHM_HAS_PLOTS[] = { false,false,true,true,true,false};
+	const bool ALGORITHM_HAS_PLOTS[] = { false,false,true,true,true,false,false};
 
 	COMPILE_ASSERT(THREEDEP_ARRAYSIZE(ALGORITHM_HAS_PLOTS) == ALGORITHM_ENUM_END);
 
@@ -1565,7 +1867,7 @@ bool SpatialAnalysisFilter::writeState(std::ostream &f,unsigned int format, unsi
 			f << tabs(depth+1) << "<densitycutoff value=\""<<densityCutoff<< "\"/>"  << endl;
 			f << tabs(depth+1) << "<keepdensityupper value=\""<<(int)keepDensityUpper<< "\"/>"  << endl;
 			
-			f << tabs(depth+1) << "<replace file=\""<<replaceFile << "\" mode=\"" << replaceMode 
+			f << tabs(depth+1) << "<replace file=\""<<escapeXML(convertFileStringToCanonical(replaceFile)) << "\" mode=\"" << replaceMode 
 				<< "\" tolerance=\"" << replaceTolerance <<  "\" replacemass=\"" << boolStrEnc(replaceMass) << "\" />"  << endl;
 
 
@@ -1584,9 +1886,14 @@ bool SpatialAnalysisFilter::writeState(std::ostream &f,unsigned int format, unsi
 			
 			writeVectorsXML(f,"vectorparams",vectorParams,depth+1);
 			writeScalarsXML(f,"scalarparams",scalarParams,depth+1);
-			
-			writeIonsEnabledXML(f,"source",ionSourceEnabled,ionNames,depth+1);
-			writeIonsEnabledXML(f,"target",ionTargetEnabled,ionNames,depth+1);
+		
+			if(ionNames.size())	
+			{
+				writeIonsEnabledXML(f,"source",ionSourceEnabled,ionNames,depth+1);
+				writeIonsEnabledXML(f,"target",ionTargetEnabled,ionNames,depth+1);
+				writeIonsEnabledXML(f,"numerator",ionNumeratorEnabled,ionNames,depth+1);
+				writeIonsEnabledXML(f,"denominator",ionDenominatorEnabled,ionNames,depth+1);
+			}
 
 			f << tabs(depth) << "</" << trueName() << ">" << endl;
 			break;
@@ -1599,6 +1906,34 @@ bool SpatialAnalysisFilter::writeState(std::ostream &f,unsigned int format, unsi
 	return true;
 }
 
+
+void SpatialAnalysisFilter::getStateOverrides(std::vector<string> &externalAttribs) const 
+{
+	externalAttribs.push_back(replaceFile);
+
+}
+
+bool SpatialAnalysisFilter::writePackageState(std::ostream &f, unsigned int format,
+			const std::vector<std::string> &valueOverrides, unsigned int depth) const
+{
+	ASSERT(valueOverrides.size() == 1);
+
+	//Temporarily modify the state of the filter, then call writestate
+	string tmpReplaceFile=replaceFile;
+
+
+	//override const and self-modify
+	// this is quite naughty, but we know what we are doing...
+	const_cast<SpatialAnalysisFilter *>(this)->replaceFile=valueOverrides[0];
+	bool result;
+	result=writeState(f,format,depth);
+
+	//restore the filter state, such that the caller doesn't notice that this has been modified
+	const_cast<SpatialAnalysisFilter *>(this)->replaceFile=tmpReplaceFile;
+
+	return result;
+}
+
 bool SpatialAnalysisFilter::readState(xmlNodePtr &nodePtr, const std::string &stateFileDir)
 {
 	using std::string;
@@ -1817,6 +2152,26 @@ bool SpatialAnalysisFilter::readState(xmlNodePtr &nodePtr, const std::string &st
 
 	if(!XMLHelpFwdToElem(nodePtr,"vectorparams"))
 		readVectorsXML(nodePtr,vectorParams);
+	else
+		nodePtr=tmpNode;
+
+	//FIXME: Remap the ion names  we load from the file to the ion names that we 
+	// see in the rangefile
+
+	vector<string> ionNames;
+	if(!XMLHelpFwdToElem(nodePtr,"source"))
+		readIonsEnabledXML(nodePtr,ionSourceEnabled,ionNames);
+	nodePtr=tmpNode;
+	if(!XMLHelpFwdToElem(nodePtr,"target"))
+		readIonsEnabledXML(nodePtr,ionTargetEnabled,ionNames);
+
+	nodePtr=tmpNode;
+	if(!XMLHelpFwdToElem(nodePtr,"numerator"))
+		readIonsEnabledXML(nodePtr,ionNumeratorEnabled,ionNames);
+	
+	nodePtr=tmpNode;
+	if(!XMLHelpFwdToElem(nodePtr,"denominator"))
+		readIonsEnabledXML(nodePtr,ionDenominatorEnabled,ionNames);
 
 	resetParamsAsNeeded();
 	
@@ -1882,134 +2237,17 @@ void SpatialAnalysisFilter::resetParamsAsNeeded()
 		;
 	}
 }
-//Scan input datastreams to build two point vectors,
-// one of those with points specified as "target" 
-// which is a copy of the input points
-//Returns 0 on no error, otherwise nonzero
-size_t SpatialAnalysisFilter::buildSplitPoints(const vector<const FilterStreamData *> &dataIn,
-				ProgressData &progress, size_t totalDataSize,
-				const RangeFile *rngF,
-				vector<Point3D> &pSource, vector<Point3D> &pTarget
-				) const
-{
-	size_t sizeNeeded[2];
-	sizeNeeded[0]=sizeNeeded[1]=0;
-
-	//Presize arrays
-	for(unsigned int ui=0; ui<dataIn.size() ; ui++)
-	{
-		switch(dataIn[ui]->getStreamType())
-		{
-			case STREAM_TYPE_IONS:
-			{
-				unsigned int ionID;
-
-				const IonStreamData *d;
-				d=((const IonStreamData *)dataIn[ui]);
-				ionID=getIonstreamIonID(d,rngF);
-
-				if(ionID == (unsigned int)-1)
-				{
-					//FIXME: Fallback handling  to re-range data
-					// - this can technically fail for inputs that are
-					// not homogeneously ranged!
-					break;
-				}
-
-				if(ionSourceEnabled[ionID])
-					sizeNeeded[0]+=d->data.size();
-
-				if(ionTargetEnabled[ionID])
-					sizeNeeded[1]+=d->data.size();
-
-				break;
-			}
-			default:
-				break;
-		}
-	}
-
-	pSource.resize(sizeNeeded[0]);
-	pTarget.resize(sizeNeeded[1]);
-
-	//Fill arrays
-	size_t curPos[2];
-	curPos[0]=curPos[1]=0;
-
-	for(unsigned int ui=0; ui<dataIn.size() ; ui++)
-	{
-		switch(dataIn[ui]->getStreamType())
-		{
-			case STREAM_TYPE_IONS:
-			{
-				unsigned int ionID;
-				const IonStreamData *d;
-				d=((const IonStreamData *)dataIn[ui]);
-				ionID=getIonstreamIonID(d,rngF);
-
-				if(ionID==(unsigned int)(-1))
-					break;
-
-				if(ionSourceEnabled[ionID])
-				{
-					if(extendPointVector(pSource,d->data,
-					                     progress.filterProgress,curPos[0]))
-						return ERR_ABORT_FAIL;
-
-					curPos[0]+=d->data.size();
-				}
-
-				if(ionTargetEnabled[ionID])
-				{
-					if(extendPointVector(pTarget,d->data,
-					                     progress.filterProgress,curPos[1]))
-						return ERR_ABORT_FAIL;
-
-					curPos[1]+=d->data.size();
-				}
-
-				break;
-			}
-			default:
-				break;
-		}
-	}
-
-
-	return 0;
-}
 
 void SpatialAnalysisFilter::filterSelectedRanges(const vector<IonHit> &ions, bool sourceFilter, const RangeFile *rngF,
 			vector<IonHit> &output) const
 {
-	ASSERT(rngF);
-
 	if(sourceFilter)
-	{
-		for(size_t ui=0;ui<ions.size();ui++)
-		{
-			unsigned int id;
-			id=rngF->getIonID(ions[ui].getMassToCharge());
-			if(id == (unsigned int )-1)
-				continue;
-			if(ionSourceEnabled[id])
-				output.push_back(ions[ui]);
-		}
-	}
+		rngF->rangeByIon(ions,ionSourceEnabled,output);
 	else
-	{
-		for(size_t ui=0;ui<ions.size();ui++)
-		{
-			unsigned int id;
-			id=rngF->getIonID(ions[ui].getMassToCharge());
-			if(id == (unsigned int)-1)
-				continue;
-			if(ionTargetEnabled[id])
-				output.push_back(ions[ui]);
-		}
-	}
+		rngF->rangeByIon(ions,ionTargetEnabled,output);
 }
 
+//FIXME: Move to filter common
 //Scan input datastreams to build a single point vector,
 // which is a copy of the input points
 //Returns 0 on no error, otherwise nonzero
@@ -2036,7 +2274,7 @@ size_t buildMonolithicPoints(const vector<const FilterStreamData *> &dataIn,
 				const IonStreamData *d;
 				d=((const IonStreamData *)dataIn[ui]);
 
-				if(extendPointVector(p,d->data,	progress.filterProgress,
+				if(extendDataVector(p,d->data,	progress.filterProgress,
 						dataSize))
 					return ERR_ABORT_FAIL;
 
@@ -2085,7 +2323,7 @@ size_t SpatialAnalysisFilter::algorithmRDF(ProgressData &progress, size_t totalD
 		ASSERT(ionNames.size());
 		size_t errCode;
 		if((errCode=buildSplitPoints(dataIn,progress,totalDataSize,
-				rngF,pts[0],pts[1])))
+				rngF,ionSourceEnabled, ionTargetEnabled,pts[0],pts[1])))
 			return errCode;
 
 		progress.step=2;
@@ -2619,6 +2857,7 @@ size_t SpatialAnalysisFilter::algorithmDensity(ProgressData &progress,
 						deadDistSqr=0;
 
 						//Assign the mass to charge using nn density estimates
+						//TODO: Use multi-neareast search algorithm?
 						do
 						{
 							res=kdTree.findNearest(r,treeDomain,deadDistSqr);
@@ -2710,7 +2949,6 @@ size_t SpatialAnalysisFilter::algorithmDensity(ProgressData &progress,
 					newD->b=d->b;
 					newD->a=d->a;
 					newD->ionSize=d->ionSize;
-					newD->representationType=d->representationType;
 					newD->valueType=TRANS("Number Density (\\#/Vol^3)");
 
 					//Cache result as neede
@@ -2728,6 +2966,9 @@ size_t SpatialAnalysisFilter::algorithmDensity(ProgressData &progress,
 				break;
 		}
 	}
+
+	progress.filterProgress=100;
+
 	//If we have bad points, let the user know.
 	if(!badPts.empty())
 	{
@@ -3007,7 +3248,6 @@ size_t SpatialAnalysisFilter::algorithmDensityFilter(ProgressData &progress,
 					newD->b=d->b;
 					newD->a=d->a;
 					newD->ionSize=d->ionSize;
-					newD->representationType=d->representationType;
 					newD->valueType=TRANS("Number Density (\\#/Vol^3)");
 
 					//Cache result as needed
@@ -3692,6 +3932,394 @@ size_t SpatialAnalysisFilter::algorithmBinomial(ProgressData &progress,
 	return 0;
 }
 
+
+size_t SpatialAnalysisFilter::algorithmLocalConcentration(ProgressData &progress, 
+		size_t totalDataSize, const vector<const FilterStreamData *>  &dataIn, 
+		vector<const FilterStreamData * > &getOut,const RangeFile *rngF)
+{
+
+
+	vector<IonHit> pSource;
+
+#ifdef _OPENMP
+	bool spin=false;	
+#endif
+	if(stopMode == STOP_MODE_RADIUS)
+	{
+		vector<Point3D> numeratorPts,denominatorPts;
+
+		progress.step=1;
+		progress.stepName=TRANS("Collate");
+		progress.filterProgress=0;
+		progress.maxStep=4;
+
+		//Build the numerator and denominator points
+		unsigned int errCode;
+		errCode = buildSplitPoints(dataIn, progress, totalDataSize, rngF, 
+				ionNumeratorEnabled,ionDenominatorEnabled,numeratorPts,denominatorPts);
+		if(errCode)
+			return errCode;	
+
+		if(*Filter::wantAbort)
+			return ERR_ABORT_FAIL;
+		progress.step=2;
+		progress.stepName = TRANS("Build Numerator");
+		progress.filterProgress=0;
+
+
+		//Build the tree (its roughly nlogn timing, but worst case n^2)
+		K3DTreeMk2 treeNumerator,treeDenominator;
+		treeNumerator.resetPts(numeratorPts);
+		if(*Filter::wantAbort)
+			return ERR_ABORT_FAIL;
+		treeNumerator.build();
+		if(*Filter::wantAbort)
+			return ERR_ABORT_FAIL;
+
+		progress.step=3;
+		progress.stepName = TRANS("Build Denominator");
+		progress.filterProgress=0;
+
+		treeDenominator.resetPts(denominatorPts);
+		treeDenominator.build();
+		if(*Filter::wantAbort)
+			return ERR_ABORT_FAIL;
+
+		unsigned int sizeNeeded=0;
+		//Count the array size that we need to store the points 
+		for(unsigned int ui=0; ui<dataIn.size() ; ui++)
+		{
+			switch(dataIn[ui]->getStreamType())
+			{
+				case STREAM_TYPE_IONS:
+				{
+					const IonStreamData *d;
+					d=((const IonStreamData *)dataIn[ui]);
+					unsigned int ionID;
+					ionID=getIonstreamIonID(d,rngF);
+
+					//Check to see if we have a grouped set of ions
+					if(ionID == (unsigned int)-1)
+					{
+						//we have ungrouped ions, so work out size individually
+						for(unsigned int uj=0;uj<d->data.size();uj++)
+						{
+							ionID = rngF->getIonID(d->data[uj].getMassToCharge());
+							if(ionID != (unsigned int)-1 && ionSourceEnabled[ionID])
+								sizeNeeded++;
+						}
+						break;
+					}
+					
+					if(ionSourceEnabled[ionID])
+						sizeNeeded+=d->data.size();
+				}
+			}
+
+		}
+
+		pSource.resize(sizeNeeded);
+		
+
+		//Build the array of output points
+		//--
+		size_t curOffset=0;	
+		for(unsigned int ui=0; ui<dataIn.size() ; ui++)
+		{
+			switch(dataIn[ui]->getStreamType())
+			{
+				case STREAM_TYPE_IONS:
+				{
+					unsigned int ionID;
+					const IonStreamData *d;
+					d=((const IonStreamData *)dataIn[ui]);
+					ionID=getIonstreamIonID(d,rngF);
+
+					if(ionID==(unsigned int)(-1))
+					{
+						//we have ungrouped ions, so work out size individually
+						for(unsigned int uj=0;uj<d->data.size();uj++)
+						{
+							ionID = rngF->getIonID(d->data[uj].getMassToCharge());
+							if(ionID != (unsigned int)-1 && ionSourceEnabled[ionID])
+							{
+								pSource[curOffset] = d->data[uj];
+								curOffset++;
+							}
+						}
+						break;
+					}
+
+					if(ionSourceEnabled[ionID])
+					{
+						std::copy(d->data.begin(),d->data.end(),pSource.begin()+curOffset);
+						curOffset+=d->data.size();
+					}
+
+					break;
+				}
+				default:
+					break;
+			}
+
+			if(*Filter::wantAbort)
+				return false;
+		}
+
+		ASSERT(curOffset == pSource.size());
+		//--
+
+		progress.step=4;
+		progress.stepName = TRANS("Compute");
+		progress.filterProgress=0;
+
+		//Loop through the array, and perform local search on each tree
+#pragma omp parallel for schedule(dynamic)
+		for(unsigned int ui=0;ui<pSource.size(); ui++)
+		{
+#ifdef _OPENMP
+			if(spin)
+				continue;
+#endif
+
+			vector<size_t> ptsNum,ptsDenom;
+			//Find the points that are within the search radius
+			treeNumerator.ptsInSphere(pSource[ui].getPosRef(),distMax,ptsNum);
+			treeDenominator.ptsInSphere(pSource[ui].getPosRef(),distMax,ptsDenom);
+
+			//Check to see if there is any self-matching going on. Don't allow zero-distance matches
+			// as this biases the composition towards the chosen source points
+			//TODO: Is there a faster way to do this? We might be able to track the original index of the point
+			// that we built, and map it back to the input?
+			//--
+			unsigned int nCount,dCount;
+			nCount=0;
+			for(unsigned int uj=0;uj<ptsNum.size(); uj++)
+			{
+				size_t ptIdx;
+				ptIdx=ptsNum[uj];
+				float dist;
+				dist = treeNumerator.getPtRef(ptIdx).sqrDist(pSource[ui].getPosRef());
+				if(dist > DISTANCE_EPSILON)
+					nCount++;
+			}
+
+			dCount=0;
+			for(unsigned int uj=0;uj<ptsDenom.size(); uj++)
+			{
+				size_t ptIdx;
+				ptIdx=ptsDenom[uj];
+				float dist;
+				dist = treeDenominator.getPtRef(ptIdx).sqrDist(pSource[ui].getPosRef());
+				if(dist> DISTANCE_EPSILON)
+					dCount++;
+			}
+			//--
+			
+			//compute concentration
+			if( nCount + dCount )
+				pSource[ui].setMassToCharge((float)nCount/(float)(nCount + dCount)*100.0f);
+			else
+				pSource[ui].setMassToCharge(-1.0f);
+			
+
+#ifdef _OPENMP 
+			#pragma omp critical
+			if(!omp_get_thread_num())
+			{
+#endif
+				//let master thread do update	
+				progress.filterProgress= (unsigned int)((float)ui/(float)pSource.size()*100.0f);
+
+				if(*Filter::wantAbort)
+				{
+#ifndef _OPENMP
+					return ERR_ABORT_FAIL;
+#else
+					#pragma atomic
+					spin=true;
+#endif			
+				}
+#ifdef _OPENMP
+			}
+#endif
+
+			
+		}
+	}
+	else if(stopMode == STOP_MODE_NEIGHBOUR)
+	{
+
+		//Merge the numerator and denominator ions into a single search tree
+		vector<bool> enabledSearchIons;
+		enabledSearchIons.resize(rngF->getNumIons());
+		
+		for(unsigned int ui=0;ui<enabledSearchIons.size(); ui++)	
+		{
+			enabledSearchIons[ui] = (ionNumeratorEnabled[ui] 
+						|| ionDenominatorEnabled[ui]); 
+		}	
+
+		
+		progress.step=1;
+		progress.stepName=TRANS("Collate");
+		progress.filterProgress=0;
+		progress.maxStep=3;
+	
+		vector<IonHit> pTarget;
+
+		//FIXME: This is highly memory inefficient - 
+		//	we build points, then throw them awaway.
+		// We should build and range at the same time
+		buildSplitPoints(dataIn,progress,totalDataSize,rngF,
+					ionSourceEnabled,enabledSearchIons,
+						pSource, pTarget);
+		if(*Filter::wantAbort)
+			return ERR_ABORT_FAIL;
+
+		if(pTarget.size() < nnMax)
+			return INSUFFICIENT_SIZE_ERR;
+
+		progress.step=2;
+		progress.stepName=TRANS("Build");
+		progress.filterProgress=0;
+
+		//Keep a copy of the mass to charge data
+		vector<float> dataMasses;
+		dataMasses.resize(pTarget.size());
+		#pragma omp parallel for
+		for(unsigned int ui=0;ui<pTarget.size();ui++)
+			dataMasses[ui]=pTarget[ui].getMassToCharge();
+
+		K3DTreeMk2 searchTree;
+		searchTree.resetPts(pTarget);
+		searchTree.build();
+		if(*Filter::wantAbort)
+			return ERR_ABORT_FAIL;
+
+		progress.step=3;
+		progress.stepName=TRANS("Compute");
+		progress.filterProgress=0;
+
+
+		//Loop through the array, and perform local search on each tree
+		BoundCube bc;
+		searchTree.getBoundCube(bc);
+
+#pragma omp parallel for schedule(dynamic) 
+		for(unsigned int ui=0;ui<pSource.size(); ui++)
+		{
+#ifdef _OPENMP
+			//If user requests abort, then do not process any more
+			if(spin)
+				continue;
+#endif
+			set<size_t> ptsFound;
+
+			//Points from the tree we have already found. Abort if we cannot find enough NNs to satisfy search
+			while(ptsFound.size()<nnMax)
+			{
+				size_t ptIdx;
+				ptIdx=searchTree.findNearestWithSkip(pSource[ui].getPosRef(),bc,ptsFound);
+
+				//Check that we have a valid NN
+				if(ptIdx == (size_t)-1)
+				{
+					ptsFound.clear();
+					break;
+				}
+
+				//distance between search pt and found pt
+				float sqrDistance;
+				sqrDistance = searchTree.getPtRef(ptIdx).sqrDist(pSource[ui].getPosRef());
+
+				if(sqrDistance > DISTANCE_EPSILON)
+					ptsFound.insert(ptIdx);
+			}
+
+
+			unsigned int nCount;
+			unsigned int dCount;
+			nCount=dCount=0;	
+			//Count the number of numerator and denominator ions, using the masses we set aside earlier
+			for(set<size_t>::iterator it=ptsFound.begin(); it!=ptsFound.end(); ++it)
+			{
+				float ionMass;
+				//check that the distance is non-zero, to force no self-matching
+				ionMass = dataMasses[searchTree.getOrigIndex(*it)];
+
+				unsigned int ionID;
+				ionID = rngF->getIonID(ionMass);
+
+
+				//Ion can be either numerator or denominator OR BOTH.
+				if(ionNumeratorEnabled[ionID])
+					nCount++;
+				if(ionDenominatorEnabled[ionID])
+					dCount++;
+			}
+
+			//compute concentration
+			pSource[ui].setMassToCharge((float)nCount/(float)(nCount + dCount)*100.0f);
+
+#ifdef _OPENMP 
+			if(!omp_get_thread_num())
+			{
+#endif
+				//let master thread do update	
+				progress.filterProgress= (unsigned int)((float)ui/(float)pSource.size()*100.0f);
+				if(*Filter::wantAbort)
+				{
+#ifndef _OPENMP
+					return ERR_ABORT_FAIL;
+#else
+					#pragma atomic
+					spin=true;
+#endif			
+				}
+
+#ifdef _OPENMP
+			}
+#endif
+
+			
+		}
+	
+	}
+	else
+	{
+		//Should not get here...
+		ASSERT(false);
+		return ERR_ABORT_FAIL;
+	}
+
+
+#ifdef _OPENMP
+	if(spin)
+	{
+		ASSERT(*Filter::wantAbort);
+		return ERR_ABORT_FAIL;
+	}
+#endif
+	progress.filterProgress=100;
+
+	if(pSource.size())
+	{
+		IonStreamData *outData = new IonStreamData(this);
+		//make a guess as to desired size/colour
+		outData->estimateIonParameters(dataIn);
+		//override colour to grey
+		outData->g = outData->b = outData->r = 0.5;
+		outData->valueType = "Relative Conc. (%)";
+		outData->data.swap(pSource);
+		cacheAsNeeded(outData);
+
+		getOut.push_back(outData);
+	}
+
+	return 0;
+}
+
 #ifdef DEBUG
 
 bool densityPairTest();
@@ -3699,6 +4327,8 @@ bool nnHistogramTest();
 bool rdfPlotTest();
 bool axialDistTest();
 bool replaceTest();
+bool localConcTestRadius();
+bool localConcTestNN();
 
 bool SpatialAnalysisFilter::runUnitTests()
 {
@@ -3715,6 +4345,11 @@ bool SpatialAnalysisFilter::runUnitTests()
 		return false;
 	if(!replaceTest())
 		return false;
+	if(!localConcTestRadius())
+		return false;
+
+	if(!localConcTestNN())
+		return false;
 	return true;
 }
 
@@ -4043,5 +4678,211 @@ bool replaceTest()
 	return true;
 }
 
+
+//--- Local concentration tests --
+const IonStreamData *createLCIonStream()
+{
+	IonStreamData*d = new IonStreamData;
+	IonHit h;
+
+	//create some points, of differing mass-to-charge 
+
+	//1 "A" ion, mass 1
+	//1 "B" ion, mass 2
+	//2 "C" ions,mass 3
+	h.setPos(Point3D(0,0,0));
+	h.setMassToCharge(1);
+	d->data.push_back(h);
+
+	h.setPos(Point3D(0.49,0.0,0.0));
+	h.setMassToCharge(2);
+	d->data.push_back(h);
+
+	h.setPos(Point3D(0.0,0.5,0.0));
+	h.setMassToCharge(3);
+	d->data.push_back(h);
+	
+	h.setPos(Point3D(0.0,0.0,0.51));
+	h.setMassToCharge(3);
+	d->data.push_back(h);
+	
+	return d;
+}
+
+RangeStreamData *createLCRangeStream()
+{
+	//Create a fake rangefile
+	RangeStreamData *r= new RangeStreamData;
+	RangeFile *rng = new RangeFile;
+
+	RGBf colour;
+	colour.red=colour.blue=colour.green=0.5;
+	unsigned int iid[3], rid[3]; 
+	iid[0] = rng->addIon("A","A",colour);
+	iid[1] = rng->addIon("B","B",colour);
+	iid[2] = rng->addIon("C","C",colour);
+
+	rid[0]=rng->addRange(0.5,1.5,iid[0]);
+	rid[1]=rng->addRange(1.51,2.5,iid[1]);
+	rid[2]=rng->addRange(2.51,3.5,iid[2]);
+
+	r->rangeFile=rng;
+	r->enabledRanges.resize(3,1);
+	r->enabledIons.resize(3,1);
+	return r;
+}
+
+SpatialAnalysisFilter *createLCTestSpatialFilter(const vector<const FilterStreamData *>  &in)
+{
+	//Create a spatial analysis filter
+	SpatialAnalysisFilter *f=new SpatialAnalysisFilter;
+	f->setCaching(false);
+	//inform it about the rangefile	
+	vector< const FilterStreamData *> out;
+	f->initFilter(in,out);
+	//Set Filter to perform local concentration analysis 
+	// - dist termination,
+	//---
+	bool needUp;
+	string s;
+	s=TRANS(SPATIAL_ALGORITHMS[ALGORITHM_LOCAL_CONCENTRATION]);
+	if(!(f->setProperty(KEY_ALGORITHM,s,needUp)) )
+	{
+		cerr << "Failed Set prop (algorithm)";
+		return 0;
+	}
+	
+	
+	//Set enable/disable status (one for each)
+	// A ions - source. B ions - numerator, C ions - denominator
+	for(unsigned int ui=0; ui<3; ui++)
+	{
+		if(ui!=0)
+		{
+			if(!(f->setProperty(Filter::muxKey(KEYTYPE_ENABLE_SOURCE,ui),"0",needUp)) )
+				return 0;
+		}
+		if(ui!=1)
+		{
+			if(!(f->setProperty(Filter::muxKey(KEYTYPE_ENABLE_NUMERATOR,ui),"0",needUp)) )
+				return 0;
+		}
+		if(ui!=2)
+		{
+			if(!(f->setProperty(Filter::muxKey(KEYTYPE_ENABLE_DENOMINATOR,ui),"0",needUp)))
+				return 0;
+		}
+	}
+	//---
+
+	return f;
+}
+
+bool localConcTestRadius()
+{
+	//Build some points to pass to the filter
+	vector<const FilterStreamData*> streamIn,streamOut;
+	
+	//Create some input data
+	//--
+	RangeStreamData *rngStream=createLCRangeStream();
+	streamIn.push_back(rngStream);
+	streamIn.push_back(createLCIonStream());
+
+	//--
+	
+	SpatialAnalysisFilter *f=createLCTestSpatialFilter(streamIn);
+	f->initFilter(streamIn,streamOut);
+
+	bool needUp;	
+	string s;
+	s=TRANS(STOP_MODES[STOP_MODE_RADIUS]);
+	TEST(f->setProperty(KEY_STOPMODE,s,needUp),"Failed Set prop (stop mode)");
+	s="1.0";
+	TEST(f->setProperty(KEY_DISTMAX,s,needUp),"Failed Set prop (maxDist)");
+	
+	//Do the refresh
+	ProgressData p;
+	TEST(!f->refresh(streamIn,streamOut,p),"Checking refresh code");
+	delete f;
+
+	//FIXME: Check the data coming out
+	TEST(streamOut.size() == 1,"stream size");
+	TEST(streamOut[0]->getStreamType() == STREAM_TYPE_IONS,"stream type");
+	TEST(streamOut[0]->getNumBasicObjects() == 1,"output ion count");
+
+	IonStreamData *ionD = (IonStreamData *)streamOut[0];
+
+	float localConc = ionD->data[0].getMassToCharge(); 
+	TEST(EQ_TOL(localConc,1.0/3.0*100.0),"Local Concentration check");
+
+	delete rngStream->rangeFile;
+
+	for(unsigned int ui=0;ui<streamIn.size(); ui++)
+		delete streamIn[ui];
+	streamIn.clear();
+
+	//kill the output ion stream
+	for(unsigned int ui=0;ui<streamOut.size(); ui++)
+		delete streamOut[ui];
+	streamOut.clear();
+
+	return true;
+}
+
+bool localConcTestNN()
+{
+	//Build some points to pass to the filter
+	vector<const FilterStreamData*> streamIn,streamOut;
+	
+	//Create some input data
+	//--
+
+	RangeStreamData *rngStream=createLCRangeStream();
+	streamIn.push_back(rngStream);
+	streamIn.push_back(createLCIonStream());
+
+	//--
+	
+	SpatialAnalysisFilter *f=createLCTestSpatialFilter(streamIn);
+	f->initFilter(streamIn,streamOut);
+	
+	bool needUp;	
+	string s;
+	s=TRANS(STOP_MODES[STOP_MODE_NEIGHBOUR]);
+	TEST(f->setProperty(KEY_STOPMODE,s,needUp),"Failed Set prop (stop mode)");
+	s="3";
+	TEST(f->setProperty(KEY_NNMAX,s,needUp),"Failed Set prop (nnMax)");
+	
+	//Do the refresh
+	ProgressData p;
+	TEST(!f->refresh(streamIn,streamOut,p),"Checking refresh code");
+	delete f;
+
+	//FIXME: Check the data coming out
+	TEST(streamOut.size() == 1,"stream size");
+	TEST(streamOut[0]->getStreamType() == STREAM_TYPE_IONS,"stream type");
+	TEST(streamOut[0]->getNumBasicObjects() == 1,"output ion count");
+
+	IonStreamData *ionD = (IonStreamData *)streamOut[0];
+
+	float localConc = ionD->data[0].getMassToCharge(); 
+	TEST(EQ_TOL(localConc,1.0/3.0*100.0),"Local Concentration check");
+
+
+	delete rngStream->rangeFile;
+	for(unsigned int ui=0;ui<streamIn.size(); ui++)
+		delete streamIn[ui];
+	streamIn.clear();
+
+	//kill the output ion stream
+	for(unsigned int ui=0;ui<streamOut.size(); ui++)
+		delete streamOut[ui];
+	streamOut.clear();
+
+	return true;
+}
+//--------------------------------
+
 #endif
 
diff --git a/src/backend/filters/spatialAnalysis.h b/src/backend/filters/spatialAnalysis.h
index 6963560..67f85af 100644
--- a/src/backend/filters/spatialAnalysis.h
+++ b/src/backend/filters/spatialAnalysis.h
@@ -46,6 +46,9 @@ class SpatialAnalysisFilter : public Filter
 		//!Are the sources/targets enabled for a  particular incoming range?
 		std::vector<bool> ionSourceEnabled,ionTargetEnabled;
 
+		//!work out which ions to count in the numerator vs denominator
+		std::vector<bool> ionNumeratorEnabled,ionDenominatorEnabled;
+
 		//RDF specific params
 		//--------
 		//RDF bin count
@@ -156,6 +159,12 @@ class SpatialAnalysisFilter : public Filter
 			const std::vector<const FilterStreamData *>  &dataIn, 
 			std::vector<const FilterStreamData * > &getOut);
 
+		//Local concentration algorithm, as described by 10.1016/j.jnucmat.2014.03.034
+		// TODO: Better reference?
+		// - I think implementations pre-date this paper, as I know of this algorithm from much earlier than 2014
+		size_t algorithmLocalConcentration(ProgressData &progress, size_t totalDataSize, 
+			const std::vector<const FilterStreamData *>  &dataIn, 
+			std::vector<const FilterStreamData * > &getOut, const RangeFile *rngF);
 		//Create a 3D manipulable cylinder as an output drawable
 		// using the parameters stored inside the vector/scalar params
 		// both parameters are outputs from this function
@@ -167,15 +176,6 @@ class SpatialAnalysisFilter : public Filter
 		// and if needed, output object will be generated 
 		void createDevice(std::vector<const FilterStreamData *> &getOut);
 
-		//Scan input datstreams to build a two point vectors,
-		// one of those with points specified as "target" 
-		// which is a copy of the input points
-		//Returns 0 on no error, otherwise nonzero
-		size_t buildSplitPoints(const std::vector<const FilterStreamData *> &dataIn,
-					ProgressData &progress, size_t totalDataSize,
-					const RangeFile *rngF,
-					std::vector<Point3D> &pSource, std::vector<Point3D> &pTarget) const;
-
 
 		//From the given input ions, filter them down using the user
 		// selection for ranges. If sourceFilter is true, filter by user
@@ -213,6 +213,13 @@ class SpatialAnalysisFilter : public Filter
 		//!Dump state to output stream, using specified format
 		bool writeState(std::ostream &f,unsigned int format,
 						unsigned int depth=0) const;
+		
+		//!write an overridden filename version of the state
+		virtual bool writePackageState(std::ostream &f, unsigned int format,
+				const std::vector<std::string> &valueOverrides,unsigned int depth=0) const;
+		//Obtain the state file override 
+		void getStateOverrides(std::vector<string> &externalAttribs) const; 
+
 		//!Read the state of the filter from XML file. If this
 		//fails, filter will be in an undefined state.
 		bool readState(xmlNodePtr &node, const std::string &packDir);
diff --git a/src/backend/filters/spectrumPlot.cpp b/src/backend/filters/spectrumPlot.cpp
index 7e4c8a9..b24a2ed 100644
--- a/src/backend/filters/spectrumPlot.cpp
+++ b/src/backend/filters/spectrumPlot.cpp
@@ -435,6 +435,10 @@ unsigned int SpectrumPlotFilter::refresh(const std::vector<const FilterStreamDat
 		{
 			if (!showOnlyCorrected)
 			{
+				vector<float> backgroundHist;
+				createMassBackground(backParams.massStart,backParams.massEnd,
+					nBins,backParams.intensity,backgroundHist);
+
 				//Create a new plot which shows the spectrum's background
 				PlotStreamData *plotBack = new PlotStreamData;
 				plotBack->parent = this;
@@ -444,14 +448,18 @@ unsigned int SpectrumPlotFilter::refresh(const std::vector<const FilterStreamDat
 				plotBack->index=d->index+1;	
 				plotBack->yLabel=d->yLabel;
 				plotBack->xyData.reserve(d->xyData.size());
+
+
+				float intensityPerBin = backParams.intensity;
 				for(size_t ui=0;ui<d->xyData.size(); ui++)
+
 				{
 					//negative sqrt cannot does not work. Equation only valid for positive masses
 					if(d->xyData[ui].first <=0)
 						continue;
 		
 					plotBack->xyData.push_back( std::make_pair(d->xyData[ui].first,
-							backParams.intensity/(sqrtf(d->xyData[ui].first))));
+							intensityPerBin/(2.0*sqrtf(d->xyData[ui].first))));
 			
 				}
 
@@ -674,7 +682,6 @@ void SpectrumPlotFilter::getProperties(FilterPropGroup &propertyList) const
 
 	propertyList.setGroupTitle(curGroup,TRANS("Appearance"));
 
-	/* FIXME: This has been removed owing to broken unit test. 
 	curGroup++;
 
 	choices.clear();
@@ -728,7 +735,7 @@ void SpectrumPlotFilter::getProperties(FilterPropGroup &propertyList) const
 
 	}
 
-	propertyList.setGroupTitle(curGroup,TRANS("Background Mode"));*/	
+	propertyList.setGroupTitle(curGroup,TRANS("Background Mode"));
 	
 }
 
diff --git a/src/backend/filters/transform.cpp b/src/backend/filters/transform.cpp
index bcc6927..e5ba4c0 100644
--- a/src/backend/filters/transform.cpp
+++ b/src/backend/filters/transform.cpp
@@ -37,7 +37,9 @@ enum
 	KEY_NOISETYPE,
 	KEY_ROTATE_ANGLE,
 	KEY_ROTATE_AXIS,
-	KEY_ORIGIN_VALUE
+	KEY_ORIGIN_VALUE,
+	KEY_CROP_MINIMUM,
+	KEY_CROP_MAXIMUM,
 };
 
 //Possible transform modes (scaling, rotation etc)
@@ -50,6 +52,7 @@ enum
 	MODE_VALUE_SHUFFLE,
 	MODE_SPATIAL_NOISE,
 	MODE_TRANSLATE_VALUE,
+	MODE_CROP_VALUE,
 	MODE_ENUM_END
 };
 
@@ -84,7 +87,8 @@ const char *TRANSFORM_MODE_STRING[] = { NTRANS("Translate"),
 					NTRANS("Rotate"),
 					NTRANS("Value Shuffle"),
 					NTRANS("Spatial Noise"),
-					NTRANS("Translate Value")
+					NTRANS("Translate Value"),
+					NTRANS("Crop Value")
 					};
 
 const char *TRANSFORM_ORIGIN_STRING[]={ 
@@ -305,9 +309,10 @@ unsigned int TransformFilter::refresh(const std::vector<const FilterStreamData *
 	if( transformMode != MODE_VALUE_SHUFFLE)
 	{
 		//Don't cross the streams. Why? It would be bad.
-		//  - I'm fuzzy on the whole good-bad thing, what do you mean bad?"
+		//  - I'm fuzzy on the whole good-bad thing, what do you mean bad?
 		//  - Every ion in the data body can be operated on independently.
-		//
+		//		FIXME: I'm still not clear why that is bad. Might have something to do with tracking range parent IDs, or somesuch
+		//			may or may not be relevant today 
 		//  OK, important safety tip.
 		size_t n=0;
 		for(unsigned int ui=0;ui<dataIn.size() ;ui++)
@@ -751,6 +756,35 @@ unsigned int TransformFilter::refresh(const std::vector<const FilterStreamData *
 					}
 					break;
 				}
+				case MODE_CROP_VALUE:
+				{
+					ASSERT(scalarParams.size() == 2);
+
+					switch(dataIn[ui]->getStreamType())
+					{
+						case STREAM_TYPE_IONS:
+						{
+							//Set up scaling output ion stream 
+							IonStreamData *d=new IonStreamData;
+							d->parent=this;
+							
+							const IonStreamData *src = (const IonStreamData *)dataIn[ui];
+							for(unsigned int uj=0;uj<src->data.size();uj++)
+							{
+								float v;
+								v=src->data[uj].getMassToCharge();
+								if(v >=scalarParams[0] && v < scalarParams[1])
+									d->data.push_back(src->data[uj]);
+							}
+
+							d->estimateIonParameters(src);
+							cacheAsNeeded(d);
+							
+							getOut.push_back(d);
+						}
+					}
+				}
+				break;
 				case MODE_ROTATE:
 				{
 					Point3D origin=vectorParams[0];
@@ -772,12 +806,8 @@ unsigned int TransformFilter::refresh(const std::vector<const FilterStreamData *
 								delete d;
 								return ERR_NOMEM;
 							}
-							d->r = src->r;
-							d->g = src->g;
-							d->b = src->b;
-							d->a = src->a;
-							d->ionSize = src->ionSize;
-							d->valueType=src->valueType;
+
+							d->estimateIonParameters(src);
 
 							//We are going to rotate the incoming point data
 							//around the specified origin.
@@ -967,7 +997,8 @@ unsigned int TransformFilter::refresh(const std::vector<const FilterStreamData *
 					}
 					break;
 				}
-			}
+			
+		}
 		}
 	}
 	else
@@ -993,7 +1024,7 @@ unsigned int TransformFilter::refresh(const std::vector<const FilterStreamData *
 		d->b = 0.5;
 		d->a = 0.5;
 		d->ionSize = 2.0;
-		d->valueType=TRANS("Mass-to-Charge (amu/e)");
+		d->valueType=TRANS("Mass-to-Charge (Da/e)");
 
 		size_t curPos=0;
 		
@@ -1315,6 +1346,29 @@ void TransformFilter::getProperties(FilterPropGroup &propertyList) const
 
 			break;	
 		}
+		case MODE_CROP_VALUE:
+		{
+			ASSERT(vectorParams.size() == 0);
+			ASSERT(scalarParams.size() == 2);
+			
+			
+			stream_cast(tmpStr,scalarParams[0]);
+			p.name=TRANS("Min Value");
+			p.data=tmpStr;
+			p.key=KEY_CROP_MINIMUM;
+			p.type=PROPERTY_TYPE_REAL;
+			p.helpText=TRANS("Minimum value to use for crop");
+			propertyList.addProperty(p,curGroup);
+			
+			stream_cast(tmpStr,scalarParams[1]);
+			p.name=TRANS("Max Value");
+			p.data=tmpStr;
+			p.key=KEY_CROP_MAXIMUM;
+			p.type=PROPERTY_TYPE_REAL;
+			p.helpText=TRANS("Maximum value to use for crop");
+			propertyList.addProperty(p,curGroup);
+			break;
+		}
 		default:
 			ASSERT(false);
 	}
@@ -1374,6 +1428,10 @@ bool TransformFilter::setProperty(  unsigned int key,
 				case MODE_SPATIAL_NOISE:
 					scalarParams.push_back(0.1f);
 					break;
+				case MODE_CROP_VALUE:
+					scalarParams.push_back(1.0f);
+					scalarParams.push_back(100.0f);
+					break;
 				default:
 					ASSERT(false);
 			}
@@ -1465,6 +1523,20 @@ bool TransformFilter::setProperty(  unsigned int key,
 			}
 			break;
 		}
+		case KEY_CROP_MINIMUM:
+		{
+			ASSERT(scalarParams.size() ==2);
+			if(!applyPropertyNow(scalarParams[0],value,needUpdate))
+				return false;
+			break;
+		}
+		case KEY_CROP_MAXIMUM:
+		{
+			ASSERT(scalarParams.size() ==2);
+			if(!applyPropertyNow(scalarParams[1],value,needUpdate))
+				return false;
+			break;
+		}
 		default:
 			ASSERT(false);
 	}	
@@ -1606,6 +1678,12 @@ bool TransformFilter::readState(xmlNodePtr &nodePtr, const std::string &stateFil
 		case MODE_VALUE_SHUFFLE:
 		case MODE_SPATIAL_NOISE:
 			break;
+		case MODE_CROP_VALUE:
+		{
+			if(vectorParams.size() != 0 || scalarParams.size() !=2)
+				return false;
+			break;
+		}
 		default:
 			ASSERT(false);
 			return false;
diff --git a/src/backend/filters/voxelise.cpp b/src/backend/filters/voxelise.cpp
index adcf39b..7269227 100644
--- a/src/backend/filters/voxelise.cpp
+++ b/src/backend/filters/voxelise.cpp
@@ -208,7 +208,7 @@ VoxeliseFilter::VoxeliseFilter()
 	numeratorAll = false;
 	denominatorAll = true;
 
-	sliceInterpolate=SLICE_INTERP_NONE;
+	sliceInterpolate=VOX_INTERP_NONE;
 	sliceAxis=0;
 	sliceOffset=0.5;
 	showColourBar=false;
@@ -827,7 +827,7 @@ void VoxeliseFilter::getProperties(FilterPropGroup &propertyList) const
 			p.data=str;
 			p.type=PROPERTY_TYPE_BOOL;
 			p.helpText=TRANS("Enable this ion for numerator");
-			p.key=KEY_ENABLE_NUMERATOR*1000+ui;
+			p.key=muxKey(KEY_ENABLE_NUMERATOR,ui);
 			propertyList.addProperty(p,curGroup);
 		}
 	
@@ -843,6 +843,7 @@ void VoxeliseFilter::getProperties(FilterPropGroup &propertyList) const
 		p.type=PROPERTY_TYPE_BOOL;
 		p.helpText=TRANS("Parameter \"b\" used in fraction (a/b) to get voxel value");
 		p.key=KEY_ENABLE_DENOMINATOR;
+		propertyList.addProperty(p,curGroup);
 
 		for(unsigned  int ui=0; ui<rsdIncoming->enabledIons.size(); ui++)
 		{			
@@ -850,7 +851,7 @@ void VoxeliseFilter::getProperties(FilterPropGroup &propertyList) const
 			str=boolStrEnc(enabledIons[1][ui]);
 
 			//Append the ion name with a checkbox
-			p.key=KEY_ENABLE_DENOMINATOR*1000 + ui;
+			p.key=muxKey(KEY_ENABLE_DENOMINATOR,ui);
 			p.data=str;
 			p.name=rsdIncoming->rangeFile->getName(ui);
 			p.type=PROPERTY_TYPE_BOOL;
@@ -858,7 +859,7 @@ void VoxeliseFilter::getProperties(FilterPropGroup &propertyList) const
 
 			propertyList.addProperty(p,curGroup);
 		}
-		propertyList.setGroupTitle(curGroup,TRANS("Mode"));
+		propertyList.setGroupTitle(curGroup,TRANS("Denominator"));
 		curGroup++;
 	}
 
@@ -1021,7 +1022,7 @@ void VoxeliseFilter::getProperties(FilterPropGroup &propertyList) const
 		
 			
 			p.name=TRANS("Interp. Mode");
-			for(unsigned int ui=0;ui<SLICE_INTERP_ENUM_END;ui++)
+			for(unsigned int ui=0;ui<VOX_INTERP_ENUM_END;ui++)
 			{
 				choices.push_back(make_pair(ui,
 					TRANS(VOXELISE_SLICE_INTERP_STRING[ui])));
@@ -1408,10 +1409,10 @@ bool VoxeliseFilter::setProperty(unsigned int key,
 		case KEY_VOXEL_SLICE_INTERP:
 		{
 			unsigned int i;
-			for (i = 0; i < SLICE_INTERP_ENUM_END; i++)
+			for (i = 0; i < VOX_INTERP_ENUM_END; i++)
 				if( value == TRANS(VOXELISE_SLICE_INTERP_STRING[i])) break;
 				
-			if( i >= SLICE_INTERP_ENUM_END)
+			if( i >= VOX_INTERP_ENUM_END)
 				return false;
 
 			if(i != sliceInterpolate)
@@ -1525,25 +1526,28 @@ bool VoxeliseFilter::setProperty(unsigned int key,
 		}
 		default:
 		{
+			unsigned int subKeyType,offset;
+			demuxKey(key,subKeyType,offset);
+			
 			//Check for jump to denominator or numerator section
 			// TODO: This is a bit of a hack.
-			if (key >= KEY_ENABLE_DENOMINATOR*1000) {
+			if (subKeyType==KEY_ENABLE_DENOMINATOR) {
 				bool b;
 				if(!boolStrDec(value,b))
 					return false;
 
-				enabledIons[1][key - KEY_ENABLE_DENOMINATOR*1000]=b;
+				enabledIons[1][offset]=b;
 				if (!b) {
 					denominatorAll = false;
 				}
 				needUpdate=true;			
 				clearCache();
-			} else if (key >= KEY_ENABLE_NUMERATOR*1000) {
+			} else if (subKeyType == KEY_ENABLE_NUMERATOR) {
 				bool b;
 				if(!boolStrDec(value,b))
 					return false;
 				
-				enabledIons[0][key - KEY_ENABLE_NUMERATOR*1000]=b;
+				enabledIons[0][offset]=b;
 				if (!b) {
 					numeratorAll = false;
 				}
@@ -1818,7 +1822,7 @@ bool VoxeliseFilter::readState(xmlNodePtr &nodePtr, const std::string &stateFile
 		if(!XMLGetNextElemAttrib(sliceNodes,sliceInterpolate,"interpolate","value"))
 			return false;
 
-		if(sliceInterpolate >=SLICE_INTERP_ENUM_END)
+		if(sliceInterpolate >=VOX_INTERP_ENUM_END)
 			return false;
 
 		if(!XMLGetNextElemAttrib(sliceNodes,sliceAxis,"axis","value"))
diff --git a/src/backend/filtertree.cpp b/src/backend/filtertree.cpp
index b2449c3..ceeb33e 100644
--- a/src/backend/filtertree.cpp
+++ b/src/backend/filtertree.cpp
@@ -609,7 +609,7 @@ void FilterTree::getConsoleMessagesToNodes(std::vector<tree<Filter *>::iterator
 
 
 	//now loop through the filters and obtain the console messages
-	for(set<Filter *>::iterator it=filterSet.begin();it!=filterSet.end();it++)
+	for(set<Filter *>::iterator it=filterSet.begin();it!=filterSet.end();++it)
 	{
 		vector<string> tmpMsgs;
 		(*it)->getConsoleStrings(tmpMsgs);
@@ -664,6 +664,8 @@ unsigned int FilterTree::refreshFilterTree(list<FILTER_OUTPUT_DATA > &outData,
 	}
 
 
+	initFilterTree();
+
 	// -- Build data streams --	
 	vector< const FilterStreamData *> curData;
 	stack<vector<const FilterStreamData * > > inDataStack;
@@ -778,6 +780,11 @@ unsigned int FilterTree::refreshFilterTree(list<FILTER_OUTPUT_DATA > &outData,
 			if(!currentFilter->haveCache())
 				currentFilter->clearConsole();
 
+			currentFilter->clearDevices();
+
+			curProg.maxStep=curProg.step=1;
+			curProg.filterProgress=0;
+
 			//Take the stack top, filter it and generate "curData"
 			try
 			{
@@ -900,9 +907,9 @@ unsigned int FilterTree::refreshFilterTree(list<FILTER_OUTPUT_DATA > &outData,
 	//Construct a single list of all pointers in output,
 	//checking for uniqueness. Delete duplicates
 	
+	std::set<const FilterStreamData *> uniqueSet;
 	for(list<FILTER_OUTPUT_DATA>::iterator it=outData.begin();it!=outData.end(); )
 	{
-		std::set<const FilterStreamData *> uniqueSet;
 
 		vector<const FilterStreamData *>::iterator itJ;
 		itJ=it->second.begin();
@@ -927,8 +934,6 @@ unsigned int FilterTree::refreshFilterTree(list<FILTER_OUTPUT_DATA > &outData,
 	}
 	//======
 
-
-
 	return 0;
 }
 
@@ -1193,6 +1198,8 @@ unsigned int FilterTree::loadXML(const xmlNodePtr &treeParent, std::ostream &err
 bool FilterTree::saveXML(std::ofstream &f,std::map<string,string> &fileMapping, 
 					bool writePackage, bool useRelativePaths, unsigned int minTabDepth) const
 {
+	set<string> existingFiles;
+
 	f << tabs(minTabDepth+1) << "<filtertree>" << endl;
 	//Depth-first search, enumerate all filters in depth-first fashion
 	unsigned int depthLast=0;
@@ -1234,6 +1241,24 @@ bool FilterTree::saveXML(std::ofstream &f,std::map<string,string> &fileMapping,
 				string newFilename;
 				newFilename=string("./") + onlyFilename(valueOverrides[ui]);
 
+				//resolve naming clashes (eg if we had /path1/file.pos and /path2/file.pos, we need to ensure
+				// these are named such that we dont collide
+				//--
+				unsigned int offset=0;
+				string a,b,c;
+				splitFileData(newFilename,a,b,c);
+				while(existingFiles.find(newFilename) != existingFiles.end())
+				{
+					std::string s;
+					stream_cast(s,offset);
+					newFilename = a + b + "-" + s+ "." + c;
+					offset++;	
+				}
+
+				//record the new choice for filename, so we can check for future collisions
+				existingFiles.insert(newFilename);
+				//--
+				
 				map<string,string>::const_iterator it;
 				it =fileMapping.find(valueOverrides[ui]);
 				
@@ -1611,10 +1636,13 @@ void FilterTree::addFilterTree(FilterTree &f, const Filter *parent)
 	}
 	else
 	{
-		if(filters.empty())
-			filters.insert_subtree(filters.begin(),f.filters.begin());
-		else
-			filters.insert_subtree_after(filters.begin(),f.filters.begin());
+		if(f.size())
+		{
+			if(filters.empty())
+				filters.insert_subtree(filters.begin(),f.filters.begin());
+			else
+				filters.insert_subtree_after(filters.begin(),f.filters.begin());
+		}
 	}
 
 	f.filters.clear();
diff --git a/src/backend/filtertreeAnalyse.cpp b/src/backend/filtertreeAnalyse.cpp
index fcbda53..a62e7d1 100644
--- a/src/backend/filtertreeAnalyse.cpp
+++ b/src/backend/filtertreeAnalyse.cpp
@@ -99,10 +99,10 @@ bool affectedBySampling(const Filter *f, bool haveRngParent)
 			affected=haveRngParent;
 			break;
 		}
-		case FILTER_TYPE_COMPOSITION:
+		case FILTER_TYPE_PROFILE:
 		{
 			FilterProperty p;
-			p=props.getPropValue(COMPOSITION_KEY_NORMALISE);
+			p=props.getPropValue(PROFILE_KEY_NORMALISE);
 
 			//If using normalise mode, and we do not have a range parent
 			//then filter is in "density" plotting mode, which is affected by
@@ -270,7 +270,7 @@ void FilterTreeAnalyse::spatialSampling(const FilterTree &f)
 	//filter. 
 	vector<int> affectedFilters;
 	affectedFilters.push_back(FILTER_TYPE_CLUSTER_ANALYSIS); //If have range parent
-	affectedFilters.push_back(FILTER_TYPE_COMPOSITION); //If using density
+	affectedFilters.push_back(FILTER_TYPE_PROFILE); //If using density
 	affectedFilters.push_back(FILTER_TYPE_SPATIAL_ANALYSIS); 
 	affectedFilters.push_back(FILTER_TYPE_IONINFO); 
 
@@ -529,10 +529,10 @@ bool filterAffectedByComposition(const Filter *f, bool haveRngParent)
 			affected=haveRngParent;
 			break;
 		}
-		case FILTER_TYPE_COMPOSITION:
+		case FILTER_TYPE_PROFILE:
 		{
 			FilterProperty p;
-			p=props.getPropValue(COMPOSITION_KEY_NORMALISE);
+			p=props.getPropValue(PROFILE_KEY_NORMALISE);
 
 			//Affected if using normalise mode, and we do have a range parent
 			affected= (p.data== "1" && haveRngParent);
@@ -556,7 +556,7 @@ void FilterTreeAnalyse::compositionAltered(const FilterTree &f)
 	//filter. 
 	vector<int> affectedFilters;
 	affectedFilters.push_back(FILTER_TYPE_CLUSTER_ANALYSIS); //If have range parent
-	affectedFilters.push_back(FILTER_TYPE_COMPOSITION); //By definition
+	affectedFilters.push_back(FILTER_TYPE_PROFILE); //By definition
 	affectedFilters.push_back(FILTER_TYPE_IONINFO); //If using composition 
 
 	const tree<Filter *> &treeFilt=f.getTree();
diff --git a/src/backend/plot.h b/src/backend/plot.h
index fae258d..51894e4 100644
--- a/src/backend/plot.h
+++ b/src/backend/plot.h
@@ -31,6 +31,10 @@
 	#define NO_GSL
 #endif
 
+#ifdef __APPLE__
+	#define typeof __typeof__
+#endif
+
 //Use config header to determine if we need to enable mgl2 support
 #include "../config.h"
 #include <mgl2/mgl.h>
diff --git a/src/backend/state.cpp b/src/backend/state.cpp
index 2c8977a..66e3299 100644
--- a/src/backend/state.cpp
+++ b/src/backend/state.cpp
@@ -285,7 +285,8 @@ bool AnalysisState::save(const char *cpFilename, std::map<string,string> &fileMa
 	return true;
 }
 
-bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errStream ) 
+
+bool AnalysisState::loadInternal(const char *cpFilename, bool doMerge, std::ostream &errStream)
 {
 	if(doMerge)
 	{
@@ -561,6 +562,7 @@ bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errS
 				errStream<< TRANS("Unable to interpret property \"value\"  for \"cameras->active\" node.") << endl;
 				throw 1;
 			}
+			xmlFree(xmlString);
 
 		
 			//Spin through the list of each camera	
@@ -590,20 +592,34 @@ bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errS
 				}
 
 				ASSERT(thisCam);
-				newCameraVec.push_back(thisCam);	
+
+				//Discard any cameras that are non-unique There is a bug in some of the writer functions,
+				// so we can receive invalid data. We have to enforce validity
+				bool haveCameraAlready;
+				haveCameraAlready=false;
+				for(unsigned int ui=0; ui<newCameraVec.size() ; ui++)
+				{
+					if(thisCam->getUserString() == newCameraVec[ui]->getUserString())
+					{
+						haveCameraAlready=true;
+#ifdef DEBUG
+						cerr << "Found duplicate camera, ignoring" << endl;
+	#endif
+						break;
+					} 
+				}
+				if(!haveCameraAlready)
+					newCameraVec.push_back(thisCam);
+				else
+				{
+					delete thisCam;
+					thisCam=0;
+				}	
 			}
 
 
 		}
 
-		
-		//Enforce active cam value validity.
-		if(newCameraVec.empty())	
-			newCameraVec.push_back(new CameraLookAt);
-
-		if(newCameraVec.size() < activeCamera)
-			activeCamera=0;
-
 		//Now the cameras are loaded into a temporary vector. We will 
 		// copy them into the scene soon
 
@@ -812,11 +828,10 @@ bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errS
 	//Wipe the existing cameras, and then put the new cameras in place
 	savedCameras.clear();
 	
-	//Set a default camera as needed. We don't need to track its unique ID, as this is
-	//"invisible" to the UI
+	//Set a default camera as needed. 
 	Camera *c=new CameraLookAt();
 	savedCameras.push_back(c);
-	activeCamera=0;
+	
 	bool defaultSet = false;
 	//spin through
 	for(unsigned int ui=0;ui<newCameraVec.size();ui++)
@@ -827,11 +842,11 @@ bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errS
 		// set it directly. Otherwise, its a user camera.
 
 		//if there are multiple without a string, only use the first
-		if(newCameraVec[ui]->getUserString().size() && !defaultSet)
+		if(newCameraVec[ui]->getUserString().size())
 		{
 			savedCameras.push_back(newCameraVec[ui]);
 		}
-		else
+		else if (!defaultSet)
 		{
 			ASSERT(savedCameras.size());
 			delete savedCameras[0];
@@ -874,10 +889,24 @@ bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errS
 	// state is overwritten
 	setStateModifyLevel(STATE_MODIFIED_NONE);
 
+#ifdef DEBUG
+	checkSane();
+#endif
 	//Perform sanitisation on results
 	return true;
 }
 
+bool AnalysisState::load(const char *cpFilename, bool doMerge,std::ostream &errStream ) 
+{
+	AnalysisState otherState;
+	if(!otherState.loadInternal(cpFilename,doMerge,errStream))
+		return false;
+
+	*this=otherState;
+
+	return true;
+}
+
 void AnalysisState::merge(const AnalysisState &otherState)
 {
 
@@ -910,7 +939,8 @@ void AnalysisState::merge(const AnalysisState &otherState)
 	//wipe treestate's undo/redo trees, as we can no longer rely on them
 	treeState.clearUndoRedoStacks();	
 
-	treeState.addFilterTree(f,0);
+	if(f.size())
+		treeState.addFilterTree(f,true);
 	
 
 	const vector<Camera *> &newCameraVec = otherState.savedCameras;	
@@ -977,6 +1007,7 @@ void AnalysisState::removeCam(size_t offset)
 	setStateModifyLevel(STATE_MODIFIED_ANCILLARY);
 
 	ASSERT(offset < savedCameras.size());
+	delete savedCameras[offset];
 	savedCameras.erase(savedCameras.begin()+offset);
 	if(activeCamera >=savedCameras.size())
 		activeCamera=0;
@@ -990,6 +1021,8 @@ void AnalysisState::addCamByClone(const Camera *c)
 
 void AnalysisState::addCam(const std::string &camName, bool makeActive)
 {
+	//Disallow unnamed cameras
+	ASSERT(camName.size());
 	//Duplicate the current camera, and give it a new name
 	Camera *c=getCam(getActiveCam())->clone();
 	c->setUserString(camName);
@@ -1161,7 +1194,18 @@ std::string AnalysisState::getStashName(size_t offset) const
 	return  stashedTrees[offset].first;
 }
 
+#ifdef DEBUG
+void AnalysisState::checkSane() const
+{
+	ASSERT(activeCamera < savedCameras.size());
 
+	ASSERT(rBack >=0.0f && rBack <=1.0f 
+		&& gBack <= 1.0f && gBack >=0.0f &&
+		bBack >=0.0f && bBack <=1.0f);
+
+	
+}
+#endif
 
 void AnalysisState::eraseStash(size_t offset)
 {
@@ -1170,6 +1214,22 @@ void AnalysisState::eraseStash(size_t offset)
 	stashedTrees.erase(stashedTrees.begin() + offset);
 }
 
+void AnalysisState::eraseStashes(std::vector<size_t> &offsets)
+{
+	std::sort(offsets.begin(),offsets.end());
+	ASSERT(std::unique(offsets.begin(),offsets.end()) == offsets.end());
+
+
+
+	setStateModifyLevel(STATE_MODIFIED_ANCILLARY);
+	for(unsigned int ui=offsets.size();ui>0;)
+	{
+		ui--;
+		
+		stashedTrees.erase(stashedTrees.begin() + offsets[ui]);
+	}
+}
+		
 bool AnalysisState::hasStateOverrides() const
 {
 	if(treeState.hasStateOverrides())
@@ -1189,7 +1249,7 @@ void TreeState::operator=(const TreeState &oth)
 #ifdef DEBUG
 	//Should not be refreshing
 	wxMutexLocker lock(amRefreshing);
-	ASSERT(!lock.IsOk());
+	ASSERT(lock.IsOk());
 #endif
 	filterTree=oth.filterTree;	
 	
@@ -1198,7 +1258,6 @@ void TreeState::operator=(const TreeState &oth)
 	redoFilterStack=oth.redoFilterStack;
 	undoFilterStack=oth.undoFilterStack;
 	
-	fta=oth.fta;
 	selectionDevices=oth.selectionDevices;
 	pendingUpdates=oth.pendingUpdates;
 	
@@ -1237,12 +1296,15 @@ void TreeState::addFilter(Filter *f, bool isBase,size_t parentId)
 
 void TreeState::addFilterTree(FilterTree &f, bool isBase,size_t parentId)
 { 
-	ASSERT(!(isBase && parentId==(unsigned int)-1));
+	ASSERT(!(isBase && parentId==(size_t)-1));
 
 	if(isBase)
 		filterTree.addFilterTree(f,0);
 	else
+	{
+		ASSERT(filterMap.size());
 		filterTree.addFilterTree(f,filterMap[parentId]);
+	}
 
 	//FIXME: This technically does not need to be cleared. We can
 	// tweak the filter map to remain valid. It is the caller's problem
@@ -1549,6 +1611,17 @@ bool TreeState::hasUpdates() const
 {
 	return pendingUpdates;
 }
+bool TreeState::hasMonitorUpdates() const
+{
+	for(tree<Filter *>::iterator it=filterTree.depthBegin(); 
+			it!=filterTree.depthEnd();++it)
+	{
+		if((*it)->monitorNeedsRefresh())
+			return true;
+	}
+
+	return false;
+}
 
 
 
diff --git a/src/backend/state.h b/src/backend/state.h
index 275eece..4c397f1 100644
--- a/src/backend/state.h
+++ b/src/backend/state.h
@@ -97,6 +97,9 @@ class TreeState
 
 		//!Returns true if the filter tree has updates that need to be processed
 		bool hasUpdates() const; 
+		
+		//!Returns true if the filter tree has updates via a filter monitor 
+		bool hasMonitorUpdates() const; 
 
 		//Obtain a clone of the active filter tree
 		void cloneFilterTree(FilterTree &f) const {f=filterTree;};
@@ -276,6 +279,14 @@ class AnalysisState
 		//Clear the camera data vector
 		void clearCams();
 
+		//Actual load function for loading internal state
+		// this is used by ::load to mitigate actual "state" 
+		// class instance modifications on failure
+		bool loadInternal(const char *cpFilename,  bool merge,
+				std::ostream &errStream);
+#ifdef DEBUG
+		void checkSane() const;
+#endif
 	public:
 
 		TreeState treeState;
@@ -301,7 +312,9 @@ class AnalysisState
 				std::ostream &errStream);
 
 		//save an XML-ised representation of the analysis sate
-		//	- mapping provides the on-disk to local name mapping to use when saving
+		//	- Provides the on-disk to local name
+		//      mapping to use when saving. This needs to be copied by
+		//     the caller into the same dir as the XML file to be usable
 		// 	- write package says if state should attempt to ensure that output
 		// 		state is fully self-contained, and locally referenced
 		bool save(const char *cpFilename, std::map<std::string,std::string> &fileMapping,
@@ -339,7 +352,7 @@ class AnalysisState
 		void setCameraByClone(const Camera *c, unsigned int offset) ;
 
 		//Obtain the ID of the active camera
-		size_t getActiveCam() const  { return activeCamera;};
+		size_t getActiveCam() const  { ASSERT(activeCamera < savedCameras.size()) ; return activeCamera;};
 
 		//Set
 		void setActiveCam(size_t offset) {ASSERT(offset < savedCameras.size()); activeCamera=offset; };
@@ -417,8 +430,11 @@ class AnalysisState
 
 		//!Insert  the given stash into the tree as a child of the given parent filter
 		void addStashedToFilters(const Filter *parentFilter, unsigned int stashOffset);
-		//Remove the stash at the specified offset
+		//Remove the stash at the specified offset. Numbers will
+		// be reset, so previous offsets will no longer be valid
 		void eraseStash(size_t offset);
+		//Remove the given stashew at the specified offsets
+		void eraseStashes(std::vector<size_t> &offset);
 
 		//Return the number of stash elements
 		size_t getStashCount()  const { return stashedTrees.size();}
diff --git a/src/backend/viscontrol.cpp b/src/backend/viscontrol.cpp
index 2c3063e..a239ec9 100644
--- a/src/backend/viscontrol.cpp
+++ b/src/backend/viscontrol.cpp
@@ -102,6 +102,7 @@ void VisController::updateFilterPropGrid(wxPropertyGrid *g,size_t filterId, cons
 
 void VisController::updateScene(RefreshController *r)
 {
+	//Strip data out of the refresh controller (drop the parent filter data)
 	list<FILTER_OUTPUT_DATA> &sceneData = r->getRefreshData();
 	list< vector<const FilterStreamData *> > dataOnly;
 
@@ -151,6 +152,11 @@ void VisController::updateScene(list<vector<const FilterStreamData *> > &sceneDa
 			//Filter must specify whether it is cached or not. Other values
 			//are inadmissible, but useful to catch uninitialised values
 			ASSERT((*it)[ui]->cached == 0 || (*it)[ui]->cached == 1);
+			
+			//set to true if we need to free up ram pointed to by 
+			// scene object iterator
+			bool deleteIt;
+			deleteIt=false;
 
 			switch((*it)[ui]->getStreamType())
 			{
@@ -346,6 +352,7 @@ void VisController::updateScene(list<vector<const FilterStreamData *> > &sceneDa
 						//prevent vector destructor from deleting pointers
 						//we have transferred ownership of to scene
 						drawData->drawables.clear();
+						deleteIt=true;
 					}
 					break;
 				}
@@ -406,8 +413,10 @@ void VisController::updateScene(list<vector<const FilterStreamData *> > &sceneDa
 			}
 			
 			//delete drawables as needed
-			if(!(*it)[ui]->cached && releaseData)
+			if( (!(*it)[ui]->cached && releaseData) || deleteIt)
 			{
+				//Ensure that we didnt force deletion of a cached obejct
+				ASSERT(deleteIt != (*it)[ui]->cached);
 				delete (*it)[ui];
 				(*it)[ui]=0;	
 			}
@@ -670,7 +679,9 @@ void VisController::updateWxTreeCtrl(wxTreeCtrl *t, const Filter *visibleFilt)
 
 void VisController::updateStashComboBox(wxComboBox *comboStash) const
 {
-	comboStash->Clear();
+	//HACK: Calling ->Clear() under MSW causes a crash
+	while(comboStash->GetCount())
+		comboStash->Delete(0);
 
 	unsigned int nStashes = state.getStashCount();	
 	for(unsigned int ui=0;ui<nStashes; ui++)
@@ -687,7 +698,10 @@ void VisController::updateStashComboBox(wxComboBox *comboStash) const
 void VisController::updateCameraComboBox(wxComboBox *comboCamera) const
 {
 	//Update the camera dropdown
-	comboCamera->Clear();
+	//HACK: Calling ->Clear() under MSW causes a crash
+	while(comboCamera->GetCount())
+		comboCamera->Delete(0);
+	
 	size_t nCams = state.getNumCams();
 	//The start from 1 is a hack to avoid the unnamed camera
 	for(unsigned int ui=1;ui<nCams;ui++)
@@ -695,7 +709,8 @@ void VisController::updateCameraComboBox(wxComboBox *comboCamera) const
 		std::string camName;
 		camName = state.getCamName(ui);
 		ASSERT(camName.size());
-		//Do not delete as this will be deleted by wx
+		//Do not delete as this will be deleted by wx?
+		//FIXME: ListUInt is leaking... Is this a wx bug, or a usage bug?
 		comboCamera->Append(camName,
 				(wxClientData *)new wxListUint(ui));	
 		//If this is the active cam (1) set the selection and (2) remember
diff --git a/src/common/assertion.h b/src/common/assertion.h
index 89b069c..a70f827 100644
--- a/src/common/assertion.h
+++ b/src/common/assertion.h
@@ -56,8 +56,8 @@
 
 	//Debug timing routines
 	#define DEBUG_TIME_START() timeval TIME_DEBUG_t; gettimeofday(&TIME_DEBUG_t,NULL);
-	#define DEBUG_TIME_END() timeval TIME_DEBUG_tend; gettimeofday(&TIME_DEBUG_tend,NULL); \
-	std::cerr << (TIME_DEBUG_tend.tv_sec - TIME_DEBUG_t.tv_sec) + ((float)TIME_DEBUG_tend.tv_usec-(float)TIME_DEBUG_t.tv_usec)/1.0e6 << std::endl;
+	#define DEBUG_TIME_END()  { timeval TIME_DEBUG_tend; gettimeofday(&TIME_DEBUG_tend,NULL); \
+	std::cerr << (TIME_DEBUG_tend.tv_sec - TIME_DEBUG_t.tv_sec) + ((float)TIME_DEBUG_tend.tv_usec-(float)TIME_DEBUG_t.tv_usec)/1.0e6 << std::endl; }
 
 	#ifndef TEST
 	#define EQ_TOL(f,g) (fabs( (f) - (g)) < 0.001)
@@ -66,6 +66,8 @@
 	#define TEST(f,g) if(!(f)) { std::cerr << "Test fail :" << __FILE__ << ":" << __LINE__ << "\t"<< (g) << std::endl;return false;}
 	#endif
 
+	#define TRACE(f) { timespec timeval; clock_gettime(CLOCK_MONOTONIC, &timeval); std::cerr  << "<" << f <<">" __FILE__ << ":" << __LINE__ << " t: " << timeval.tv_sec << "." << timeval.tv_nsec/1000 << endl;} 
+
 	//A hack to generate compile time asserts (thanks Internet).
 	//This causes gcc to give "duplicate case value", if the predicate is false
 	#ifndef  HAVE_CPP_1X
@@ -79,6 +81,7 @@
 	#define COMPILE_ASSERT(f)
 	#define WARN(f,g) 
 	#define TEST(f,g)
+	#define TRACE(f)
 	//Do we want to trap floating point exceptions 
 	void trapfpe (bool doTrap=true);
 		
diff --git a/src/common/basics.cpp b/src/common/basics.cpp
index 1571566..20677e4 100644
--- a/src/common/basics.cpp
+++ b/src/common/basics.cpp
@@ -568,7 +568,7 @@ ColourRGBAf ColourRGBAf::interpolate(float delta, const ColourRGBAf &other)
 {
 	ColourRGBAf result;
 
-	for(unsigned int ui=0;ui<3;ui++)
+	for(unsigned int ui=0;ui<4;ui++)
 		result[ui] = data[ui] + (other.data[ui] - data[ui])*delta;
 	return result;
 }
@@ -696,11 +696,7 @@ void BoundCube::getVertices(std::vector<Point3D> &points, bool centre) const
 	points.resize(8);
 
 	for(size_t ui=0;ui<8;ui++)
-	{
-		points[ui][0]=bounds[0][ ui & 1]; 
-		points[ui][1]=bounds[1][ (ui & 2) >> 1]; 
-		points[ui][2]=bounds[2][ (ui & 4) >> 2]; 
-	}
+		points[ui]=getVertex(ui);
 
 	if(centre)
 	{
@@ -710,6 +706,60 @@ void BoundCube::getVertices(std::vector<Point3D> &points, bool centre) const
 	}
 }
 
+void BoundCube::getPlaneIntersectVertices(const Point3D &planeOrigin, const Point3D &normal, vector<Point3D> &intersectPts) const
+{
+	//To visualise the connections, draw a cube, then label
+	// each coordinate using a binary table like so:
+	// idx  x y z
+	// 0    0 0 0
+	// 1    1 0 0 
+	// etc ..
+
+	//Now flatten the cube into a graph like so :
+	//	0_________ 2
+	//	| \4___6/ |	^	y+ ->
+	//	|  |   |  |	| x-
+	//	|  5---7  |
+	//	| /     \ |
+	//	1---------- 3
+
+	//Edges are between  (idx  - idx + 4) (idx <4)		: 4 edges (diag) 
+	// 		and  (idx, idx +2) (idx in 0,1,4,5)	: 4 edges (across)
+	//		and  (idx,idx+1) (idx in 0,2,4,6)	: 4 edges (vertical)
+
+	//Adjacency graph for cube edges
+	const unsigned int eStartIdx[12] = {0,1,2,3, 0,1,4,5, 0,2,4,6};
+	const unsigned int eEndIdx[12] = {4,5,6,7, 2,3,6,7, 1,3,5,7};
+	
+
+	for(unsigned int ui=0;ui<12;ui++)
+	{
+		Point3D eStart,eEnd;
+		eStart = getVertex(eStartIdx[ui]);
+		eEnd = getVertex(eEndIdx[ui]);
+
+		float denom = (eEnd-eStart).dotProd(normal);
+
+		//check for intersection. If line vector is perp to
+		// plane normal, either is in plane, or no intersection
+		// for our purpose, do not report intersections that are in-the-plane
+		if(fabs(denom) < sqrtf(std::numeric_limits<float>::epsilon()))
+			continue;
+
+		float numerator = (planeOrigin - eStart).dotProd(normal);
+		float v;
+		v= numerator/denom;	
+		intersectPts.push_back((eEnd-eStart)*v+ eStart);
+	}
+}
+
+Point3D BoundCube::getVertex(unsigned int idx) const
+{
+	ASSERT(idx < 8);
+	
+	return Point3D(bounds[0][(idx&1)],bounds[1][(idx&2) >> 1],bounds[2][(idx&4)>>2]);
+}
+
 void BoundCube::setInverseLimits(bool setValid)
 {
 	bounds[0][0] = std::numeric_limits<float>::max();
@@ -907,7 +957,7 @@ float BoundCube::getSize(unsigned int dim) const
 }
 
 //checks intersection with sphere [centre,centre+radius)
-bool BoundCube::intersects(const Point3D &pt, float sqrRad)
+bool BoundCube::intersects(const Point3D &pt, float sqrRad) const
 {
 	Point3D nearPt;
 	
@@ -1015,16 +1065,10 @@ bool BoundCube::containedInSphere(const Point3D &queryPt,float sqrDist) const
 	}
 #endif
 
-
-	//Set lower and upper corners on the bounding rectangle
-	Point3D p[2];
-	p[0].setValue(bounds[0][0],bounds[1][0],bounds[2][0]);
-	p[1].setValue(bounds[0][1],bounds[1][1],bounds[2][1]);
-
-	//Count binary-wise selecting upper and lower limits, to enumerate all 8 verticies.
-	for(unsigned int ui=0;ui<9; ui++)
+	//Check all vertices
+	for(unsigned int ui=0;ui<8; ui++)
 	{
-		if(queryPt.sqrDist(Point3D(p[ui&1][0],p[(ui&2) >> 1][1],p[(ui&4) >> 2][2])) > sqrDist)
+		if(queryPt.sqrDist(getVertex(ui)) > sqrDist)
 			return false;
 	}
 
@@ -1300,7 +1344,7 @@ unsigned int loadTextData(const char *cpFilename, vector<vector<float> > &dataVe
 	bool atHeader=true;
 
 	vector<string> prevStrs;
-	while(!CFile.eof() && atHeader)
+	while(CFile.good() && !CFile.eof() && atHeader)
 	{
 		//Grab a line from the file
 		CFile.getline(inBuffer,BUFFER_SIZE);
@@ -1385,7 +1429,7 @@ unsigned int loadTextData(const char *cpFilename, vector<vector<float> > &dataVe
 
 	float f;
 	std::stringstream ss;
-	while(!CFile.eof())
+	while(CFile.good() && !CFile.eof())
 	{
 		if(strhas(inBuffer,"0123456789"))
 		{
diff --git a/src/common/basics.h b/src/common/basics.h
index 064ffbb..e7151f1 100644
--- a/src/common/basics.h
+++ b/src/common/basics.h
@@ -370,7 +370,7 @@ public:
     //!Get the bounds
     void getBounds(Point3D &low, Point3D &high) const ;
 
-    //!Return the size
+    //!Return the size of the cube along the specified dimension
     float getSize(unsigned int dim) const;
 
     //! Returns true if all bounds are valid
@@ -395,7 +395,7 @@ public:
 
     //Set & set-like operations
     //!Checks if a point intersects a sphere of centre Pt, radius^2 sqrRad
-    bool intersects(const Point3D &pt, float sqrRad);
+    bool intersects(const Point3D &pt, float sqrRad) const;
    
     //Create a union of two bounding cubes, which is itself a cube 
     BoundCube makeUnion(const BoundCube &b) const;
@@ -428,8 +428,15 @@ public:
     void expand(const Point3D &p);
     //!Expand by a specified thickness 
     void expand(float v);
+    //!Obtain a corner point of the cube
+    Point3D getVertex(unsigned int idx) const;
     //!Obtain the corner points of the cube
     void getVertices(std::vector<Point3D> &p,bool centre=false) const;
+	
+    //!Obtain the vertices that arise from the intersection of a plane with the cube
+    void getPlaneIntersectVertices(const Point3D &planeOrigin, 
+	const Point3D &normal, std::vector<Point3D> &intersectPts) const;
+
     friend  std::ostream &operator<<(std::ostream &stream, const BoundCube& b);
 
     //FIXME: Hack!
diff --git a/src/common/constants.cpp b/src/common/constants.cpp
index 3ce30a5..7bb901b 100644
--- a/src/common/constants.cpp
+++ b/src/common/constants.cpp
@@ -26,6 +26,6 @@ const char *DTD_NAME="threeDepict-state.dtd";
 //Program name
 const char *PROGRAM_NAME = "3Depict";
 //Program version
-const char *PROGRAM_VERSION = "0.0.18";
+const char *PROGRAM_VERSION = "0.0.19";
 //Path to font for Default FTGL  font
 const char *FONT_FILE= "FreeSans.ttf";
diff --git a/src/common/constants.h b/src/common/constants.h
index f4f0245..0ee20a9 100644
--- a/src/common/constants.h
+++ b/src/common/constants.h
@@ -71,8 +71,6 @@ struct PLOT_ERROR
 	unsigned int mode;
 	//!Number of data points for moving average
 	unsigned int movingAverageNum;
-	//!Edge mode
-	unsigned int edgeMode;
 };
 
 extern const char *RANGEFILE_WX_CONSTANT;
diff --git a/src/common/mathfuncs.cpp b/src/common/mathfuncs.cpp
index 1d5e49e..3c5c073 100644
--- a/src/common/mathfuncs.cpp
+++ b/src/common/mathfuncs.cpp
@@ -23,6 +23,8 @@
 
 #include <sys/time.h>
 
+#include <gsl/gsl_blas.h>
+
 using std::string;
 using std::vector;
 
@@ -161,6 +163,15 @@ const Point3D Point3D::operator/(float scale) const
 	return tmpPt;
 }
 
+const Point3D Point3D::operator/(const Point3D &pt) const
+{
+	Point3D tmpPt;
+	for(unsigned int ui=0;ui<3;ui++)
+		tmpPt.value[ui] = value[ui]/pt[ui];
+
+	return tmpPt;
+}
+
 float Point3D::sqrDist(const Point3D &pt) const
 {
 	return (pt.value[0]-value[0])*(pt.value[0]-value[0])+
@@ -244,7 +255,21 @@ void Point3D::negate()
 
 float Point3D::angle(const Point3D &pt) const
 {
-	return acos(dotProd(pt)/(sqrtf(sqrMag()*pt.sqrMag())));
+#ifndef EQ_TOL
+	#define EQ_TOL(f,g) (fabs( (f) - (g)) < sqrtf(std::numeric_limits<float>::epsilon()))
+#endif
+	//Check for near degenerate case. Acos does not appreciate small arguments in the dot product.
+	if( EQ_TOL(pt.value[0] , value[0]) &&  
+		 EQ_TOL(pt.value[1] , value[1]) &&  
+		 EQ_TOL(pt.value[2] , value[2]) )  
+		return 0;
+	double param = dotProd(pt)/sqrtf(sqrMag()*pt.sqrMag());
+
+	//trap the domain - on some systems, there are tolerance problems here
+	if(param > 1.0f || param < -1.0f)
+		return M_PI;
+	else
+		return acos(param); 
 }
 
 
@@ -922,4 +947,82 @@ double pyramidVol(const Point3D *planarPts, const Point3D &apex)
 	return 1.0/6.0 * (fabs(det3by3(simplexA)));	
 }
 
+void computeRotationMatrix(const Point3D &ur1, const Point3D &ur2,
+	const Point3D &r1, const Point3D &r2, gsl_matrix *m)
+{
+	//TRIAD algorithm, for determining rotation matrix from two
+	// linearly independant vector pairs.
+	// This is a specific case of "Wahba's Problem", where no noise is present
+
+	//unrotated and rotated vectors should be linearly independant
+	ASSERT(ur1.crossProd(ur2).sqrMag() < 0.001);
+	ASSERT(r1.crossProd(r2).sqrMag() < 0.001);
+
+	//vectors should be pre-normalised
+//	ASSERT(TOL_EQ(ur1.sqrMag(),1) && TOL_EQ(ur2.sqrMag(),1));
+//	ASSERT(TOL_EQ(r1.sqrMag(),1) && TOL_EQ(r2.sqrMag(),1));
+
+//	ASSERT(gsl_matrix_num_rows(m) == 3);
+//	ASSERT(gsl_matrix_num_cols(m) == 3);
+
+	Point3D rCross,urCross;
+	rCross = r1.crossProd(r2);
+	urCross = ur1.crossProd(r2);
+
+	gsl_matrix *a,*b;
+	a = gsl_matrix_alloc(3,3);
+	b = gsl_matrix_alloc(3,3);
+
+	for(unsigned int ui=0;ui<3;ui++)
+	{
+		//build A matrix, row by row
+		gsl_matrix_set(a,ui,0,ur1[ui]);
+		gsl_matrix_set(a,ui,1,ur2[ui]);
+		gsl_matrix_set(a,ui,2,urCross[ui]);
+
+		//build B^T matrix, row by row
+		gsl_matrix_set(b,0,ui,r1[ui]);
+		gsl_matrix_set(b,1,ui,r2[ui]);
+		gsl_matrix_set(b,2,ui,rCross[ui]);
+
+	}
+
+	//Compute m = a*b;
+	gsl_blas_dgemm (CblasNoTrans, CblasNoTrans,
+			    1.0, a, b,
+			    0.0, m);
+
+	gsl_matrix_free(a);
+	gsl_matrix_free(b);
+
+}
+
+void rotateByMatrix(const vector<Point3D> &vpts, const gsl_matrix *m, vector<Point3D> &r)
+{
+	r.resize(vpts.size());
+
+	gsl_vector *v = gsl_vector_alloc(3);
+	gsl_vector *rv = gsl_vector_alloc(3);
+
+
+	for(unsigned int ui=0;ui<vpts.size();ui++)
+	{
+		gsl_vector_set(v,0,vpts[ui][0]);
+		gsl_vector_set(v,1,vpts[ui][1]);
+		gsl_vector_set(v,2,vpts[ui][2]);
+
+		//compute v = m * pY;
+		gsl_blas_dgemv(CblasNoTrans,1.0, m, v,0,rv);
+
+		r[ui][0] = gsl_vector_get(rv,0);
+		r[ui][1] = gsl_vector_get(rv,1);
+		r[ui][2] = gsl_vector_get(rv,2);
+	}
+
+
+	gsl_vector_free(v);
+	gsl_vector_free(rv);
+}
+
+	
 
diff --git a/src/common/mathfuncs.h b/src/common/mathfuncs.h
index f48c122..ac18128 100644
--- a/src/common/mathfuncs.h
+++ b/src/common/mathfuncs.h
@@ -23,6 +23,8 @@
 #include <iostream>
 #include <vector>
 
+#include <gsl/gsl_matrix.h>
+
 
 #include "endianTest.h"
 
@@ -43,6 +45,10 @@ class Point3D
 		//!Constructor with initialising values
                 inline Point3D(float x,float y,float z) 
 					{ value[0] = x, value[1] = y, value[2] = z;}
+                inline Point3D(float *v)
+					{ value[0] = v[0], value[1] = v[1], value[2] = v[2];}
+                inline Point3D(double *v)
+					{ value[0] = v[0], value[1] = v[1], value[2] = v[2];}
                 //!Set by value (ith dim 0, 1 2)
                 inline void setValue(unsigned int ui, float val){value[ui]=val;};
 				//!Set all values
@@ -92,6 +98,8 @@ class Point3D
 		const Point3D operator*(const Point3D &pt) const;
 		//!Division. 
                 const Point3D operator/(float scale) const;
+
+                const Point3D operator/(const Point3D &p) const;
 		//!Subtraction
                 const Point3D operator-(const Point3D &pt) const;
 		//!returns a negative of the existing value
@@ -282,4 +290,16 @@ inline unsigned int ilog2(unsigned int value)
 		++l;
 	return l;
 }
+
+
+//!Use the TRIAD algorithm to compute the matrix that transforms orthogonal unit vectors
+// ur1,ur2 to rotated orthogonal unit vectors r1,r2. MUST be orthogonal and unit. 
+// matrix m must be pre-allocated 3x3 matrix
+void computeRotationMatrix(const Point3D &ur1, const Point3D &ur2,
+	const Point3D &r1, const Point3D &r2, gsl_matrix *m);
+
+//Rotate a set of points by the given 3x3 matrix
+void rotateByMatrix(const std::vector<Point3D> &vpts, 
+		const gsl_matrix *m, std::vector<Point3D> &r);
+
 #endif
diff --git a/src/common/stringFuncs.cpp b/src/common/stringFuncs.cpp
index 6d97f31..a2e19ed 100644
--- a/src/common/stringFuncs.cpp
+++ b/src/common/stringFuncs.cpp
@@ -140,6 +140,34 @@ bool boolStrDec(const std::string &s, bool &b)
 	return true;
 }
 
+
+void splitFileData(const std::string &fileWithPath, std::string &path, std::string &basename, std::string &extension)
+{
+	path.clear(); basename.clear(); extension.clear();
+
+	if(fileWithPath.empty())
+		return;
+
+	basename= onlyFilename(fileWithPath);
+	path = onlyDir(fileWithPath);
+
+	unsigned int extPosition=(unsigned int)-1;
+	for(unsigned int ui=basename.size();ui--;)
+	{
+		if(basename[ui] =='.')
+		{
+			extPosition=ui;
+			break;
+		}
+		
+	} 
+
+	if(extPosition != (unsigned int)-1)
+	{
+		extension = basename.substr(extPosition+1,basename.size()-(extPosition+1));
+		basename = basename.substr(0,extPosition);
+	}
+}
 std::string onlyFilename( const std::string& path) 
 {
 #if defined(_WIN32) || defined(_WIN64)
@@ -229,7 +257,8 @@ bool genRandomFilename(std::string &s,bool seedRand)
 		retry++;
 	}
 	while(!f && (retry < MAX_RETRY) );
-	return f;
+
+	return f.good();
 
 }
 
@@ -589,6 +618,21 @@ bool testStringFuncs()
 	TEST(getMaxVerStr(verStrs) == "0.0.9","version string maximum testing");
 	}
 
+#if !(defined(__WIN32) || defined(__WIN64))
+	{
+	string filename;
+	filename="/path/blah.dir/basefile.test.ext";
+	string a,b,c;
+	splitFileData(filename, a,b,c);
+
+	TEST(a == "/path/blah.dir/","path split");	
+	TEST(b == "basefile.test","basename split");	
+	TEST(c == "ext","extension split");	
+	}
+
+#endif
+
+
 	return true;
 }
 
diff --git a/src/common/stringFuncs.h b/src/common/stringFuncs.h
index fe5d2bb..fc50cc7 100644
--- a/src/common/stringFuncs.h
+++ b/src/common/stringFuncs.h
@@ -88,6 +88,12 @@ void splitStrsRef(const char *cpStr, const char delim,std::vector<std::string> &
 //!Split string references using any of a given string of delimiters
 void splitStrsRef(const char *cpStr, const char *delim,std::vector<std::string> &v );
 
+//!Split the file into three parts, base path, base name and file extension
+// this splits using "/" and "." under unix, and "\" and "." under windows.
+// the "." between the basename and the extension is omitted. Trailing slashes in pathname are kept
+void splitFileData(const std::string &filenameWithPath , 
+		std::string &path, std::string &basename, std::string &extension);
+
 //!Return only the filename component
 std::string onlyFilename( const std::string& path );
 //!Return only  the directory name component of the full path 
diff --git a/src/common/voxels.cpp b/src/common/voxels.cpp
index 2612e20..85fcaba 100644
--- a/src/common/voxels.cpp
+++ b/src/common/voxels.cpp
@@ -17,12 +17,221 @@
  */
 #include "voxels.h"
 
+#include <utility>
+
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_blas.h>
+
+using std::vector;
+using std::pair;
 using std::numeric_limits;
-const float FLOAT_SMALL=
-	sqrt(numeric_limits<float>::epsilon());
 
 
+
+
+//Helper function to test if a point lies in a convex polygon. The input points MUST be convex
+//	- by default this will re-sort the polygon. This is needed to
+//		ensure convex ordering. If data is already ordered, you can
+//		safely disable this (angularSort=false).;
+bool pointIn2DConvexPoly(float px,float py,
+	vector<pair<float,float> > &planarPts2D, bool angularSort=true)
+{
+
+	ASSERT(planarPts2D.size() >=3);
+
+	if(angularSort)
+	{
+		//TODO : Optimise me. Probably not required to calculate angles explicitly
+
+		//Find the centre x,y value
+		float midPx =0;
+		float midPy =0;
+		for(size_t ui=1;ui<planarPts2D.size();ui++)
+		{
+			midPx +=planarPts2D[ui].first;
+			midPy +=planarPts2D[ui].second;
+		}
+		midPx/=planarPts2D.size();
+		midPy/=planarPts2D.size();
+	
+		//sort points by angle between vector p-p_0 and [1,0]	
+
+		vector<pair<unsigned int, float> > angles;
+		angles.resize(planarPts2D.size());
+		for(unsigned int ui=0;ui<planarPts2D.size();ui++)
+		{
+			float dx,dy;	
+			dx = planarPts2D[ui].first - midPx;
+			dy = planarPts2D[ui].second - midPy;
+	
+			angles[ui] = make_pair(ui,atan2(dy,dx));
+		}
+
+		//--
+		//First, sort by angle
+		ComparePairSecond cmp;
+		std::sort(angles.begin(),angles.end(),cmp); //Sort angle mapping
+
+		//then re-map the original points to the sorted angle
+		vector<pair<float,float>  > tmp;
+		tmp.resize(planarPts2D.size());
+		for(size_t ui=0;ui<planarPts2D.size();ui++)
+			tmp[ui] = planarPts2D[angles[ui].first];
+		//--
+		
+
+		planarPts2D.swap(tmp);
+	}
+
+	//find the normal vector. This is achieved by flipping the X/Y values
+	float nx =-(planarPts2D[1].second -planarPts2D[0].second);
+	float ny =(planarPts2D[1].first -planarPts2D[0].first);
+
+	float dx = (px-planarPts2D[0].first);
+	float dy = (py-planarPts2D[0].second);
+
+	//dot-product the result. If positive, is on RHS of line
+	bool positive = (nx*dx + ny*dy)>0;
+
+
+	//repeat, aborting if any half-plane  intersects
+	size_t nP = planarPts2D.size();
+	for(size_t ui=1;ui<nP;ui++)
+	{
+		unsigned int next;
+		next = 	(ui+1)%nP;
+
+		nx =-( planarPts2D[next].second -planarPts2D[ui].second);
+		ny =( planarPts2D[next].first -planarPts2D[ui].first);
+		
+		dx = (px-planarPts2D[ui].first);
+		dy = (py-planarPts2D[ui].second);
+
+		if((nx*dx + ny*dy > 0) != positive)
+			return false;
+	}
+
+	return true;
+}
+
+//FIXME: This code is unfinished.
+template<class T>
+vector<Point3D> getVoxelIntersectionPoints(const BoundCube &b, const Point3D &p, const Point3D &normal, 
+						const Voxels<T> &vox, unsigned int numRequiredSamples, 
+							vector<Point3D> &samples, vector<T> &interpVal)
+{
+	vector<Point3D> pts;
+	b.getPlaneIntersectVertices(p,normal,pts);
+
+	//Dont do anything if there is no intersection 
+	//(should have at least 3 pts to form a plane
+	if(pts.size() < 3)
+		return pts;
+		
+
+	//Now, using the plane points, rotate these into the Z=0 plane
+	gsl_matrix *m = gsl_matrix_alloc(3,3); 
+	computeRotationMatrix(Point3D(0,0,1),
+		Point3D(1,0,0),normal,Point3D(1,0,0),m);
+
+	//Now rotate them into the Z=0 plane	
+	vector<Point3D> planarPts;
+	rotateByMatrix(pts,m,planarPts);
+
+	//Find the 2D bounding box, then generate uniform deviate
+	// random numbers. Scale these ot fit inside the bbox.
+
+	vector<pair<float,float> > planarPts2D;
+	float bounds[2][2];
+	bounds[0][0] = std::numeric_limits<float>::max(); //minX
+	bounds[0][1] = std::numeric_limits<float>::max(); //minY
+	bounds[1][0] = -std::numeric_limits<float>::max(); //maxX
+	bounds[1][1] = -std::numeric_limits<float>::max(); //maxY
+		
+	for(unsigned  int ui=0; ui<planarPts.size();ui++)
+	{
+		//Should lie pretty close to z=0
+		ASSERT(planarPts[ui][2] < sqrt(std::numeric_limits<float>::epsilon()));
+
+		planarPts2D[ui].first = planarPts[ui][0];	
+		planarPts2D[ui].second = planarPts[ui][1];	
+
+		bounds[0][0] = std::min(bounds[0][0],planarPts2D[ui].first);
+		bounds[0][1] = std::min(bounds[0][1],planarPts2D[ui].second);
+
+		bounds[1][0] = std::max(bounds[1][0],planarPts2D[ui].first);
+		bounds[1][1] = std::max(bounds[1][1],planarPts2D[ui].second);
+	}
+
+	//Init the random number generator	
+	RandNumGen rng;
+	rng.initTimer();
+
+	//compute scaling factors
+	float ax,ay;
+	ax = bounds[1][0] - bounds[0][0];
+	ay = bounds[1][1] - bounds[0][1];
+
+	//generate the randomly sampled points
+	size_t nSample=0;
+	samples.resize(numRequiredSamples);
+	while(nSample< numRequiredSamples)
+	{
+		float px,py;
+		px = ax*rng.genUniformDev() + bounds[0][0];
+		py = ay*rng.genUniformDev() + bounds[0][0];
+		
+		if(pointIn2DConvexPoly(px,py,planarPts2D))
+		{
+			samples[nSample] = Point3D(px,py,0);
+			nSample++;
+		}
+	}
+
+
+	//Transpose the matrix to obtain the inverse transform 
+	// originally rotate from frame to z=0. After transpose, 
+	// will rotate from z=0 to frame 
+	gsl_matrix_transpose(m);
+	gsl_vector *vRot = gsl_vector_alloc(3);
+	gsl_vector *vOrig = gsl_vector_alloc(3);
+
+	gsl_vector_set(vOrig,3,0);
+	for(size_t ui=0;ui<samples.size(); ui++)
+	{
+		gsl_vector_set(vOrig,0,samples[ui][0]);
+		gsl_vector_set(vOrig,1,samples[ui][1]);
+		//compute v = m * pY;
+		gsl_blas_dgemv(CblasNoTrans,1.0, m, vOrig,0,vRot);
+
+		samples[ui] = Point3D(vRot->data);
+	}	
+
+	gsl_vector_free(vRot);
+	gsl_vector_free(vOrig);
+	gsl_matrix_free(m);
+
+	
+	//Find the interpolated value for each point in the voxel set
+	interpVal.resize(samples.size());
+	for(size_t ui=0;ui<samples.size();ui++)
+	{
+		const size_t INTERP_MODE=VOX_INTERP_LINEAR;
+		vox.getInterpolatedData(samples[ui],interpVal[ui]);
+	}
+
+
+	//Now delanuay tessalate the random points, with the surrounding polygon
+
+		
+}
+
 #ifdef DEBUG
+#include <algorithm>
+
+const float FLOAT_SMALL=
+	sqrt(numeric_limits<float>::epsilon());
 
 bool simpleMath()
 {
@@ -153,6 +362,27 @@ bool edgeCountTests()
 }
 */
 
+bool pointInPoly()
+{
+	vector<pair<float,float> > pts;
+	//make a square
+	pts.push_back(make_pair(0,0));	
+//	pts.push_back(make_pair(0,0.5));	
+	pts.push_back(make_pair(0,1));	
+	pts.push_back(make_pair(1,0));	
+	pts.push_back(make_pair(1,1));	
+
+	//shuffle vertex positions
+	std::random_shuffle(pts.begin(),pts.end());
+
+	//Run test
+	TEST(pointIn2DConvexPoly(0.5,0.5,pts),"Point-in-poly test");	// Inside
+	TEST(!pointIn2DConvexPoly(1.5,0.5,pts),"Point-in-poly test");	//Outside
+	TEST(!pointIn2DConvexPoly(1.5,1.5,pts),"Point-in-poly test");	//Diagonal
+
+	return true;
+}
+
 
 bool runVoxelTests()
 {
@@ -161,6 +391,8 @@ bool runVoxelTests()
 
 	TEST(basicTests(),"basic voxel tests");
 	TEST(simpleMath(), "voxel simple maths");	
+
+	TEST(pointInPoly(),"point-in-poly tests");
 //	TEST(edgeCountTests(), "voxel edge tests");	
 	return true;	
 }
diff --git a/src/common/voxels.h b/src/common/voxels.h
index b5c2d01..4f40f2d 100644
--- a/src/common/voxels.h
+++ b/src/common/voxels.h
@@ -31,6 +31,9 @@ const unsigned int MAX_CALLBACK=500;
 #undef I 
 #undef Complex
 #include <typeinfo>
+#if defined(WIN32) || defined(WIN64)
+#include <vigra/windows.h>
+#endif
 #include <vigra/multi_array.hxx>
 #include <vigra/multi_convolution.hxx>
 
@@ -65,9 +68,9 @@ enum{
 //Interpolation mode for slice 
 enum
 {
-	SLICE_INTERP_NONE,
-	SLICE_INTERP_LINEAR,
-	SLICE_INTERP_ENUM_END
+	VOX_INTERP_NONE,
+	VOX_INTERP_LINEAR,
+	VOX_INTERP_ENUM_END
 };
 
 enum{
@@ -110,6 +113,8 @@ static const bool *voxelsWantAbort;
 /*! To instantiate this class, objects must have
  * basic mathematical operators, such as * + - and =
  */
+//FIXME: Cross check all algorithsm agree that the centre of the voxel is 
+// where the data value is located
 template<class T> class Voxels
 {
 	private:
@@ -143,7 +148,7 @@ template<class T> class Voxels
 
 		//!Set the value of a point in the dataset
 		void setPoint(const Point3D &pt, const T &val);
-		//!Retrieve the value of a datapoint
+		//!Retrieve the value of a datapoint, this is rounded to the nearest voxel
 		T getPointData(const Point3D &pt) const;
 
 
@@ -161,6 +166,7 @@ template<class T> class Voxels
 				size_t y, size_t z) const;
 		//!Retrieve the value of a specific voxel
 		inline T getData(size_t x, size_t y, size_t z) const;
+		inline T getData(size_t *array) const;
 		//!Retrieve value of the nth voxel
 		inline T getData(size_t i) const { return voxels[i];}
 
@@ -172,6 +178,9 @@ template<class T> class Voxels
 		//!Set the value of nth point in the dataset
 		void setData(size_t n, const T &val);
 
+		//Obtain an interpolated entry. The interpolated values are obtained by padding
+		void getInterpolatedData(const Point3D &pt, T &v) const;
+
 		//Perform in-place gaussian smoothing
 		void isotropicGaussianSmooth(float stdev,float windowRatio);
 
@@ -180,7 +189,7 @@ template<class T> class Voxels
 
 		//get an interpolated slice from a section of the data
 		void getInterpSlice(size_t normal, float offset, T *p, 
-			size_t interpMode=SLICE_INTERP_NONE) const;
+			size_t interpMode=VOX_INTERP_NONE) const;
 
 		//Get a specific slice, from an integral offset in the data, no interp
 		void getSlice(size_t normal, size_t offset, T *p) const;
@@ -257,7 +266,7 @@ template<class T> class Voxels
 
 		//!Fill all voxels with a given value
 		void fill(const T &val);
-		//!Get the bounding size
+		//!Get the bounding box vertex (min/max) 
 		Point3D getMinBounds() const;
 		Point3D getMaxBounds() const;
 		//Obtain the ounds for a specified axis
@@ -1134,13 +1143,10 @@ template<class T>
 T Voxels<T>::getSum(const T &initialValue) const
 {
 	ASSERT(voxels.size());
-	using namespace vigra::acc;
-	AccumulatorChain<T,Sum> s();
-
 
 	T tmp(initialValue);
 	size_t n=voxels.size();
-#pragma omp parallel for
+#pragma omp parallel for reduction(+:tmp)
 	for(size_t ui=0;ui<n;ui++)
 		tmp+=voxels[ui];
 
@@ -1502,19 +1508,32 @@ void Voxels<T>::getInterpSlice(size_t normal, float offset,
 	//Obtain the appropriately interpolated slice
 	switch(interpMode)
 	{
-		case SLICE_INTERP_NONE:
+		case VOX_INTERP_NONE:
 		{
 			size_t slicePos;
 			slicePos=roundf(offset*binCount[normal]);
+			slicePos=std::min(slicePos,binCount[normal]-1);
 			getSlice(normal,slicePos,p);
 			break;
 		}
-		case SLICE_INTERP_LINEAR:
+		case VOX_INTERP_LINEAR:
 		{
-			//Find the upper and lower bounds
-			size_t sliceUpper,sliceLower;;
-			sliceUpper=ceilf(offset*binCount[normal]);
-			sliceLower=offset*binCount[normal];
+			//Find the upper and lower bounds, then
+			// limit them so we don't fall off the end of the dataset
+			size_t sliceUpper,sliceLower;
+			if(binCount[0] == 1)
+				sliceUpper=sliceLower=0;
+			else
+			{
+				sliceUpper=ceilf(offset*binCount[normal]);
+
+				if(sliceUpper >=binCount[normal])
+					sliceUpper=binCount[normal]-1;
+				else if(sliceUpper==0)
+					sliceUpper=1;
+				
+				sliceLower=sliceUpper-1;
+			}
 
 			{
 				T *pLower;
@@ -1542,6 +1561,59 @@ void Voxels<T>::getInterpSlice(size_t normal, float offset,
 
 }
 
+//FIXME: I think this has a slight shift as we are moving the data voxels
+// definition of the voxel centre by 1/2 a pitch, I think
+template<class T>
+void Voxels<T>::getInterpolatedData(const Point3D &p, T &v) const
+
+{
+#ifdef DEBUG
+	BoundCube bc(minBound,maxBound);
+	ASSERT(bc.containsPt(p));
+#endif
+
+	size_t index[3];
+	getIndex(index[0],index[1],index[2],p);
+
+	Point3D pitch =getPitch();
+	
+	//Find the offset to the voxel that we are in.
+	//fraction should be in range [0,1)
+	Point3D fraction = p - (minBound + Point3D(index[0],index[1],index[2])*pitch);
+	fraction =fraction/pitch;
+
+
+	size_t iPlus[3];
+	//0.5 corresponds to voxel centre.
+	for(unsigned int ui=0;ui<3;ui++)
+	{
+		if(index[ui] == (binCount[ui]-1))
+			iPlus[ui]=0;
+		else
+			iPlus[ui]=1;
+	}	
+	
+
+	float c[2][2];
+	//Tri-linear interpolation
+
+	//interpolate data values at cube vertices that surround point. We are coming from below the point
+	// so we are simply extending the field on the upper edge by duplicating values as needed
+	for(unsigned int ui=0;ui<4;ui++)
+	{
+		c[(ui&1)][(ui&2)>>1] = getData( index[0],index[1]+ iPlus[1]*(ui&1),index[2] + iPlus[2]*(ui&2) )*(1-fraction[0]) 
+				+  getData(index[0]+iPlus[0],index[1]+ iPlus[1]*(ui&1),index[2] + iPlus[2]*(ui&2));
+	}
+
+
+	float c0,c1;
+	c0 = c[0][0]*(1-fraction[1]) + c[1][0]*fraction[1];
+	c1 = c[0][1]*(1-fraction[1]) + c[1][1]*fraction[1];
+
+	v= c0*(1-fraction[2])*c1;	
+	
+}	
+
 template<class T>
 void Voxels<T>::isotropicGaussianSmooth(float stdev,float windowRatio)
 {
diff --git a/src/gl/cameras.cpp b/src/gl/cameras.cpp
index 4e2f5f3..63e8d02 100644
--- a/src/gl/cameras.cpp
+++ b/src/gl/cameras.cpp
@@ -437,42 +437,42 @@ void CameraLookAt::ensureVisible(const BoundCube &boundCube, unsigned int face)
 	float boxToFrontDist,faceSize[2];
 	switch(face)
 	{
-		case 0:
+		case CAMERA_DIR_ZPLUS:
 			faceOutVector = Point3D(0,0,1); 
 			boxToFrontDist=boundCube.getSize(2);
 			tmpUpVec = Point3D(0,1,0);
 			faceSize[0]=boundCube.getSize(0);
 			faceSize[1]=boundCube.getSize(1);
 			break;
-		case 1:
+		case CAMERA_DIR_YMINUS:
 			faceOutVector = Point3D(0,-1,0); 
 			boxToFrontDist=boundCube.getSize(1);
 			tmpUpVec = Point3D(1,0,0);
 			faceSize[0]=boundCube.getSize(1);
 			faceSize[1]=boundCube.getSize(0);
 			break;
-		case 2:
-			faceOutVector = Point3D(0,1,0); 
-			boxToFrontDist=boundCube.getSize(1);
-			tmpUpVec =Point3D(1,0,0);
-			faceSize[0]=boundCube.getSize(0);
-			faceSize[1]=boundCube.getSize(2);
-			break;
-		case 3:
+		case CAMERA_DIR_XPLUS:
 			faceOutVector = Point3D(1,0,0); 
 			boxToFrontDist=boundCube.getSize(0);
 			tmpUpVec = Point3D(0,0,1);
 			faceSize[0]=boundCube.getSize(1);
 			faceSize[1]=boundCube.getSize(2);
 			break;
-		case 4:
+		case CAMERA_DIR_YPLUS:
+			faceOutVector = Point3D(0,1,0); 
+			boxToFrontDist=boundCube.getSize(1);
+			tmpUpVec =Point3D(1,0,0);
+			faceSize[0]=boundCube.getSize(0);
+			faceSize[1]=boundCube.getSize(2);
+			break;
+		case CAMERA_DIR_ZMINUS:
 			faceOutVector = Point3D(0,0,-1); 
 			boxToFrontDist=boundCube.getSize(2);
 			tmpUpVec = Point3D(0,1,0);
 			faceSize[0]=boundCube.getSize(0);
 			faceSize[1]=boundCube.getSize(1);
 			break;
-		case 5:
+		case CAMERA_DIR_XMINUS:
 			faceOutVector = Point3D(-1,0,0); 
 			boxToFrontDist=boundCube.getSize(0);
 			tmpUpVec = Point3D(0,0,1);
@@ -745,8 +745,6 @@ bool CameraLookAt::setProperty(unsigned int key, const string &value)
 				return false;
 			}
 			
-			if(ltmp>=PROJECTION_MODE_ENUM_END)
-				return false;
 			
 			projectionMode=ltmp;
 			
@@ -848,6 +846,7 @@ bool CameraLookAt::readState(xmlNodePtr nodePtr)
 		lock=false;
 	else
 		return false;
+	xmlFree(xmlString);
 
 	//Retrieve origin
 	//====
@@ -996,6 +995,45 @@ float CameraLookAt::getViewWidth(float depth) const
 	ASSERT(false);
 }
 
+
+void CameraLookAt::repositionAroundTarget(unsigned int direction)
+{
+	//Try to reposition the camera around the target
+	float distance = sqrt(origin.sqrDist(target));
+	Point3D faceOutVector;	
+	switch(direction)
+	{
+		case CAMERA_DIR_ZPLUS:
+			faceOutVector = Point3D(0,0,1); 
+			faceOutVector*=distance;
+			break;
+		case CAMERA_DIR_YMINUS:
+			faceOutVector = Point3D(0,-1,0); 
+			faceOutVector*=distance;
+			break;
+		case CAMERA_DIR_XPLUS:
+			faceOutVector = Point3D(0,1,0); 
+			faceOutVector*=distance;
+			break;
+		case CAMERA_DIR_YPLUS:
+			faceOutVector = Point3D(1,0,0); 
+			faceOutVector*=distance;
+			break;
+		case CAMERA_DIR_ZMINUS:
+			faceOutVector = Point3D(0,0,-1); 
+			faceOutVector*=distance;
+			break;
+		case CAMERA_DIR_XMINUS:
+			faceOutVector = Point3D(-1,0,0); 
+			faceOutVector*=distance;
+			break;
+		default:
+			ASSERT(false);
+	}	
+
+	setOrigin(target+faceOutVector);
+}
+
 std::ostream& operator<<(std::ostream &strm, const Camera &c)
 {
 	strm << "origin: " << c.origin << std::endl;
diff --git a/src/gl/cameras.h b/src/gl/cameras.h
index 78a506b..06b5533 100644
--- a/src/gl/cameras.h
+++ b/src/gl/cameras.h
@@ -56,6 +56,17 @@ enum
 	CAMERA_KEY_LOOKAT_ORTHOSCALE
 };
 
+//visible direction enum
+enum
+{
+	CAMERA_DIR_ZPLUS, //0
+	CAMERA_DIR_YMINUS, //1
+	CAMERA_DIR_YPLUS, //2
+	CAMERA_DIR_XPLUS, //3
+	CAMERA_DIR_ZMINUS, //4
+	CAMERA_DIR_XMINUS, //5
+};
+
 class CameraProperty
 {
 	public:
@@ -240,6 +251,8 @@ class CameraLookAt : public Camera
 		//!Ensure that up direction is perpendicular to view direction
 		void recomputeUpDirection();
 		
+		void repositionAroundTarget(unsigned int direction);
+
 		//!Ensure that the box is visible
 		/*! Face is set by cube net
 					0
diff --git a/src/gl/drawables.cpp b/src/gl/drawables.cpp
index 08b6f4a..77d05db 100644
--- a/src/gl/drawables.cpp
+++ b/src/gl/drawables.cpp
@@ -45,8 +45,6 @@ TexturePool *DrawableObj::texPool=0;
 unsigned int DrawableObj::winX;
 unsigned int DrawableObj::winY;
 
-DrawTexturedQuad DrawPointLegendOverlay::dQuad;
-bool DrawPointLegendOverlay::quadSet=false;
 //==
 
 
@@ -182,8 +180,8 @@ void drawBox(Point3D pMin, Point3D pMax, float r,float g, float b, float a)
 {
 	//TODO: Could speedup with LINE_STRIP/LOOP. This is 
 	//not a bottleneck atm though.
+	glColor4f(r,g,b,a);
 	glBegin(GL_LINES);
-		glColor4f(r,g,b,a);
 		//Bottom corner out (three lines from corner)
 		glVertex3f(pMin[0],pMin[1],pMin[2]);
 		glVertex3f(pMax[0],pMin[1],pMin[2]);
@@ -610,6 +608,9 @@ DrawTexturedQuad::~DrawTexturedQuad()
 		texPool->closeTexture(textureId);
 		textureId=-1;
 	}
+
+	if(textureData)
+		delete[] textureData;
 }
 
 void DrawTexturedQuad::draw() const
@@ -725,6 +726,21 @@ DrawSphere::~DrawSphere()
 		gluDeleteQuadric(q);
 }
 
+DrawableObj *DrawSphere::clone() const
+{
+	DrawSphere *d = new DrawSphere();
+	d->r=r;
+	d->g=g;
+	d->b=b;
+	d->a=a;
+	d->origin=origin;
+	d->radius=radius;
+	d->latSegments=latSegments;
+	d->longSegments=longSegments;
+
+	d->q=gluNewQuadric();
+	return d;
+}
 
 void DrawSphere::getBoundingBox(BoundCube &b) const
 {
@@ -1858,6 +1874,8 @@ void DrawProgressCircleOverlay::draw( )const
 	}
 
 
+	float visGrey=getHighContrastValue();
+
 	//Draw the completed Steps
 	float thetaPerStep =  thetaPerFilter/maxStep;
 	for(size_t ui=1;ui<step;ui++)
@@ -1871,7 +1889,7 @@ void DrawProgressCircleOverlay::draw( )const
 		if(ui < step-1)
 		{
 			//Draw a line to mark the step
-			glColor4f(1.0f,0.0f,0.0f,1.0f);
+			glColor4f(visGrey,0.0f,0.0f,1.0f);
 			glBegin(GL_LINES);
 				glVertex3f(radiusIn*sin(curTheta),radiusIn*cos(curTheta),0);
 				glVertex3f(radiusOut*sin(curTheta),radiusOut*cos(curTheta),0);
@@ -1961,14 +1979,15 @@ void DrawProgressCircleOverlay::drawSection(unsigned int degreeStep,
 		return;
 
 
+	float visGrey= getHighContrastValue();
 
 
 	const float ALPHA_COMPLETE=0.5*alphaBase;
 	const float ALPHA_INCOMPLETE=0.15*alphaBase;
 	if(complete)	
-		glColor4f(1.0f,1.0f,1.0f,ALPHA_COMPLETE);
+		glColor4f(visGrey,visGrey,visGrey,ALPHA_COMPLETE);
 	else
-		glColor4f(1.0f,1.0f,1.0f,ALPHA_INCOMPLETE);
+		glColor4f(visGrey,visGrey,visGrey,ALPHA_INCOMPLETE);
 
 	//Draw arc
 	glBegin(GL_TRIANGLE_STRIP);
@@ -2214,6 +2233,12 @@ void DrawColourBarOverlay::draw() const
 
 }
 
+DrawableObj *DrawColourBarOverlay::clone() const
+{
+	DrawColourBarOverlay *newBar = new DrawColourBarOverlay(*this);
+	return newBar;
+}
+
 void DrawColourBarOverlay::setColourVec(const vector<float> &r,
 					const vector<float> &g,
 					const vector<float> &b)
@@ -2237,45 +2262,6 @@ DrawPointLegendOverlay::DrawPointLegendOverlay() : enabled(true)
 
 	std::string tmpStr =getDefaultFontFile();
 	font = new FTGLPolygonFont(tmpStr.c_str());
-
-	//check to see if we need to init the texture quad
-	if(!quadSet &&  texPool)
-	{
-
-		dQuad.setUseColouring(false);
-
-		//Create a circular texture
-		const unsigned int N_CHANNELS=4;
-		unsigned int LEG_TEX_SIZE = 256; 
-		unsigned char colourWhite[N_CHANNELS]= { 255,255,255,255 };
-		unsigned char colourBlack[N_CHANNELS]= { 0,0,0,0 };
-
-		//TODO: Convert to single channel texture, to save space?
-		// DrawQuad does not support single channel at this time
-		dQuad.resize(LEG_TEX_SIZE,LEG_TEX_SIZE,N_CHANNELS);
-		const float HALF_CIRCLE_R2 = 0.25; 
-		#pragma omp parallel for
-		for(unsigned int nX=0;nX<LEG_TEX_SIZE;nX++)
-		{
-			float fx;
-			fx= (float) nX/(float)LEG_TEX_SIZE - 0.5;
-			for(unsigned int nY=0;nY<LEG_TEX_SIZE;nY++)
-			{
-				float fy;
-				fy = (float) nY/(float)LEG_TEX_SIZE -0.5;
-				if( fx*fx + fy*fy < HALF_CIRCLE_R2) 
-					dQuad.setData(nX,nY,colourWhite);
-				else
-					dQuad.setData(nX,nY,colourBlack);
-			}
-
-		}
-
-		dQuad.rebindTexture(GL_RGBA);
-
-		quadSet=true;
-
-	}
 }
 
 DrawPointLegendOverlay::~DrawPointLegendOverlay()
@@ -2318,7 +2304,6 @@ void DrawPointLegendOverlay::draw() const
 
 	float delta = std::max(std::min(1.0f/legendItems.size(),0.02f),0.05f);
 	float size = delta*0.9f; 
-	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
 	float maxTextWidth=0;
 
@@ -2329,18 +2314,17 @@ void DrawPointLegendOverlay::draw() const
 	{
 		for(;ui<legendItems.size();ui++)
 		{
+			Draw2DCircle dCirc;
 
-			//Draw textured quad (circle)
+			//Draw circle
 			//--
-			dQuad.setVertex(0,Point3D(curX,curY,0));
-			dQuad.setVertex(1,Point3D(curX+size,curY,0));
-			dQuad.setVertex(2,Point3D(curX+size,curY+size,0));
-			dQuad.setVertex(3,Point3D(curX,curY+size,0));
+			dCirc.setCentre(curX+size/2.0f,curY+size/2.0f);
+			dCirc.setRadius(size/2.0f);
 
 			const RGBFloat *f;
 			f = &legendItems[ui].second;
-			glColor3f(f->v[0],f->v[1],f->v[2]);
-			dQuad.draw();
+			dCirc.setColour(f->v[0],f->v[1],f->v[2]);
+			dCirc.draw();
 
 
 			//--
@@ -2369,7 +2353,6 @@ void DrawPointLegendOverlay::draw() const
 		curX+=maxTextWidth + size;
 		curY=position[1] + 0.5*delta;
 	}
-	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
 void DrawPointLegendOverlay::addItem(const std::string &s, float r, float g, float b)
@@ -2863,3 +2846,76 @@ void DrawAxis::getBoundingBox(BoundCube &b) const
 	b.setInvalid();
 }
 
+Draw2DCircle::Draw2DCircle()
+{
+	angularStep = 2.0f*M_PI/180.0f;
+	filled=true;
+}
+
+void Draw2DCircle::draw() const
+{
+
+	float nSteps = 2.0* M_PI/angularStep;
+	WARN(nSteps > 1,"Draw2D Circle, too few steps");
+	glColor4f(r,g,b,1.0f);
+
+	if(filled)
+	{
+		glBegin(GL_TRIANGLE_FAN);
+			//Central vertex
+			glVertex2fv(centre);
+
+			//vertices from [0,2PI)
+			for(unsigned int ui=0;ui<nSteps;ui++)
+			{
+				float fx,fy,theta;
+				theta = angularStep*ui;	
+				fx = centre[0]+cos(-theta)*radius;
+				fy = centre[1]+sin(-theta)*radius;
+
+				glVertex2f(fx,fy);
+			}
+
+			//2PI vertex
+			glVertex2f(centre[0]+radius,centre[1]);
+		glEnd();
+	}
+	else
+	{
+		glBegin(GL_LINE_LOOP);
+		//Central vertex
+		for(unsigned int ui=0;ui<nSteps;ui++)
+		{
+			float fx,fy,theta;
+			theta = angularStep*ui;	
+			fx = centre[0]+cos(theta)*radius;
+			fy = centre[1]+sin(theta)*radius;
+
+			glVertex2f(fx,fy);
+		}
+		glEnd();
+	}
+}
+
+void Draw2DCircle::getBoundingBox(BoundCube &b) const
+{
+
+	b.setBounds(centre[0]-radius, centre[1]-radius,
+			centre[0]+radius, centre[1]+radius,
+			0,0);
+}
+
+unsigned int Draw2DCircle::getType() const
+{
+	return DRAW_TYPE_2D_CIRCLE; 	
+}
+
+
+DrawableObj *Draw2DCircle::clone() const
+{
+	Draw2DCircle *p = new Draw2DCircle;
+	*p = *this;	
+
+	return p;	
+}
+
diff --git a/src/gl/drawables.h b/src/gl/drawables.h
index fd3776e..e9040db 100644
--- a/src/gl/drawables.h
+++ b/src/gl/drawables.h
@@ -93,6 +93,7 @@ enum
 	DRAW_TYPE_CYLINDER,
 	DRAW_TYPE_DISPLAYLIST,
 	DRAW_TYPE_GLTEXT,
+	DRAW_TYPE_2D_CIRCLE,
 	DRAW_TYPE_RECTPRISM,
 	DRAW_TYPE_COLOURBAR,
 	DRAW_TYPE_TEXTUREDOVERLAY,
@@ -196,7 +197,7 @@ class DrawableObj
 
 		//!Set the active state of the object
 		void setActive(bool active);
-		//!Pure virtual funciton - draw the object
+		//!Pure virtual function - draw the object
 		virtual void draw() const =0;
 
 		//!Set if user can interact with object, needed for opengl hit testing
@@ -531,6 +532,8 @@ class DrawSphere : public DrawableObj
 		//! Destructor
 		virtual ~DrawSphere();
 
+		virtual DrawableObj *clone() const;
+
 		virtual unsigned int getType() const {return DRAW_TYPE_SPHERE;};	
 		//!Sets the location of the sphere's origin
 		void setOrigin(const Point3D &p);
@@ -899,6 +902,7 @@ class DrawColourBarOverlay : public DrawableOverlay
 		DrawColourBarOverlay(const DrawColourBarOverlay &o);
 		~DrawColourBarOverlay(){delete font;};
 		
+		virtual DrawableObj *clone() const; 
 
 		virtual unsigned int getType() const {return DRAW_TYPE_COLOURBAR;}
 
@@ -1030,7 +1034,6 @@ class DrawProgressCircleOverlay : public DrawAnimatedOverlay
 class DrawPointLegendOverlay : public DrawableOverlay
 {
 	private:
-	static DrawTexturedQuad dQuad;
 	static bool quadSet;
 
 	FTFont *font;
@@ -1194,6 +1197,7 @@ class DrawAxis : public DrawableObj
 		Point3D position;
 		//!size
 		float size;
+
 	public:
 		DrawAxis();
 		~DrawAxis();
@@ -1211,5 +1215,41 @@ class DrawAxis : public DrawableObj
 		void setPosition(const Point3D &p);
 
 		void getBoundingBox(BoundCube &b) const;
+
 };
+
+
+//Draw a 2D filled circle
+class Draw2DCircle : public DrawableObj
+{
+	private:
+		float centre[2];
+		float angularStep;
+		float radius; 
+
+		//Circle colour
+		float r,g,b;
+
+		//Should the circle be drawn as an outline, or as a filled object
+		bool filled;
+	public:
+		Draw2DCircle();
+		
+		void result() const; 
+		//Obtain the type mask for this drawable
+		virtual unsigned int getType() const;	
+		virtual DrawableObj *clone() const; 
+		virtual void getBoundingBox(BoundCube &b) const;
+
+		virtual void draw() const;
+
+		void setCentre(float fx,float fy) { centre[0] = fx; centre[1]= fy;};
+		void setRadius(float r) { radius=r;}
+		//Angular step in radiians
+		void setAngularStep(float da) { angularStep = da;};
+	
+		void setColour(float rP, float gP, float bP) { r=rP;g=gP;b=bP;} ;
+			
+};
+
 #endif
diff --git a/src/gl/glDebug.h b/src/gl/glDebug.h
index 2c87f7f..f6296f7 100644
--- a/src/gl/glDebug.h
+++ b/src/gl/glDebug.h
@@ -32,7 +32,7 @@
 #define glError() { \
 		GLenum err = glGetError(); \
 		while (err != GL_NO_ERROR) { \
-					fprintf(stderr, "glError: %s caught at %s:%u\n", (char *)gluErrorString(err), __FILE__, __LINE__); \
+					fprintf(stderr, "glError: %s caught at %s:%u\n", (char *)gluErrorString(err), __FILE__, (unsigned int)__LINE__); \
 					err = glGetError(); \
 				} \
 		}
diff --git a/src/gl/isoSurface.cpp b/src/gl/isoSurface.cpp
index 20110c9..f919305 100644
--- a/src/gl/isoSurface.cpp
+++ b/src/gl/isoSurface.cpp
@@ -792,6 +792,7 @@ bool testIsoSurface()
 	//Convert the triangle soup into a mesh
 	Mesh debugMesh;
 	TRIANGLE t;
+	t.physGroup=0;
 	for(size_t ui=0;ui<tVec.size();ui++)
 	{
 
diff --git a/src/gui/cropPanel.cpp b/src/gui/cropPanel.cpp
index f8827fd..6357b44 100644
--- a/src/gui/cropPanel.cpp
+++ b/src/gui/cropPanel.cpp
@@ -501,7 +501,12 @@ void CropPanel::draw()
 	//Draw greyed out section
 	//--
 	wxPen *noPen;
+#if wxCHECK_VERSION(3,1,0)
+	noPen = new wxPen(*wxBLACK,1,wxPENSTYLE_TRANSPARENT);
+#else
 	noPen = new wxPen(*wxBLACK,1,wxTRANSPARENT);
+#endif
+
 	b->SetColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND));
 	dc->SetBrush(*b);
 	dc->SetPen(*noPen);
diff --git a/src/gui/dialogs/ExportPos.cpp b/src/gui/dialogs/ExportPos.cpp
index c1e661c..add49be 100644
--- a/src/gui/dialogs/ExportPos.cpp
+++ b/src/gui/dialogs/ExportPos.cpp
@@ -39,6 +39,7 @@ using std::pair;
 using std::string;
 using std::vector;
 
+
 enum
 {
 	ID_BTN_ADDDATA=wxID_ANY+1,
@@ -152,7 +153,11 @@ void ExportPosDialog::initialiseData(FilterTree &f)
 
 void ExportPosDialog::OnVisibleRadio(wxCommandEvent &event)
 {
-	ASSERT(haveRefreshed);
+	//This event can fire BEFORE the dialog is shown (after initing)
+	// under MSW/wx3.1
+	if(!haveRefreshed)
+		return;
+
 	exportVisible=true;
 	listAvailable->DeleteAllItems();
 	enableSelectionControls(false);
@@ -512,8 +517,8 @@ void ExportPosDialog::do_layout()
     sizer_12->Add(listSelected, 1, wxEXPAND, 0);
     sizer_12->Add(20, 20, 0, 0, 0);
     sizer_13->Add(20, 20, 1, 0, 0);
-    sizer_13->Add(btnSave, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxALIGN_RIGHT|wxALIGN_BOTTOM, 6);
-    sizer_13->Add(btnCancel, 0, wxBOTTOM|wxALIGN_RIGHT|wxALIGN_BOTTOM, 6);
+    sizer_13->Add(btnSave, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxALIGN_BOTTOM, 6);
+    sizer_13->Add(btnCancel, 0, wxBOTTOM|wxALIGN_BOTTOM, 6);
     sizer_12->Add(sizer_13, 0, wxEXPAND, 0);
     sizer_4->Add(sizer_12, 1, wxALL|wxEXPAND, 5);
     SetSizer(sizer_4);
diff --git a/src/gui/dialogs/ExportRngDialog.cpp b/src/gui/dialogs/ExportRngDialog.cpp
index 0879a39..8f913e3 100644
--- a/src/gui/dialogs/ExportRngDialog.cpp
+++ b/src/gui/dialogs/ExportRngDialog.cpp
@@ -149,7 +149,8 @@ void ExportRngDialog::OnSave(wxCommandEvent &event)
 
 	//create a file chooser for later.
 	wxFileDialog *wxF = new wxFileDialog(this,TRANS("Save pos..."), wxT(""),
-		wxT(""),TRANS("ORNL format RNG (*.rng)|*.rng|All Files (*)|*"),wxFD_SAVE);
+		wxT(""),TRANS("Cameca/Ametek RRNG (*.rrng)|*.rrng|ORNL format RNG (*.rng)|*.rng|Cameca ENV (*.env)|*.env|All Files (*)|*"),wxFD_SAVE);
+	
 	//Show, then check for user cancelling export dialog
 	if(wxF->ShowModal() == wxID_CANCEL)
 	{
@@ -159,9 +160,25 @@ void ExportRngDialog::OnSave(wxCommandEvent &event)
 	
 	std::string dataFile = stlStr(wxF->GetPath());
 
+	unsigned int selectedFormat= wxF->GetFilterIndex();
+	unsigned int rngFormat=RANGE_FORMAT_RRNG;
+	switch(selectedFormat)
+	{
+		case 0:
+			rngFormat=RANGE_FORMAT_RRNG;
+			break;
+		case 1:
+			rngFormat=RANGE_FORMAT_ORNL;
+			break;
+		case 2:
+			rngFormat=RANGE_FORMAT_ENV;
+			break;
+		default:
+			ASSERT(false);
+	}
 
 	if(((RangeFileFilter *)(rngFilters[selectedRange]))->
-				getRange().write(dataFile.c_str()))
+				getRange().write(dataFile.c_str(),rngFormat))
 	{
 		std::string errString;
 		errString=TRANS("Unable to save. Check output destination can be written to.");
diff --git a/src/gui/dialogs/StashDialog.cpp b/src/gui/dialogs/StashDialog.cpp
index 7300f25..ddf3885 100644
--- a/src/gui/dialogs/StashDialog.cpp
+++ b/src/gui/dialogs/StashDialog.cpp
@@ -164,12 +164,11 @@ void StashDialog::updateList()
 		string strTmp;
 		pair<std::string,FilterTree> stash;
 		long itemIdx;
-		
+		visControl->state.copyStashedTree(ui,stash);
 		//First item is the stash name
 		itemIdx = listStashes->InsertItem(ui,stash.first);
 
 		//Second column is num filters
-		visControl->state.copyStashedTree(ui,stash);
 		stream_cast(strTmp,stash.second.size());
 		listStashes->SetItem(itemIdx,1,(strTmp));
 
@@ -329,6 +328,7 @@ void StashDialog::updateTree()
 void StashDialog::OnBtnRemove(wxCommandEvent &event)
 {
 	//Spin through the list, to find the selected items
+	vector<size_t> itemsToRemove;
 	int item=-1;
 	for ( ;; )
 	{
@@ -337,15 +337,12 @@ void StashDialog::OnBtnRemove(wxCommandEvent &event)
 					     wxLIST_STATE_SELECTED);
 		if ( item == -1 )
 			break;
-
-		visControl->state.eraseStash(listStashes->GetItemData(item));
-		updateList();
-		updateTree();
-		updateGrid();
-		
+		itemsToRemove.push_back(listStashes->GetItemData(item));
 	}
 	
+	visControl->state.eraseStashes(itemsToRemove);
 
+	ready();
 }
 
 void StashDialog::do_layout()
diff --git a/src/gui/dialogs/animateFilterDialog.cpp b/src/gui/dialogs/animateFilterDialog.cpp
index 7bc70b1..10e6332 100644
--- a/src/gui/dialogs/animateFilterDialog.cpp
+++ b/src/gui/dialogs/animateFilterDialog.cpp
@@ -82,15 +82,15 @@ const size_t RANGE_FORMAT_NUM_OPTIONS=3;
 //TODO: This should be merged into aptclasses?
 const char *extension[RANGE_FORMAT_NUM_OPTIONS] =
 {
-	"rng",
 	"rrng",
+	"rng",
 	"env"
 };
 
 const char * comboRange_choices[RANGE_FORMAT_NUM_OPTIONS] =
 {
-	NTRANS("Oak-Ridge RNG"),
 	NTRANS("Cameca/Ametek RRNG"),
+	NTRANS("Oak-Ridge RNG"),
 	NTRANS("Cameca/Ametek ENV")
 };
 
@@ -158,7 +158,7 @@ ExportAnimationDialog::ExportAnimationDialog(wxWindow* parent, int id, const wxS
     filterPropertySizer_staticbox = new wxStaticBox(filterLeftPane, -1, TRANS("Filters and properties"));
     filterTreeCtrl =new wxTreeCtrl(filterLeftPane,ID_FILTER_TREE_CTRL , wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS|wxTR_NO_LINES|wxTR_HIDE_ROOT|wxTR_DEFAULT_STYLE|wxSUNKEN_BORDER|wxTR_EDIT_LABELS);
 
-    propertyGrid = new wxPropertyGrid(filterLeftPane, ID_PROPERTY_GRID);
+    propertyGrid = new wxPropertyGrid(filterLeftPane, ID_PROPERTY_GRID,wxDefaultPosition,wxDefaultSize,PROPERTY_GRID_STYLE);
     animationGrid = new wxGrid(filterRightPane, ID_ANIMATION_GRID_CTRL);
     keyFrameRemoveButton = new wxButton(filterRightPane, wxID_REMOVE, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
     labelWorkDir = new wxStaticText(frameViewPane, wxID_ANY, TRANS("Dir : "));
@@ -168,7 +168,7 @@ ExportAnimationDialog::ExportAnimationDialog(wxWindow* parent, int id, const wxS
     outputDataSepLine = new wxStaticLine(frameViewPane, wxID_ANY);
     labelDataType = new wxStaticText(frameViewPane, wxID_ANY, TRANS("Data Types:"));
     checkImageOutput = new wxCheckBox(frameViewPane, ID_CHECK_IMAGE_OUT, TRANS("3D Images"));
-    lblImageName = new wxStaticText(frameViewPane, wxID_ANY, TRANS("File Suffix: "));
+    lblImageName = new wxStaticText(frameViewPane, wxID_ANY, TRANS("File Prefix: "));
     textImageName = new wxTextCtrl(frameViewPane, ID_TEXTBOX_IMAGEPREFIX, wxEmptyString);
     labelImageSize = new wxStaticText(frameViewPane, wxID_ANY, TRANS("Size : "));
     textImageSize = new wxTextCtrl(frameViewPane, ID_TEXTBOX_IMAGESIZE, wxEmptyString, wxDefaultPosition,wxDefaultSize, wxTE_READONLY );
@@ -192,6 +192,7 @@ ExportAnimationDialog::ExportAnimationDialog(wxWindow* parent, int id, const wxS
 	rangeNames.Add(wxStrTrans);
     }
     comboRangeFormat = new wxChoice(frameViewPane, ID_COMBO_RANGE_TYPE, wxDefaultPosition, wxDefaultSize, rangeNames);
+    comboRangeFormat->SetSelection(0);
     static_line_1 = new wxStaticLine(frameViewPane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
     labelFrame = new wxStaticText(frameViewPane, wxID_ANY, TRANS("Frame"));
     frameSlider = new wxSlider(frameViewPane, ID_FRAME_SLIDER, 0, 0, 1);
@@ -229,6 +230,7 @@ ExportAnimationDialog::ExportAnimationDialog(wxWindow* parent, int id, const wxS
 
 
     comboRangeFormat->Enable(checkRangeData->IsChecked());
+    rangeExportMode=RANGE_FORMAT_RRNG;
 
     currentFrame=0;
     existsConflicts=false;
@@ -400,6 +402,7 @@ void ExportAnimationDialog::prepare()
 	upWxTreeCtrl(*filterTree,filterTreeCtrl,filterMap,
 			dummyVec,NULL);
 
+	updateOKButton();	
 }
 
 void ExportAnimationDialog::updateFilterViewGrid()
@@ -408,7 +411,6 @@ void ExportAnimationDialog::updateFilterViewGrid()
 	animationGrid->BeginBatch();
 	if(animationGrid->GetNumberRows())
 		animationGrid->DeleteRows(0,animationGrid->GetNumberRows());
-	animationGrid->EndBatch();
 
 
 	animationGrid->AppendRows(propertyAnimator.getNumProps());
@@ -441,6 +443,8 @@ void ExportAnimationDialog::updateFilterViewGrid()
 		animationGrid->SetCellValue(ui,CELL_ENDFRAME, (str));
 	}
 
+	animationGrid->EndBatch();
+
 	//Check for conflicting rows in the animation dialog,
 	// and highlight them in colour
 	set<size_t> conflictRows;
@@ -635,6 +639,9 @@ void ExportAnimationDialog::OnFilterTreeCtrlSelChanged(wxTreeEvent &event)
 
 void ExportAnimationDialog::OnFilterGridCellChanging(wxPropertyGridEvent &event)
 {
+	//very odd behaviour. Bool options trigger the first time,  but
+	// not on the second time. Perhaps we can veto the event
+	// dynamically to catch this case?
 	event.SetValidationFailureBehavior(0);
 	event.Veto();
 }
@@ -656,8 +663,22 @@ void ExportAnimationDialog::OnFilterGridCellSelected(wxPropertyGridEvent &event)
 	//grab the key from the property grid
 	size_t key;
 	std::string keyStr;
+
+	wxPGProperty *pgp;
+	pgp= event.GetProperty();
+	if(!pgp)
+	{
+		cerr << "wxBUG: wx returned a null item for the event's property. THat makes no sense." << endl;	
+		event.Veto(); 
+		return;
+	}	
 	keyStr=event.GetProperty()->GetName();
-	stream_cast(key,keyStr);
+	if(stream_cast(key,keyStr))
+	{
+		cerr << "Wx bug? Should not be firing on a column that has no key" << endl; 
+		return;
+	}
+	cerr << "Keystr was :" << keyStr << endl;
 
 
 	const Filter *f;
@@ -857,6 +878,8 @@ void ExportAnimationDialog::OnFilterGridCellSelected(wxPropertyGridEvent &event)
 		}
 		default:
 			ASSERT(false); // that should cover all data types...
+			propertyGrid->ClearSelection();
+			return;
 	}
 
 	//Add property to animator
@@ -865,6 +888,7 @@ void ExportAnimationDialog::OnFilterGridCellSelected(wxPropertyGridEvent &event)
 	//update the user interface controls
 	update();
 
+	propertyGrid->ClearSelection();
 }
 
 void ExportAnimationDialog::OnFrameGridCellEditorShow(wxGridEvent &event)
@@ -1164,7 +1188,6 @@ void ExportAnimationDialog::set_properties()
     checkImageOutput->SetValue(1);
     textImageName->SetToolTip(TRANS("Title for files, result will be saved as #-name.png, where # is image number."));
     textImageSize->SetToolTip(TRANS("Target resolution (image size)"));
-    comboRangeFormat->SetSelection(-1);
     frameSlider->SetToolTip(TRANS("Select frame for property display"));
     textFrame->SetToolTip(TRANS("Enter frame number to change frame (eg 1/20)"));
     checkPoints->SetToolTip(TRANS("Save point data (POS files) in output folder?"));
@@ -1207,7 +1230,7 @@ void ExportAnimationDialog::do_layout()
     filterLeftPane->SetSizer(filterPropertySizer);
     animationGridSizer->Add(animationGrid, 1, wxALL|wxEXPAND, 3);
     keyFramesSizer->Add(animationGridSizer, 1, wxEXPAND, 0);
-    keyFrameButtonSizer->Add(keyFrameRemoveButton, 0, wxALIGN_CENTER_HORIZONTAL, 0);
+    keyFrameButtonSizer->Add(keyFrameRemoveButton, 0, 0, 0);
     keyFramesSizer->Add(keyFrameButtonSizer, 0, wxALL|wxEXPAND, 3);
     filterRightPane->SetSizer(keyFramesSizer);
     splitPaneFilter->SplitVertically(filterLeftPane, filterRightPane);
diff --git a/src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp b/src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp
index 109b51f..0375c2d 100644
--- a/src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp
+++ b/src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp
@@ -25,6 +25,10 @@
 #include <wx/colordlg.h>
 
 
+//TODO: Currently we change the foreground text in a button to set colour.
+// better would be to use a "swatch"
+
+
 using std::string;
 
 // begin wxGlade: ::extracode
@@ -195,16 +199,26 @@ void ColourKeyFrameDialog::updateOKButton()
 {
 	bool isOK=true;
 	isOK&=startFrameOK;
-	isOK&=endFrameOK;
+	isOK&= (endFrameOK || transitionMode == TRANSITION_STEP) ;
 
-	//Ensure start frame is > end frame
 	if(isOK)
 	{
-		isOK&=(startFrame<endFrame);
+		if(transitionMode == TRANSITION_INTERP) 
+		{
+			//Ensure start frame is > end frame, 
+			// if we are using interp mode
+			isOK&=(startFrame<endFrame);
+		}
+
 		if(!isOK)
 		{
+			//If there is a problem, mark the problem with a colour background
 			textFrameStart->SetBackgroundColour(*wxCYAN);
-			textFrameEnd->SetBackgroundColour(*wxCYAN);
+			if(transitionMode == TRANSITION_INTERP)
+				textFrameEnd->SetBackgroundColour(*wxCYAN);
+			else
+				textFrameEnd->SetBackgroundColour(wxNullColour);
+				
 		}
 		else
 		{
@@ -212,7 +226,8 @@ void ColourKeyFrameDialog::updateOKButton()
 			textFrameEnd->SetBackgroundColour(wxNullColour);
 		}
 	}
-	
+
+	//Enable the OK button if all properties are set appropriately
 	buttonOK->Enable(isOK);
 }
 
@@ -261,24 +276,24 @@ void ColourKeyFrameDialog::do_layout()
 	sizerLeft->Add(sizerTransition, 1, wxEXPAND, 0);
 	sizerStartFrame->Add(labelFrameStart, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
 	sizerStartFrame->Add(textFrameStart, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
-	sizerLeft->Add(sizerStartFrame, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerLeft->Add(sizerStartFrame, 1, wxEXPAND, 0);
 	sizerEndFrame->Add(labelFrameEnd, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 12);
 	sizerEndFrame->Add(textFrameEnd, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
-	sizerLeft->Add(sizerEndFrame, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerLeft->Add(sizerEndFrame, 1, wxEXPAND, 0);
 	sizerLeft->Add(20, 10, 0, 0, 0);
 	sizerMainArea->Add(sizerLeft, 2, wxEXPAND, 0);
 	sizerMainArea->Add(verticalLine, 0, wxLEFT|wxRIGHT|wxEXPAND, 5);
 	sizerRight->Add(20, 20, 1, 0, 0);
 	sizerRightInitial->Add(20, 20, 1, 0, 0);
-	sizerRightInitial->Add(labelStartVal, 2, wxRIGHT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
-	sizerRightInitial->Add(btnStartColour, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 3);
+	sizerRightInitial->Add(labelStartVal, 2, wxRIGHT|wxALIGN_CENTER_VERTICAL, 0);
+	sizerRightInitial->Add(btnStartColour, 0, wxALL|wxALIGN_CENTER_VERTICAL, 3);
 	sizerRightInitial->Add(20, 20, 1, 0, 0);
-	sizerRight->Add(sizerRightInitial, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerRight->Add(sizerRightInitial, 1, wxEXPAND, 0);
 	sizerRightFinal->Add(20, 20, 1, 0, 0);
-	sizerRightFinal->Add(labelFinalVal, 2, wxRIGHT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 9);
-	sizerRightFinal->Add(btnEndColour, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 3);
+	sizerRightFinal->Add(labelFinalVal, 2, wxRIGHT|wxALIGN_CENTER_VERTICAL, 9);
+	sizerRightFinal->Add(btnEndColour, 0, wxALL|wxALIGN_CENTER_VERTICAL, 3);
 	sizerRightFinal->Add(20, 20, 1, 0, 0);
-	sizerRight->Add(sizerRightFinal, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerRight->Add(sizerRightFinal, 1, wxEXPAND, 0);
 	sizerRight->Add(20, 20, 1, 0, 0);
 	sizerMainArea->Add(sizerRight, 2, wxEXPAND, 0);
 	sizerMainArea->Add(10, 20, 0, 0, 0);
diff --git a/src/gui/dialogs/animateSubDialogs/realKeyFrameDialog.h b/src/gui/dialogs/animateSubDialogs/realKeyFrameDialog.h
index 40cfa64..4e9abc6 100644
--- a/src/gui/dialogs/animateSubDialogs/realKeyFrameDialog.h
+++ b/src/gui/dialogs/animateSubDialogs/realKeyFrameDialog.h
@@ -308,20 +308,20 @@ void RealKeyFrameDialog<T>::do_layout()
 	sizerLeft->Add(sizerTransition, 1, wxEXPAND, 0);
 	sizerStartFrame->Add(labelFrameStart, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
 	sizerStartFrame->Add(textFrameStart, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
-	sizerLeft->Add(sizerStartFrame, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerLeft->Add(sizerStartFrame, 1, wxEXPAND, 0);
 	sizerEndFrame->Add(labelFrameEnd, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 12);
 	sizerEndFrame->Add(textFrameEnd, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
-	sizerLeft->Add(sizerEndFrame, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerLeft->Add(sizerEndFrame, 1, wxEXPAND, 0);
 	sizerLeft->Add(20, 10, 0, 0, 0);
 	sizerMainArea->Add(sizerLeft, 1, wxEXPAND, 0);
 	sizerMainArea->Add(verticalLine, 0, wxLEFT|wxRIGHT|wxEXPAND, 5);
 	sizerRight->Add(20, 20, 1, 0, 0);
 	sizerRightStart->Add(labelStartVal, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
 	sizerRightStart->Add(textStartVal, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
-	sizerRight->Add(sizerRightStart, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerRight->Add(sizerRightStart, 1, wxEXPAND, 0);
 	sizerRightEnd->Add(labelEndVal, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 9);
 	sizerRightEnd->Add(textEndVal, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 4);
-	sizerRight->Add(sizerRightEnd, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 0);
+	sizerRight->Add(sizerRightEnd, 1, wxEXPAND, 0);
 	sizerRight->Add(20, 20, 1, 0, 0);
 	sizerMainArea->Add(sizerRight, 1, wxEXPAND, 0);
 	sizerMainArea->Add(10, 20, 0, 0, 0);
diff --git a/src/gui/glPane.cpp b/src/gui/glPane.cpp
index 30b739a..75cf74a 100644
--- a/src/gui/glPane.cpp
+++ b/src/gui/glPane.cpp
@@ -103,12 +103,19 @@ BasicGLPane::BasicGLPane(wxWindow* parent) : wxGLCanvas(parent, wxID_ANY,  attri
 	lastMoveShiftDown=false;
 	selectionMode=false;
 	lastKeyFlags=lastMouseFlags=0;
+
+#ifdef __APPLE__
+	requireContextUpdate=false;
+#endif
+
 }
 
 BasicGLPane::~BasicGLPane()
 {
 	keyDoubleTapTimer->Stop();
 	delete keyDoubleTapTimer;
+	if(context)
+		delete context;
 }
 
 bool BasicGLPane::displaySupported() const
@@ -210,6 +217,13 @@ void BasicGLPane::forceRedraw()
 	wxPaintEvent ptEvent;
 	wxPostEvent(this,ptEvent);
 
+#ifdef WIN32
+	//Hack for windows. Does not redraw otherwise.
+	// Refresh and Update in tandom dont work.
+	Show(false);
+	Show(true);
+#endif
+
 }
 
 // some useful events to use
@@ -635,7 +649,7 @@ void BasicGLPane::keyPressed(wxKeyEvent& event)
 		}
 		break;
 		default:
-			event.Skip();
+			event.Skip(true);
 	}
 }
 
@@ -658,6 +672,7 @@ void BasicGLPane::keyReleased(wxKeyEvent& event)
 	if(event.ShiftDown())
 		cameraMoveRate*=5;
 
+	bool update=true;
 	switch(event.GetKeyCode())
 	{
 		case '-':
@@ -687,10 +702,12 @@ void BasicGLPane::keyReleased(wxKeyEvent& event)
 			break;
 		}
 		default:
-			event.Skip();
+			event.Skip(true);
+			update=false;
 	}
 
-	Refresh();
+	if(update)
+		Refresh();
 }
 
  
@@ -699,6 +716,10 @@ void BasicGLPane::resized(wxSizeEvent& evt)
 	prepare3DViewport(0,0,getWidth(),getHeight()); 
 	wxClientDC *dc=new wxClientDC(this);
 	Refresh();
+
+#ifdef __APPLE__
+	requireContextUpdate=true;
+#endif
 	delete dc;
 }
  
@@ -764,6 +785,9 @@ void BasicGLPane::render( wxPaintEvent& evt )
 	{
 		context = new wxGLContext(this);
 		SetCurrent(*context);
+#ifdef __APPLE__
+		requireContextUpdate=false;
+#endif	
 	}
 
 	if(!paneInitialised)
@@ -772,6 +796,19 @@ void BasicGLPane::render( wxPaintEvent& evt )
 		prepare3DViewport(0,0,getWidth(),getHeight()); 
 	}
 
+//Apple requires a context update on each resize, for some reason
+// https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_contexts/opengl_contexts.html
+//and
+// https://forums.wxwidgets.org/viewtopic.php?f=23&t=41592&p=168346
+#ifdef __APPLE__
+	if(requireContextUpdate)
+	{
+		SetCurrent(*context);
+		prepare3DViewport(0,0,getWidth(),getHeight()); 
+		requireContextUpdate=false;
+	}
+#endif
+
 	wxPaintDC(this); 
 	currentScene->draw();
 	glFlush();
@@ -1044,17 +1081,21 @@ bool BasicGLPane::saveImage(unsigned int width, unsigned int height,
 		//FIXME: HACK - using "blue screen" effect
 		//don't use background as mask colour.
 		// use depth buffer or gl alpha
-		const unsigned char mask[3] = {(unsigned char)rClear*255.0f,
-				(unsigned char)gClear*255.0f,(unsigned char)bClear*255.0f};
+		unsigned char clear[3];
+		clear[0] = (unsigned char)rClear*255.0f;
+		clear[1] = (unsigned char)gClear*255.0f;
+		clear[2] = (unsigned char)bClear*255.0f;
+		const unsigned char *mask = clear;
 		copyRGBAtoWXImage(width,height,imageBuffer,imageOverlay,mask);
 
 		free(imageBuffer);
 
 		combineWxImage(*image,imageOverlay);
+
+		//Free the tile buffer
+		trDelete(tr);
 	}
 
-	//Free the tile buffer
-	trDelete(tr);
 	
 	//--------------	
 	bool isOK=image->SaveFile(filename,wxBITMAP_TYPE_PNG);
diff --git a/src/gui/glPane.h b/src/gui/glPane.h
index 015ccf0..63031c0 100644
--- a/src/gui/glPane.h
+++ b/src/gui/glPane.h
@@ -36,7 +36,12 @@ private:
 
 	wxStatusBar *parentStatusBar;
 	wxTimer *parentStatusTimer;
-	unsigned int statusDelay;	
+	unsigned int statusDelay;
+
+#ifdef __APPLE__ 
+	bool requireContextUpdate;
+#endif
+	
 	//In some implementation of openGL in wx. 
 	//calling GL funcs before Paint() will crash program
 	bool paneInitialised;
diff --git a/src/gui/glade-skeleton/mainWindow.wxg b/src/gui/glade-skeleton/mainWindow.wxg
index 6d588bd..ce4a8e9 100644
--- a/src/gui/glade-skeleton/mainWindow.wxg
+++ b/src/gui/glade-skeleton/mainWindow.wxg
@@ -1,15 +1,16 @@
 <?xml version="1.0"?>
-<!-- generated by wxGlade 0.6.5 on Sun Jun  9 13:07:46 2013 -->
+<!-- generated by wxGlade 0.7.1 on Fri Mar 18 00:04:02 2016 -->
 
-<application path="/home/user/Desktop/3Depict/src/glade-skeleton/3Depict.cpp" name="quick3d" class="quick3dApp" option="0" language="C++" top_window="MainFrame" encoding="ISO-8859-1" use_gettext="1" overwrite="1" use_new_namespace="1" for_version="2.8" is_template="0" indent_amount="4" indent_symbol="space" source_extension=".cpp" header_extension=".h">
+<application class="" encoding="ISO-8859-1" for_version="3.0" header_extension=".h" indent_amount="4" indent_symbol="space" is_template="0" language="C++" name="" option="0" overwrite="1" path="/home/pcuser/code/3Depict/src/gui/glade-skeleton/3Depict.cpp" source_extension=".cpp" top_window="MainFrame" use_gettext="1" use_new_namespace="1">
     <object class="MainWindowFrame" name="MainFrame" base="EditFrame">
-        <extracode>enum {\nID_COMBO_SETTINGS = wxID_ANY+1,\nID_FILE_EXIT,\nID_FILE_OPEN,\nID_FILE_SAVE,\nID_FILE_SAVEAS,\nID_HELP_ABOUT,\nID_HELP_HELP,\nID_NOTEBOOK_CONTROL,\nID_NOTE_CAMERA,\nID_NOTE_DATA,\nID_NOTE_PERFORMANCE,\nID_NOTE_TOOLS,\nID_NOTE_VISUALISATION,\nID_PANEL_DATA,\nID_PANEL_VIEW,\nID_SPLIT_LEFTRIGHT,\nID_SPLIT_TOP_BOTTOM,\nID_NOTE_SPECTRA,\nID_NOTE_RAW,\n};</extracode>
+        <extracode>//Constant identifiers for binding events in wxwidgets "event table"\n  enum {\n  \n      //File menu\n      ID_MAIN_WINDOW= wxID_ANY+1,\n  \n      ID_FILE_EXIT,\n      ID_FILE_OPEN,\n      ID_FILE_MERGE,\n      ID_FILE_SAVE,\n      ID_FILE_SAVEAS,\n      ID_FILE_EXPORT_PLOT,\n      ID_FILE_EXPORT_IMAGE,\n      ID_FILE_EXPORT_IONS,\n      ID_FILE_EXPORT_RANGE,\n      ID_FILE_EXPORT_ANIMATION,\n      ID_FILE_EXPORT_FILTER_ANIMATION,\n      ID_FILE_EXPORT_PACKAGE,\n  \n  [...]
         <style>wxDEFAULT_FRAME_STYLE</style>
-        <title>Quick 3D</title>
+        <title>3Depict</title>
         <menubar>1</menubar>
+        <statusbar>1</statusbar>
         <object class="wxMenuBar" name="MainFrame_Menu" base="EditMenuBar">
             <menus>
-                <menu name="File" itemid="ID_FILE_MENU" label="&File">
+                <menu itemid="ID_FILE_MENU" label="&File" name="File">
                     <item>
                         <label>&Open...\tCtrl+O</label>
                         <id>ID_FILE_OPEN</id>
@@ -18,6 +19,13 @@
                         <handler>OnFileOpen</handler>
                     </item>
                     <item>
+                        <label>&Merge...\tShift+Ctrl+O</label>
+                        <id>ID_FILE_MERGE</id>
+                        <name>Merge</name>
+                        <help_str>"Merge other file"</help_str>
+                        <handler>OnFileMerge</handler>
+                    </item>
+                    <item>
                         <label>&Save\tCtrl+s</label>
                         <id>ID_FILE_SAVE</id>
                         <name>Save</name>
@@ -36,34 +44,33 @@
                         <id>---</id>
                         <name>---</name>
                     </item>
-                    <menu name="FileExport" label="&Export">
+                    <menu label="&Export" name="FileExport">
                         <item>
                             <label>&Plot...\tCtrl+P</label>
+                            <id>ID_FILE_EXPORT_PLOT</id>
                             <help_str>Export Current Plot</help_str>
                             <handler>OnFileExportPlot</handler>
                         </item>
                         <item>
                             <label>&Image...\tCtrl+I</label>
+                            <id>ID_FILE_EXPORT_IMAGE</id>
                             <help_str>Export Current 3D View</help_str>
                             <handler>OnFileExportImage</handler>
                         </item>
                         <item>
                             <label>Ion&s...\tCtrl+N</label>
+                            <id>ID_FILE_EXPORT_IONS</id>
                             <help_str>Export Ion Data</help_str>
                             <handler>OnFileExportIons</handler>
                         </item>
                         <item>
                             <label>&Ranges...\tCtrl+R</label>
+                            <id>ID_FILE_EXPORT_RANGE</id>
                             <help_str>Export Range Data</help_str>
                             <handler>OnFileExportRange</handler>
                         </item>
                     </menu>
                     <item>
-                        <label>---</label>
-                        <id>---</id>
-                        <name>---</name>
-                    </item>
-                    <item>
                         <label>E&xit</label>
                         <id>ID_FILE_EXIT</id>
                         <name>Exit</name>
@@ -71,9 +78,48 @@
                         <handler>OnFileExit</handler>
                     </item>
                 </menu>
-                <menu name="" label="View">
+                <menu itemid="ID_MENU_EDIT" label="Edit" name="menuEdit">
+                    <item>
+                        <label>Undo</label>
+                        <id>ID_MENU_EDIT_UNDO</id>
+                        <name>menuEditUndo</name>
+                        <handler>OnEditUndo</handler>
+                    </item>
+                    <item>
+                        <label>Redo</label>
+                        <id>ID_MENU_EDIT_REDO</id>
+                        <name>menuEditRedo</name>
+                        <handler>OnEditRedo</handler>
+                    </item>
+                    <item>
+                        <label>---</label>
+                        <id>---</id>
+                        <name>---</name>
+                    </item>
                     <item>
-                        <label>Background Colour...</label>
+                        <label>Range</label>
+                        <id>ID_EDIT_RANGE</id>
+                        <name>menuEditRange</name>
+                        <handler>OnEditRange</handler>
+                    </item>
+                    <item>
+                        <label>---</label>
+                        <id>---</id>
+                        <name>---</name>
+                    </item>
+                    <item>
+                        <label>Preferences</label>
+                        <id>ID_MENU_EDIT_PREFERENCES</id>
+                        <name>menuEditPreferences</name>
+                        <handler>OnEditPreferences</handler>
+                    </item>
+                </menu>
+                <menu label="View" name="">
+                    <item>
+                        <label>&Background Colour...\tCtrl+B</label>
+                        <id>ID_VIEW_BACKGROUND,</id>
+                        <help_str>Change background colour</help_str>
+                        <handler>OnViewBackground</handler>
                     </item>
                     <item>
                         <label>---</label>
@@ -111,7 +157,7 @@
                         <label>Fullscreen</label>
                     </item>
                 </menu>
-                <menu name="Help" itemid="ID_HELP" label="Help">
+                <menu itemid="ID_HELP" label="Help" name="Help">
                     <item>
                         <label>&Help...</label>
                         <id>ID_HELP_HELP</id>
@@ -120,6 +166,12 @@
                         <handler>OnHelpHelp</handler>
                     </item>
                     <item>
+                        <label>&Contact...</label>
+                        <id>ID_HELP_CONTACT</id>
+                        <help_str>Open contact page</help_str>
+                        <handler>OnHelpContact</handler>
+                    </item>
+                    <item>
                         <label>---</label>
                         <id>---</id>
                         <name>---</name>
@@ -134,6 +186,11 @@
                 </menu>
             </menus>
         </object>
+        <object class="wxStatusBar" name="MainFrame_statusbar" base="EditStatusBar">
+            <fields>
+                <field width="-1">MainFrame_statusbar</field>
+            </fields>
+        </object>
         <object class="wxBoxSizer" name="topSizer" base="EditBoxSizer">
             <orient>wxHORIZONTAL</orient>
             <object class="sizeritem">
@@ -195,18 +252,22 @@
                                                             <choices>
                                                             </choices>
                                                             <events>
-                                                                <handler event="EVT_COMBOBOX">OnComboSettings</handler>
-                                                                <handler event="EVT_TEXT">OnComboSettingsText</handler>
-                                                                <handler event="EVT_TEXT_ENTER">OnComboSettingsEnter</handler>
+                                                                <handler event="EVT_COMBOBOX">OnComboStash</handler>
+                                                                <handler event="EVT_TEXT">OnComboStashText</handler>
+                                                                <handler event="EVT_TEXT_ENTER">OnComboStashEnter</handler>
                                                             </events>
                                                         </object>
                                                     </object>
                                                     <object class="sizeritem">
-                                                        <flag>wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL</flag>
+                                                        <flag>wxALIGN_CENTER</flag>
                                                         <border>0</border>
                                                         <option>0</option>
                                                         <object class="wxButton" name="btnStashManage" base="EditButton">
                                                             <label>...</label>
+                                                            <id>ID_BTN_STASH_MANAGE,</id>
+                                                            <events>
+                                                                <handler event="EVT_BUTTON">OnButtonStashDialog</handler>
+                                                            </events>
                                                         </object>
                                                     </object>
                                                 </object>
@@ -283,11 +344,12 @@
                                                                             <id>ID_TREE_FILTERS</id>
                                                                             <events>
                                                                                 <handler event="EVT_TREE_BEGIN_DRAG">OnTreeBeginDrag</handler>
-                                                                                <handler event="EVT_TREE_END_DRAG">OnTreeEndDrag</handler>
                                                                                 <handler event="EVT_TREE_DELETE_ITEM">OnTreeDeleteItem</handler>
-                                                                                <handler event="EVT_TREE_SEL_CHANGED">OnTreeSelectionChange</handler>
-                                                                                <handler event="EVT_TREE_KEY_DOWN">OnTreeKeyDown</handler>
+                                                                                <handler event="EVT_TREE_END_DRAG">OnTreeEndDrag</handler>
                                                                                 <handler event="EVT_TREE_ITEM_GETTOOLTIP">OnTreeItemTooltip</handler>
+                                                                                <handler event="EVT_TREE_KEY_DOWN">OnTreeKeyDown</handler>
+                                                                                <handler event="EVT_TREE_SEL_CHANGED">OnTreeSelectionChange</handler>
+                                                                                <handler event="EVT_TREE_SEL_CHANGING">OnTreeSelectionPreChange</handler>
                                                                             </events>
                                                                         </object>
                                                                     </object>
@@ -476,6 +538,112 @@
                                                     </columns>
                                                 </object>
                                             </object>
+                                            <object class="sizeritem">
+                                                <border>0</border>
+                                                <option>1</option>
+                                                <object class="wxStaticBoxSizer" name="sizerAlignCam" base="EditStaticBoxSizer">
+                                                    <orient>wxVERTICAL</orient>
+                                                    <label>Align Camera</label>
+                                                    <object class="sizeritem">
+                                                        <border>0</border>
+                                                        <option>0</option>
+                                                        <object class="wxBoxSizer" name="sizerCamAlignPlus" base="EditBoxSizer">
+                                                            <orient>wxHORIZONTAL</orient>
+                                                            <object class="sizeritem">
+                                                                <flag>wxALL|wxALIGN_CENTER</flag>
+                                                                <border>5</border>
+                                                                <option>0</option>
+                                                                <object class="wxButton" name="buttonAlignCamXPlus" base="EditButton">
+                                                                    <label>X+</label>
+                                                                    <tooltip>Align camera view to this axis</tooltip>
+                                                                    <id>ID_BUTTON_ALIGNCAM_XPLUS</id>
+                                                                    <events>
+                                                                        <handler event="EVT_BUTTON">OnButtonAlignCameraXPlus</handler>
+                                                                    </events>
+                                                                </object>
+                                                            </object>
+                                                            <object class="sizeritem">
+                                                                <flag>wxALL|wxALIGN_CENTER</flag>
+                                                                <border>5</border>
+                                                                <option>0</option>
+                                                                <object class="wxButton" name="buttonAlignCamYPlus" base="EditButton">
+                                                                    <label>Y+</label>
+                                                                    <id>ID_BUTTON_ALIGNCAM_YPLUS</id>
+                                                                    <events>
+                                                                        <handler event="EVT_BUTTON">OnButtonAlignCameraYPlus</handler>
+                                                                    </events>
+                                                                </object>
+                                                            </object>
+                                                            <object class="sizeritem">
+                                                                <flag>wxALL|wxALIGN_CENTER</flag>
+                                                                <border>5</border>
+                                                                <option>0</option>
+                                                                <object class="wxButton" name="buttonAlignCamZPlus" base="EditButton">
+                                                                    <label>Z+</label>
+                                                                    <id>ID_BUTTON_ALIGNCAM_ZPLUS</id>
+                                                                    <events>
+                                                                        <handler event="EVT_BUTTON">OnButtonAlignCameraZPlus</handler>
+                                                                    </events>
+                                                                </object>
+                                                            </object>
+                                                        </object>
+                                                    </object>
+                                                    <object class="sizeritem">
+                                                        <flag>wxALIGN_CENTER</flag>
+                                                        <border>0</border>
+                                                        <option>0</option>
+                                                        <object class="wxBoxSizer" name="sizerCamAlignMinus" base="EditBoxSizer">
+                                                            <orient>wxHORIZONTAL</orient>
+                                                            <object class="sizeritem">
+                                                                <flag>wxALL|wxALIGN_CENTER</flag>
+                                                                <border>5</border>
+                                                                <option>0</option>
+                                                                <object class="wxButton" name="buttonAlignCamXMinus" base="EditButton">
+                                                                    <label>X-</label>
+                                                                    <id>ID_BUTTON_ALIGNCAM_XMINUS</id>
+                                                                    <events>
+                                                                        <handler event="EVT_BUTTON">OnButtonAlignCameraXMinus</handler>
+                                                                    </events>
+                                                                </object>
+                                                            </object>
+                                                            <object class="sizeritem">
+                                                                <flag>wxALL|wxALIGN_CENTER</flag>
+                                                                <border>5</border>
+                                                                <option>0</option>
+                                                                <object class="wxButton" name="buttonAlignCamYMinus" base="EditButton">
+                                                                    <label>Y-</label>
+                                                                    <id>ID_BUTTON_ALIGNCAM_YMINUS</id>
+                                                                    <events>
+                                                                        <handler event="EVT_BUTTON">OnButtonAlignCameraYMinus</handler>
+                                                                    </events>
+                                                                </object>
+                                                            </object>
+                                                            <object class="sizeritem">
+                                                                <flag>wxALL|wxALIGN_CENTER</flag>
+                                                                <border>5</border>
+                                                                <option>0</option>
+                                                                <object class="wxButton" name="buttonAlignCamZMinus" base="EditButton">
+                                                                    <label>Z-</label>
+                                                                    <id>ID_BUTTON_ALIGNCAM_ZMINUS</id>
+                                                                    <events>
+                                                                        <handler event="EVT_BUTTON">OnButtonAlignCameraZMinus</handler>
+                                                                    </events>
+                                                                </object>
+                                                            </object>
+                                                        </object>
+                                                    </object>
+                                                    <object class="sizeritem">
+                                                        <flag>wxALL|wxALIGN_CENTER</flag>
+                                                        <border>4</border>
+                                                        <option>0</option>
+                                                        <object class="wxCheckBox" name="checkAlignCamResize" base="EditCheckBox">
+                                                            <style>wxALIGN_RIGHT</style>
+                                                            <label>Resize to Fit</label>
+                                                            <tooltip>Resize view to fit 3D data</tooltip>
+                                                        </object>
+                                                    </object>
+                                                </object>
+                                            </object>
                                         </object>
                                     </object>
                                     <object class="wxPanel" name="notePost" base="EditPanel">
@@ -527,6 +695,9 @@
                                                                 <option>0</option>
                                                                 <object class="wxCheckBox" name="checkFxCropCameraFrame" base="EditCheckBox">
                                                                     <label>Use camera coordinate frame</label>
+                                                                    <events>
+                                                                        <handler event="EVT_CHECKBOX">OnFxCropCamFrame</handler>
+                                                                    </events>
                                                                 </object>
                                                             </object>
                                                             <object class="sizeritem">
@@ -536,7 +707,7 @@
                                                                 <object class="wxBoxSizer" name="cropFxBodyCentreSizer" base="EditBoxSizer">
                                                                     <orient>wxHORIZONTAL</orient>
                                                                     <object class="sizeritem">
-                                                                        <flag>wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL</flag>
+                                                                        <flag>wxEXPAND|wxALIGN_CENTER</flag>
                                                                         <border>0</border>
                                                                         <option>1</option>
                                                                         <object class="wxBoxSizer" name="sizerFxCropLHS" base="EditBoxSizer">
@@ -563,19 +734,19 @@
                                                                                 </object>
                                                                             </object>
                                                                             <object class="sizeritem">
-                                                                                <flag>wxRIGHT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxSHAPED</flag>
+                                                                                <flag>wxRIGHT|wxEXPAND|wxALIGN_CENTER|wxSHAPED</flag>
                                                                                 <border>5</border>
                                                                                 <option>1</option>
                                                                                 <object class="wxPanel" name="panelFxCropOne" base="EditPanel">
                                                                                     <style>wxTAB_TRAVERSAL</style>
-                                                                                    <background>#54fff4</background>
                                                                                     <id>ID_EFFECT_CROP_PANELONE_COMBO</id>
+                                                                                    <background>#54fff4</background>
                                                                                 </object>
                                                                             </object>
                                                                         </object>
                                                                     </object>
                                                                     <object class="sizeritem">
-                                                                        <flag>wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL</flag>
+                                                                        <flag>wxEXPAND|wxALIGN_CENTER</flag>
                                                                         <border>0</border>
                                                                         <option>1</option>
                                                                         <object class="wxBoxSizer" name="sizerFxCropRHS" base="EditBoxSizer">
@@ -602,13 +773,13 @@
                                                                                 </object>
                                                                             </object>
                                                                             <object class="sizeritem">
-                                                                                <flag>wxLEFT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxSHAPED</flag>
+                                                                                <flag>wxLEFT|wxEXPAND|wxALIGN_CENTER|wxSHAPED</flag>
                                                                                 <border>5</border>
                                                                                 <option>1</option>
                                                                                 <object class="wxPanel" name="panelFxCropTwo" base="EditPanel">
                                                                                     <style>wxTAB_TRAVERSAL</style>
-                                                                                    <background>#ff4fe2</background>
                                                                                     <id>ID_EFFECT_CROP_PANELTWO_COMBO</id>
+                                                                                    <background>#ff4fe2</background>
                                                                                 </object>
                                                                             </object>
                                                                         </object>
@@ -616,7 +787,7 @@
                                                                 </object>
                                                             </object>
                                                             <object class="sizeritem">
-                                                                <flag>wxBOTTOM|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL</flag>
+                                                                <flag>wxBOTTOM|wxEXPAND|wxALIGN_CENTER</flag>
                                                                 <border>5</border>
                                                                 <option>0</option>
                                                                 <object class="wxFlexGridSizer" name="sizerFxCropGridLow" base="EditFlexGridSizer">
@@ -783,6 +954,9 @@
                                                                 <object class="wxCheckBox" name="checkFxStereoLensFlip" base="EditCheckBox">
                                                                     <label>Flip Channels</label>
                                                                     <tooltip>Reverse output 3D channels (to negate a flip in 3D lens layout)</tooltip>
+                                                                    <events>
+                                                                        <handler event="EVT_CHECKBOX">OnFxStereoLensFlip</handler>
+                                                                    </events>
                                                                 </object>
                                                             </object>
                                                         </object>
@@ -810,6 +984,10 @@
                                                 <option>0</option>
                                                 <object class="wxCheckBox" name="checkAlphaBlend" base="EditCheckBox">
                                                     <label>Smooth & translucent objects</label>
+                                                    <id>ID_CHECK_ALPHA,</id>
+                                                    <events>
+                                                        <handler event="EVT_CHECKBOX">OnCheckAlpha</handler>
+                                                    </events>
                                                 </object>
                                             </object>
                                             <object class="sizeritem">
@@ -818,6 +996,10 @@
                                                 <option>0</option>
                                                 <object class="wxCheckBox" name="checkLighting" base="EditCheckBox">
                                                     <label>3D lighting</label>
+                                                    <id>ID_CHECK_LIGHTING</id>
+                                                    <events>
+                                                        <handler event="EVT_CHECKBOX">OnCheckLighting</handler>
+                                                    </events>
                                                 </object>
                                             </object>
                                             <object class="sizeritem">
@@ -844,6 +1026,10 @@
                                                 <option>0</option>
                                                 <object class="wxCheckBox" name="checkWeakRandom" base="EditCheckBox">
                                                     <label>Fast and weak randomisation</label>
+                                                    <id>ID_CHECK_WEAKRANDOM</id>
+                                                    <events>
+                                                        <handler event="EVT_CHECKBOX">OnCheckWeakRandom</handler>
+                                                    </events>
                                                 </object>
                                             </object>
                                             <object class="sizeritem">
@@ -860,6 +1046,9 @@
                                                             <checked>1</checked>
                                                             <label>Limit Output Pts</label>
                                                             <tooltip>Limit the number of points in the 3D view</tooltip>
+                                                            <events>
+                                                                <handler event="EVT_CHECKBOX">OnCheckLimitOutput</handler>
+                                                            </events>
                                                         </object>
                                                     </object>
                                                     <object class="sizeritem">
@@ -870,6 +1059,7 @@
                                                             <value>2000000</value>
                                                             <events>
                                                                 <handler event="EVT_TEXT">OnTextLimitOutput</handler>
+                                                                <handler event="EVT_TEXT_ENTER">OnTextLimitOutputEnter</handler>
                                                             </events>
                                                         </object>
                                                     </object>
@@ -881,6 +1071,9 @@
                                                 <option>0</option>
                                                 <object class="wxCheckBox" name="checkCaching" base="EditCheckBox">
                                                     <label>Filter caching</label>
+                                                    <events>
+                                                        <handler event="EVT_CHECKBOX">OnCheckCacheEnable</handler>
+                                                    </events>
                                                 </object>
                                             </object>
                                             <object class="sizeritem">
@@ -904,6 +1097,9 @@
                                                         <object class="wxSpinCtrl" name="spinCachePercent" base="EditSpinCtrl">
                                                             <range>0, 100</range>
                                                             <value>50</value>
+                                                            <events>
+                                                                <handler event="EVT_SPINCTRL">OnCacheRamUsageSpin</handler>
+                                                            </events>
                                                         </object>
                                                     </object>
                                                 </object>
diff --git a/src/gui/mainFrame.cpp b/src/gui/mainFrame.cpp
index 25b6858..1700900 100644
--- a/src/gui/mainFrame.cpp
+++ b/src/gui/mainFrame.cpp
@@ -161,7 +161,7 @@ const unsigned int comboFiltersTypeMapping[FILTER_DROP_COUNT] = {
 	FILTER_TYPE_BOUNDBOX,
 	FILTER_TYPE_IONCLIP,
 	FILTER_TYPE_CLUSTER_ANALYSIS,
-	FILTER_TYPE_COMPOSITION,
+	FILTER_TYPE_PROFILE,
 	FILTER_TYPE_IONDOWNSAMPLE,
 	FILTER_TYPE_EXTERNALPROC,
 	FILTER_TYPE_IONCOLOURFILTER,
@@ -177,115 +177,123 @@ const unsigned int comboFiltersTypeMapping[FILTER_DROP_COUNT] = {
 
 //Constant identifiers for binding events in wxwidgets "event table"
 enum {
-    
-    //File menu
-    ID_MAIN_WINDOW= wxID_ANY+1,
-
-    ID_FILE_EXIT,
-    ID_FILE_OPEN,
-    ID_FILE_MERGE,
-    ID_FILE_SAVE,
-    ID_FILE_SAVEAS,
-    ID_FILE_EXPORT_PLOT,
-    ID_FILE_EXPORT_IMAGE,
-    ID_FILE_EXPORT_IONS,
-    ID_FILE_EXPORT_RANGE,
-    ID_FILE_EXPORT_ANIMATION,
-    ID_FILE_EXPORT_FILTER_ANIMATION,
-    ID_FILE_EXPORT_PACKAGE,
-
-    //Edit menu
-    ID_EDIT_UNDO,
-    ID_EDIT_REDO,
-    ID_EDIT_RANGE,
-    ID_EDIT_PREFERENCES,
-
-    //Help menu
-    ID_HELP_ABOUT,
-    ID_HELP_HELP,
-    ID_HELP_CONTACT,
-
-    //View menu
-    ID_VIEW_BACKGROUND,
-    ID_VIEW_CONTROL_PANE,
-    ID_VIEW_RAW_DATA_PANE,
-    ID_VIEW_SPECTRA,
-    ID_VIEW_PLOT_LEGEND,
-    ID_VIEW_WORLDAXIS,
-    ID_VIEW_FULLSCREEN,
-    //Left hand note pane
-    ID_NOTEBOOK_CONTROL,
-    ID_NOTE_CAMERA,
-    ID_NOTE_DATA,
-    ID_NOTE_PERFORMANCE,
-    ID_NOTE_TOOLS,
-    ID_NOTE_VISUALISATION,
-    //Lower pane
-    ID_PANEL_DATA,
-    ID_PANEL_VIEW,
-    ID_NOTE_SPECTRA,
-    ID_NOTE_RAW,
-    ID_GRID_RAW_DATA,
-    ID_BUTTON_GRIDCOPY,
-    ID_LIST_PLOTS,
-
-    //Splitter IDs
-    ID_SPLIT_LEFTRIGHT,
-    ID_SPLIT_FILTERPROP,
-    ID_SPLIT_TOP_BOTTOM,
-    ID_SPLIT_SPECTRA,
-    ID_RAWDATAPANE_SPLIT,
-    ID_CONTROLPANE_SPLIT,
-   
-    //Camera panel 
-    ID_COMBO_CAMERA,
-    ID_GRID_CAMERA_PROPERTY,
-   
-    //Filter panel 
-    ID_COMBO_FILTER,
-    ID_COMBO_STASH,
-    ID_BTN_STASH_MANAGE,
-    ID_CHECK_AUTOUPDATE,
-    ID_FILTER_NAMES,
-    ID_GRID_FILTER_PROPERTY,
-    ID_LIST_FILTER,
-    ID_TREE_FILTERS,
-    ID_BUTTON_REFRESH,
-    ID_BTN_EXPAND,
-    ID_BTN_COLLAPSE,
-    ID_BTN_FILTERTREE_ERRS,
-
-    //Effects panel
-    ID_EFFECT_ENABLE,
-    ID_EFFECT_CROP_ENABLE,
-    ID_EFFECT_CROP_AXISONE_COMBO,
-    ID_EFFECT_CROP_PANELONE,
-    ID_EFFECT_CROP_PANELTWO,
-    ID_EFFECT_CROP_AXISTWO_COMBO,
-    ID_EFFECT_CROP_CHECK_COORDS,
-    ID_EFFECT_CROP_TEXT_DX,
-    ID_EFFECT_CROP_TEXT_DY,
-    ID_EFFECT_CROP_TEXT_DZ,
-    ID_EFFECT_STEREO_ENABLE,
-    ID_EFFECT_STEREO_COMBO,
-    ID_EFFECT_STEREO_BASELINE_SLIDER,
-    ID_EFFECT_STEREO_LENSFLIP,
-
-    //Options panel
-    ID_CHECK_ALPHA,
-    ID_CHECK_LIGHTING,
-    ID_CHECK_LIMIT_POINT_OUT,
-    ID_TEXT_LIMIT_POINT_OUT,
-    ID_CHECK_CACHING,
-    ID_CHECK_WEAKRANDOM,
-    ID_SPIN_CACHEPERCENT,
-    	
-    //Misc
-    ID_PROGRESS_ABORT,
-    ID_STATUS_TIMER,
-    ID_PROGRESS_TIMER,
-    ID_UPDATE_TIMER,
-    ID_AUTOSAVE_TIMER,
+
+	//File menu
+	ID_MAIN_WINDOW= wxID_ANY+1000, // There is a bug under MSW where wxID_ANY+1 causes collisions with some controls with implicit IDs...
+
+	ID_FILE_EXIT,
+	ID_FILE_OPEN,
+	ID_FILE_MERGE,
+	ID_FILE_SAVE,
+	ID_FILE_SAVEAS,
+	ID_FILE_EXPORT_PLOT,
+	ID_FILE_EXPORT_IMAGE,
+	ID_FILE_EXPORT_IONS,
+	ID_FILE_EXPORT_RANGE,
+	ID_FILE_EXPORT_ANIMATION,
+	ID_FILE_EXPORT_FILTER_ANIMATION,
+	ID_FILE_EXPORT_PACKAGE,
+
+	//Edit menu
+	ID_EDIT_UNDO,
+	ID_EDIT_REDO,
+	ID_EDIT_RANGE,
+	ID_EDIT_PREFERENCES,
+
+	//Help menu
+	ID_HELP_ABOUT,
+	ID_HELP_HELP,
+	ID_HELP_CONTACT,
+
+	//View menu
+	ID_VIEW_BACKGROUND,
+	ID_VIEW_CONTROL_PANE,
+	ID_VIEW_RAW_DATA_PANE,
+	ID_VIEW_SPECTRA,
+	ID_VIEW_PLOT_LEGEND,
+	ID_VIEW_WORLDAXIS,
+	ID_VIEW_FULLSCREEN,
+	//Left hand note pane
+	ID_NOTEBOOK_CONTROL,
+	ID_NOTE_CAMERA,
+	ID_NOTE_DATA,
+	ID_NOTE_PERFORMANCE,
+	ID_NOTE_TOOLS,
+	ID_NOTE_VISUALISATION,
+	//Lower pane
+	ID_PANEL_DATA,
+	ID_PANEL_VIEW,
+	ID_NOTE_SPECTRA,
+	ID_NOTE_RAW,
+	ID_GRID_RAW_DATA,
+	ID_BUTTON_GRIDCOPY,
+	ID_LIST_PLOTS,
+
+	//Splitter IDs
+	ID_SPLIT_LEFTRIGHT,
+	ID_SPLIT_FILTERPROP,
+	ID_SPLIT_TOP_BOTTOM,
+	ID_SPLIT_SPECTRA,
+	ID_RAWDATAPANE_SPLIT,
+	ID_CONTROLPANE_SPLIT,
+
+	//Camera panel 
+	ID_COMBO_CAMERA,
+	ID_GRID_CAMERA_PROPERTY,
+	ID_BUTTON_ALIGNCAM_XMINUS,
+	ID_BUTTON_ALIGNCAM_XPLUS,
+	ID_BUTTON_ALIGNCAM_YMINUS,
+	ID_BUTTON_ALIGNCAM_YPLUS,
+	ID_BUTTON_ALIGNCAM_ZMINUS,
+	ID_BUTTON_ALIGNCAM_ZPLUS,
+
+
+
+	//Filter panel 
+	ID_COMBO_FILTER,
+	ID_COMBO_STASH,
+	ID_BTN_STASH_MANAGE,
+	ID_CHECK_AUTOUPDATE,
+	ID_FILTER_NAMES,
+	ID_GRID_FILTER_PROPERTY,
+	ID_LIST_FILTER,
+	ID_TREE_FILTERS,
+	ID_BUTTON_REFRESH,
+	ID_BTN_EXPAND,
+	ID_BTN_COLLAPSE,
+	ID_BTN_FILTERTREE_ERRS,
+
+	//Effects panel
+	ID_EFFECT_ENABLE,
+	ID_EFFECT_CROP_ENABLE,
+	ID_EFFECT_CROP_AXISONE_COMBO,
+	ID_EFFECT_CROP_PANELONE,
+	ID_EFFECT_CROP_PANELTWO,
+	ID_EFFECT_CROP_AXISTWO_COMBO,
+	ID_EFFECT_CROP_CHECK_COORDS,
+	ID_EFFECT_CROP_TEXT_DX,
+	ID_EFFECT_CROP_TEXT_DY,
+	ID_EFFECT_CROP_TEXT_DZ,
+	ID_EFFECT_STEREO_ENABLE,
+	ID_EFFECT_STEREO_COMBO,
+	ID_EFFECT_STEREO_BASELINE_SLIDER,
+	ID_EFFECT_STEREO_LENSFLIP,
+
+	//Options panel
+	ID_CHECK_ALPHA,
+	ID_CHECK_LIGHTING,
+	ID_CHECK_LIMIT_POINT_OUT,
+	ID_TEXT_LIMIT_POINT_OUT,
+	ID_CHECK_CACHING,
+	ID_CHECK_WEAKRANDOM,
+	ID_SPIN_CACHEPERCENT,
+
+	//Misc
+	ID_PROGRESS_ABORT,
+	ID_STATUS_TIMER,
+	ID_PROGRESS_TIMER,
+	ID_UPDATE_TIMER,
+	ID_AUTOSAVE_TIMER,
 
 
 };
@@ -390,6 +398,7 @@ MainWindowFrame::MainWindowFrame(wxWindow* parent, int id, const wxString& title
 	verCheckThread=0;
 	refreshThread=0;
 	refreshControl=0;
+	ensureResultVisible=false;
 	lastProgressData.reset();
 
 	//Set up the program icon handler
@@ -607,6 +616,13 @@ TRANS("Unable to initialise the openGL (3D) panel. Program cannot start. Please
     cameraNamePropertySepStaticLine = new wxStaticLine(noteCamera, wxID_ANY);
     gridCameraProperties = new wxPropertyGrid(noteCamera,ID_GRID_CAMERA_PROPERTY,
 					wxDefaultPosition,wxDefaultSize,PROPERTY_GRID_STYLE);
+    buttonAlignCamXPlus = new wxButton(noteCamera, ID_BUTTON_ALIGNCAM_XPLUS, "X+");
+    buttonAlignCamYPlus = new wxButton(noteCamera, ID_BUTTON_ALIGNCAM_YPLUS, "Y+");
+    buttonAlignCamZPlus = new wxButton(noteCamera, ID_BUTTON_ALIGNCAM_ZPLUS, "Z+");
+    buttonAlignCamXMinus = new wxButton(noteCamera, ID_BUTTON_ALIGNCAM_XMINUS, "X-");
+    buttonAlignCamYMinus = new wxButton(noteCamera, ID_BUTTON_ALIGNCAM_YMINUS, "Y-");
+    buttonAlignCamZMinus = new wxButton(noteCamera, ID_BUTTON_ALIGNCAM_ZMINUS, "Z-");
+    checkAlignCamResize = new wxCheckBox(noteCamera, wxID_ANY, _("Resize to Fit"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
 #ifndef APPLE_EFFECTS_WORKAROUND
     checkPostProcessing = new wxCheckBox(notePost, ID_EFFECT_ENABLE, TRANS("3D Post-processing"));
 #endif
@@ -662,7 +678,6 @@ TRANS("Unable to initialise the openGL (3D) panel. Program cannot start. Please
     checkWeakRandom = new wxCheckBox(noteTools, ID_CHECK_WEAKRANDOM, TRANS("Fast and weak randomisation."));
     checkWeakRandom->SetValue(true);
     checkLimitOutput = new wxCheckBox(noteTools, ID_CHECK_LIMIT_POINT_OUT, TRANS("Limit Output Pts"));
- //   checkLimitOutput->SetValue((visControl.getIonDisplayLimit() !=0));
     std::string tmpStr;
 //    stream_cast(tmpStr,visControl.getIonDisplayLimit());
     textLimitOutput = new wxTextCtrl(noteTools, ID_TEXT_LIMIT_POINT_OUT, (tmpStr),
@@ -685,9 +700,10 @@ TRANS("Unable to initialise the openGL (3D) panel. Program cannot start. Please
 
     set_properties();
     do_layout();
-
+#ifdef FIX_WXPROPGRID_16222
     backCameraPropGrid=0;
     backFilterPropGrid=0;
+#endif
     //Disable post-processing
 #ifndef APPLE_EFFECTS_WORKAROUND
     checkPostProcessing->SetValue(false); 
@@ -754,7 +770,16 @@ TRANS("Unable to initialise the openGL (3D) panel. Program cannot start. Please
 	initedOK=true;   
 
 
-
+	// Set the limit value checkbox and text field with the
+	// value obtained from the configuration file
+	unsigned int ionLimit=visControl.getIonDisplayLimit(); 
+	checkLimitOutput->SetValue((ionLimit!=0));
+	if(ionLimit)
+	{
+		std::string sValue;
+		stream_cast(sValue,visControl.getIonDisplayLimit());
+		textLimitOutput->SetValue(sValue);
+	}	
 
 
 
@@ -796,6 +821,7 @@ MainWindowFrame::~MainWindowFrame()
 	delete statusTimer;
 	delete updateTimer;
 	delete autoSaveTimer;
+	delete progressTimer;
 
 	//delete the file history  pointer
 	delete recentHistory;
@@ -807,10 +833,11 @@ MainWindowFrame::~MainWindowFrame()
 
 	//wxwidgets can crash if objects are ->Connect-ed  in 
 	// wxWindowBase::DestroyChildren(), so Disconnect before destructing
-    comboCamera->Unbind(wxEVT_SET_FOCUS, &MainWindowFrame::OnComboCameraSetFocus, this);
-    comboStash->Unbind(wxEVT_SET_FOCUS, &MainWindowFrame::OnComboStashSetFocus, this);
-    noteDataView->Unbind(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, &MainWindowFrame::OnNoteDataView, this);
-    treeFilters->Unbind(wxEVT_KEY_DOWN,&MainWindowFrame::OnTreeKeyDown,this);
+	comboCamera->Unbind(wxEVT_SET_FOCUS, &MainWindowFrame::OnComboCameraSetFocus, this);
+	comboStash->Unbind(wxEVT_SET_FOCUS, &MainWindowFrame::OnComboStashSetFocus, this);
+	noteDataView->Unbind(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, &MainWindowFrame::OnNoteDataView, this);
+	treeFilters->Unbind(wxEVT_KEY_DOWN,&MainWindowFrame::OnTreeKeyDown,this);
+	
 }
 
 
@@ -825,8 +852,9 @@ BEGIN_EVENT_TABLE(MainWindowFrame, wxFrame)
     EVT_TIMER(ID_PROGRESS_TIMER,MainWindowFrame::OnProgressTimer)
     EVT_TIMER(ID_UPDATE_TIMER,MainWindowFrame::OnUpdateTimer)
     EVT_TIMER(ID_AUTOSAVE_TIMER,MainWindowFrame::OnAutosaveTimer)
+#ifdef FIX_WXPROPGRID_16222
     EVT_IDLE(MainWindowFrame::OnIdle)
-   
+#endif   
     EVT_SPLITTER_UNSPLIT(ID_SPLIT_TOP_BOTTOM, MainWindowFrame::OnRawDataUnsplit) 
     EVT_SPLITTER_UNSPLIT(ID_SPLIT_LEFTRIGHT, MainWindowFrame::OnControlUnsplit) 
     EVT_SPLITTER_UNSPLIT(ID_SPLIT_SPECTRA, MainWindowFrame::OnSpectraUnsplit) 
@@ -886,6 +914,13 @@ BEGIN_EVENT_TABLE(MainWindowFrame, wxFrame)
     EVT_PG_DOUBLE_CLICK(ID_GRID_FILTER_PROPERTY, MainWindowFrame::OnGridFilterDClick)
     EVT_TEXT(ID_COMBO_CAMERA, MainWindowFrame::OnComboCameraText)
     EVT_TEXT_ENTER(ID_COMBO_CAMERA, MainWindowFrame::OnComboCameraEnter)
+    EVT_BUTTON(wxID_REMOVE, MainWindowFrame::OnButtonRemoveCam)
+    EVT_BUTTON(ID_BUTTON_ALIGNCAM_XPLUS, MainWindowFrame::OnButtonAlignCameraXPlus)
+    EVT_BUTTON(ID_BUTTON_ALIGNCAM_YPLUS, MainWindowFrame::OnButtonAlignCameraYPlus)
+    EVT_BUTTON(ID_BUTTON_ALIGNCAM_ZPLUS, MainWindowFrame::OnButtonAlignCameraZPlus)
+    EVT_BUTTON(ID_BUTTON_ALIGNCAM_XMINUS, MainWindowFrame::OnButtonAlignCameraXMinus)
+    EVT_BUTTON(ID_BUTTON_ALIGNCAM_YMINUS, MainWindowFrame::OnButtonAlignCameraYMinus)
+    EVT_BUTTON(ID_BUTTON_ALIGNCAM_ZMINUS, MainWindowFrame::OnButtonAlignCameraZMinus)
     EVT_CHECKBOX(ID_CHECK_ALPHA, MainWindowFrame::OnCheckAlpha)
     EVT_CHECKBOX(ID_CHECK_LIGHTING, MainWindowFrame::OnCheckLighting)
     EVT_CHECKBOX(ID_CHECK_CACHING, MainWindowFrame::OnCheckCacheEnable)
@@ -895,7 +930,6 @@ BEGIN_EVENT_TABLE(MainWindowFrame, wxFrame)
     EVT_COMBOBOX(ID_COMBO_FILTER, MainWindowFrame::OnComboFilter)
     EVT_TEXT(ID_COMBO_FILTER, MainWindowFrame::OnComboFilterText)
     EVT_BUTTON(ID_BTN_STASH_MANAGE, MainWindowFrame::OnButtonStashDialog)
-    EVT_BUTTON(wxID_REMOVE, MainWindowFrame::OnButtonRemoveCam)
     EVT_LISTBOX(ID_LIST_PLOTS, MainWindowFrame::OnSpectraListbox)
     EVT_CLOSE(MainWindowFrame::OnClose)
     EVT_TREE_END_LABEL_EDIT(ID_TREE_FILTERS,MainWindowFrame::OnTreeEndLabelEdit)
@@ -948,6 +982,7 @@ void *RefreshThread::Entry()
 	return 0;
 }
 
+#ifdef FIX_WXPROPGRID_16222
 void MainWindowFrame::OnIdle(wxIdleEvent &evt)
 {
 	if(backFilterPropGrid)
@@ -962,6 +997,7 @@ void MainWindowFrame::OnIdle(wxIdleEvent &evt)
 		backCameraPropGrid=0;
 	}
 }
+#endif
 
 unsigned int MainWindowFrame::guessFileType(const std::string &dataFile)
 {
@@ -1083,6 +1119,8 @@ void MainWindowFrame::OnFileOpen(wxCommandEvent &event)
 	//Load the file
 	if(!loadFile(wxF.GetPath()))
 	{
+		//If the load failed, do not try to set the 
+		// selection & visibility
 		visControl.clearTreeFilterViewPersistence();
 		return;
 	}
@@ -1093,15 +1131,6 @@ void MainWindowFrame::OnFileOpen(wxCommandEvent &event)
 	configFile.addRecentFile(tmp);
 	//Update the "recent files" menu
 	recentHistory->AddFileToHistory(wxF.GetPath());
-
-	//If we are using the default camera,
-	//move it to make sure that it is visible
-	if(visControl.state.getNumCams() == 1)
-	{
-		visControl.scene.ensureVisible(3);
-	}
-
-	panelTop->forceRedraw();
 }
 
 void MainWindowFrame::OnFileMerge(wxCommandEvent &event)
@@ -1123,7 +1152,6 @@ void MainWindowFrame::OnFileMerge(wxCommandEvent &event)
 
 	statusMessage(TRANS("Merged file."),MESSAGE_INFO);
 
-	panelTop->forceRedraw();
 
 	setSaveStatus();
 }
@@ -1215,12 +1243,9 @@ void MainWindowFrame::OnDropFiles(const wxArrayString &files, int x, int y)
 			//If command down, load first file using this,
 			//then merge the rest
 			if(!loaded)
-			{
-				if(loadFile(files[ui],!wxm.CmdDown()))
-					loaded=true;
-			}
+				loaded=loadFile(files[ui],!wxm.CmdDown());
 			else
-				loadFile(files[ui],true);
+				loaded=loadFile(files[ui],true);
 		}
 	}
 
@@ -1237,15 +1262,6 @@ void MainWindowFrame::OnDropFiles(const wxArrayString &files, int x, int y)
 	if(loaded || rangeLoaded)
 		doSceneUpdate();
 
-	if(files.Count())
-	{
-		//If we are using the default camera,
-		//move it to make sure that it is visible
-		if(visControl.state.getNumCams() == 1)
-		{
-			visControl.scene.ensureVisible(3);
-		}
-	}
 }
 
 bool MainWindowFrame::loadFile(const wxString &fileStr, bool merge,bool noUpdate)
@@ -1297,12 +1313,15 @@ bool MainWindowFrame::loadFile(const wxString &fileStr, bool merge,bool noUpdate
 		if(panelTop->isInited())
 			panelTop->updateClearColour();
 
-		checkViewWorldAxis->Check(visControl.scene.getWorldAxisVisible());
+		checkViewWorldAxis->Check(visControl.state.getWorldAxisMode());
+		visControl.scene.setWorldAxisVisible(visControl.state.getWorldAxisMode());
 
 		visControl.updateCameraComboBox(comboCamera);
 		//Only update the camera grid if we have a valid uniqueID
 		if(visControl.state.getNumCams() > 1)
 		{
+			//set the active camera
+			visControl.setActiveCam(visControl.state.getActiveCam());	
 			//Use the active cam to update the grid.
 			visControl.updateCameraPropGrid(gridCameraProperties,
 						visControl.state.getActiveCam());
@@ -1372,7 +1391,7 @@ bool MainWindowFrame::loadFile(const wxString &fileStr, bool merge,bool noUpdate
 	updateWxTreeCtrl(treeFilters);
 
 	if(!noUpdate)
-		return doSceneUpdate();
+		return doSceneUpdate(true);
 
 	return true;
 }	
@@ -1420,10 +1439,6 @@ void MainWindowFrame::OnRecentFile(wxCommandEvent &event)
 		}
 		
 		setSaveStatus();
-
-		//make sure camera is properly centred
-		if(visControl.state.getNumCams() == 1)
-			visControl.scene.ensureVisible(3);
 	}
 
 }
@@ -1725,7 +1740,12 @@ void MainWindowFrame::setLockUI(bool locking=true,
 			unsigned int nFilters;
 			nFilters = visControl.state.treeState.size();
 			comboFilters->Enable(!locking && nFilters);
-			refreshButton->Enable(!locking && nFilters);
+			if(locking)
+				refreshButton->SetLabel(TRANS("Abo&rt"));
+			else
+				refreshButton->SetLabel(TRANS("&Refresh"));
+			refreshButton->Enable(nFilters);
+			
 			btnFilterTreeErrs->Enable(!locking);
 			treeFilters->Enable(!locking);	
 
@@ -2275,7 +2295,8 @@ void MainWindowFrame::OnFileExportPackage(wxCommandEvent &event)
 			filesize=0;
 			if(wantDebugPack && isPosFile)
 				getFilesize(it->second.c_str(),filesize);
-			
+		
+			//If we want a debugging package, then only copy the first part of the file	
 			if(wantDebugPack && isPosFile && filesize > CHUNKSIZE)
 			{
 				std::ifstream inputF(it->second.c_str(),std::ios::binary);
@@ -2303,7 +2324,13 @@ void MainWindowFrame::OnFileExportPackage(wxCommandEvent &event)
 			}
 			else
 			{
-				copyError=!wxCopyFile((it->second),folder+(it->first));
+				//if the file exists, then try to copy it to the local folder.
+				// The file might be optional, and therefore blank, so it is not an error
+				// to not have the file existing
+				if(wxFileExists(it->second))
+					copyError=!wxCopyFile((it->second),folder+(it->first));
+				else
+					copyError=false;
 			}
 
 			if(copyError)
@@ -2344,14 +2371,16 @@ void MainWindowFrame::OnFileExportIons(wxCommandEvent &event)
 	ExportPosDialog *exportDialog=new ExportPosDialog(this,wxID_ANY,TRANS("Export"));
 	exportDialog->initialiseData(f);
 	
-	//create a file chooser for later.
+	//create a file chooser for later. The format string is special as we use it to demux the 
+	// format later
 	wxFileDialog wxF(this,TRANS("Save pos..."), wxT(""),
-		wxT(""),TRANS("POS Data (*.pos)|*.pos|All Files (*)|*"),wxFD_SAVE);
+		wxT(""),TRANS("POS Data (*.pos)|*.pos|Text File (*.txt)|*.txt|VTK Legacy (*.vtk)|*.vtk|All Files (*)|*"),wxFD_SAVE);
 	
 	//If the user cancels the file chooser, 
 	//drop them back into the export dialog.
 	do
 	{
+		cerr << "Show dialog" << __FILE__ << " :" << __LINE__ << endl;
 		//Show, then check for user cancelling export dialog
 		if(exportDialog->ShowModal() == wxID_CANCEL)
 		{
@@ -2396,10 +2425,19 @@ void MainWindowFrame::OnFileExportIons(wxCommandEvent &event)
 	//Retrieve the ion streams that we need to save
 	vector<const FilterStreamData *> exportVec;
 	exportDialog->getExportVec(exportVec);
-	
+
+
+	//Using the wildcard constant selected, set if we want text or pos
+	unsigned int format;
+	if(wxF.GetFilterIndex() == 0)
+		format = IONFORMAT_POS;
+	else if(wxF.GetFilterIndex() == 1)
+		format = IONFORMAT_TEXT;
+	else
+		format = IONFORMAT_VTK; 
 
 	//write the ion streams to disk
-	if(IonStreamData::exportStreams(exportVec,dataFile))
+	if(IonStreamData::exportStreams(exportVec,dataFile,format))
 	{
 		wxErrMsg(this,TRANS("Save error"),
 			TRANS("Unable to save. Check output destination can be written to."));
@@ -2899,7 +2937,7 @@ void MainWindowFrame::OnHelpAbout(wxCommandEvent &event)
 	info.SetName((PROGRAM_NAME));
 	info.SetVersion((PROGRAM_VERSION));
 	info.SetDescription(TRANS("Quick and dirty analysis for point data.")); 
-	info.SetWebSite(wxT("https://sourceforge.net/apps/phpbb/threedepict/"));
+	info.SetWebSite(wxT("https://threedepict.sourceforge.net/"));
 
 	info.AddDeveloper(wxT("D. Haley"));	
 	info.AddDeveloper(wxT("A. Ceguerra"));	
@@ -2991,7 +3029,9 @@ void MainWindowFrame::OnComboStashEnter(wxCommandEvent &event)
 void MainWindowFrame::OnComboFilterText(wxCommandEvent &event)
 {
 	//prevent user from modifying text
+#ifndef __APPLE__
 	comboFilters->ChangeValue(TRANS(ADD_FILTER_TEXT));
+#endif
 }
 
 void MainWindowFrame::OnComboStash(wxCommandEvent &event)
@@ -3414,6 +3454,7 @@ void MainWindowFrame::OnGridFilterPropertyChange(wxPropertyGridEvent &event)
 	else 
 		clearWxTreeImages(treeFilters);
 
+#ifdef FIX_WXPROPGRID_16222
 	//See wx bug #16222 - cannot modify a property grid's contents
 	// from a change event. Must work in a side-object then swap
 	//--
@@ -3434,6 +3475,10 @@ void MainWindowFrame::OnGridFilterPropertyChange(wxPropertyGridEvent &event)
 	//Restore the original splitter position
 	gridFilterPropGroup->SetSplitterPosition(columnPos);
 	//--
+#else
+	visControl.updateFilterPropGrid(gridFilterPropGroup,filterId,
+		stlStr(gridFilterPropGroup->SaveEditableState()));
+#endif
 
 	programmaticEvent=false;
 	
@@ -3447,7 +3492,9 @@ void MainWindowFrame::OnGridFilterDClick(wxPropertyGridEvent &event)
 void MainWindowFrame::OnGridCameraPropertyChange(wxPropertyGridEvent &event)
 {
 
-	if(programmaticEvent)
+	//Check for inited OK. Seem to be getting called before 
+	//do_layout is complete.
+	if(programmaticEvent || !initedOK)
 	{
 		event.Veto();
 		return;
@@ -3513,6 +3560,7 @@ void MainWindowFrame::OnGridCameraPropertyChange(wxPropertyGridEvent &event)
 	//Set property
 	visControl.setCamProperty(cameraId,key,newValue);
 
+#ifdef FIX_WXPROPGRID_16222
 	//FIXME :Need to send the new grid, not the old, due to wx bug
 	//See wx bug #16222 - cannot modify a property grid's contents
 	// from a change event. Must work in a side-objectm then swap
@@ -3522,10 +3570,21 @@ void MainWindowFrame::OnGridCameraPropertyChange(wxPropertyGridEvent &event)
 	backCameraPropGrid->SetExtraStyle(PROPERTY_GRID_EXTRA_STYLE);
 	
 	visControl.updateCameraPropGrid(backCameraPropGrid,cameraId);
+	int columnPos =gridCameraProperties->GetSplitterPosition();
 	
 	std::swap(backCameraPropGrid,gridCameraProperties);
 	do_cameragrid_prop_layout();
+	gridCameraProperties->SetSplitterPosition(columnPos);
+#else
+	visControl.updateCameraPropGrid(gridCameraProperties,cameraId);
+#endif
 
+
+#ifdef __WIN32
+	//Move the splitter panel
+	splitLeftRight->SetSashPosition(splitLeftRight->GetSashPosition()+1);
+	splitLeftRight->SetSashPosition(splitLeftRight->GetSashPosition()-1);
+#endif
 	//Ensure that the GL panel shows latest cam orientation 
 	panelTop->forceRedraw();
 	programmaticEvent=false;
@@ -3583,7 +3642,7 @@ void MainWindowFrame::OnComboCameraEnter(wxCommandEvent &event)
 	}
 	else
 	{
-
+		ASSERT(camName.size());
 		//Create a new camera for the scene.
 		visControl.state.addCam(camName,true);
 		
@@ -3768,12 +3827,14 @@ void MainWindowFrame::OnComboFilter(wxCommandEvent &event)
 	comboFilters->ChangeValue(TRANS(ADD_FILTER_TEXT));
 
 	//update prop grid
+#ifdef FIX_WXPROPGRID_16222
 	ASSERT(!backFilterPropGrid);
+#endif
 	updateFilterPropertyGrid(gridFilterPropGroup,f);
 	
 }
 
-bool MainWindowFrame::doSceneUpdate()
+bool MainWindowFrame::doSceneUpdate(bool ensureVisible)
 {
 	//Update scene
 	ASSERT(!currentlyUpdatingScene);
@@ -3800,6 +3861,8 @@ bool MainWindowFrame::doSceneUpdate()
 	//reset the progress timer animation
 	visControl.scene.resetProgressAnim();
 
+	ensureResultVisible=ensureVisible;
+
 	ASSERT(!refreshControl);
 	refreshControl = new RefreshController(visControl.state.treeState);
 	refreshThread=new RefreshThread(this,refreshControl);
@@ -3871,7 +3934,6 @@ void MainWindowFrame::finishSceneUpdate(unsigned int errCode)
 	//Restore the UI elements to their interactive state
 	setLockUI(false);
 
-	panelTop->forceRedraw();
 	panelSpectra->Refresh(false);	
 
 	updateEditRangeMenu();
@@ -3945,6 +4007,19 @@ void MainWindowFrame::OnFinishRefreshThread(wxCommandEvent &event)
 		MainFrame_statusbar->SetStatusText(TRANS("Complete"),1);
 		MainFrame_statusbar->SetStatusText("",2);
 	}
+
+
+	if(ensureResultVisible)
+	{
+		//If we are using the default camera,
+		//move it to make sure that it is visible
+		if(visControl.state.getNumCams() == 1)
+			visControl.scene.ensureVisible(CAMERA_DIR_YPLUS);
+
+		ensureResultVisible=false;
+	}
+
+
 	//restart the update timer, to check for updates from the backend
 	updateTimer->Start(UPDATE_TIMER_DELAY);
 }
@@ -4091,12 +4166,6 @@ void MainWindowFrame::OnUpdateTimer(wxTimerEvent &event)
 
 	if(requireFirstUpdate && !refreshThreadActive())
 	{
-		//If we are using the default camera,
-		//move it to make sure that it is visible
-		if(visControl.state.getNumCams() == 1)
-			visControl.scene.ensureVisible(3);
-
-
 		doSceneUpdate();
 
 		requireFirstUpdate=false;
@@ -4118,9 +4187,9 @@ void MainWindowFrame::OnUpdateTimer(wxTimerEvent &event)
 	//Don't attempt to update if already updating, or last
 	//update aborted
 	bool visUpdates=visControl.state.treeState.hasUpdates();
-
+	bool monitorUpdates=visControl.state.treeState.hasMonitorUpdates();
 	//I can has updates?
-	if((visUpdates || plotUpdates) && !refreshThreadActive())
+	if((visUpdates || plotUpdates|| monitorUpdates ) && !refreshThreadActive())
 	{
 		if(visUpdates)
 			visControl.state.treeState.applyBindingsToTree();	
@@ -4286,7 +4355,7 @@ void MainWindowFrame::updateProgressStatus()
 	{
 		//Check for new progress data
 		const ProgressData &p=refreshControl->curProg;
-		ASSERT(refreshControl->curProg.filterProgress <=100);
+		ASSERT(p.filterProgress <=100 || p.filterProgress==(unsigned int) -1);
 
 		if(p == lastProgressData
 
@@ -4295,8 +4364,11 @@ void MainWindowFrame::updateProgressStatus()
 
 		//This shouldn't happen, but prevent >100% progress from being reported
 		unsigned int cappedProgress;
-		cappedProgress = std::min(p.filterProgress,(unsigned int)100);
-
+		if (p.filterProgress!=(unsigned int)-1)
+			cappedProgress = std::min(p.filterProgress,(unsigned int)100);
+		else
+			cappedProgress = 0;
+			
 		//Inform progress circle in scene about current progress
 		visControl.scene.progressCircle.setCurFilter(p.totalProgress);
 		visControl.scene.progressCircle.setMaxStep(p.maxStep);
@@ -4348,7 +4420,11 @@ void MainWindowFrame::updateProgressStatus()
 
 
 			//Show the abort notice if we have hit 100%
-			if( p.filterProgress != 100 && p.filterProgress < p.totalNumFilters)
+			if( p.filterProgress == (unsigned int) -1)
+			{
+				filterProg=TRANS("Calculating...");
+			}
+			else if(p.filterProgress != 100 && p.filterProgress < p.totalNumFilters)
 				filterProg+=TRANS("\% Done (Esc aborts)");
 			else
 				filterProg+=TRANS("\% Done");
@@ -4609,8 +4685,12 @@ void MainWindowFrame::OnButtonRefresh(wxCommandEvent &event)
 	if(!gridCameraProperties || !gridFilterPropGroup)
 		return;
 
+	//Run abort code as needed
 	if(currentlyUpdatingScene || refreshThreadActive())
+	{
+		OnProgressAbort(event);
 		return;
+	}
 
 	//dirty hack to get keyboard state.
 	wxMouseState wxm = wxGetMouseState();
@@ -4817,6 +4897,16 @@ void MainWindowFrame::OnButtonRemoveCam(wxCommandEvent &event)
 		programmaticEvent=false;
 
 		setSaveStatus();
+
+		// There is one camera that we cannot access
+		// TODO: This logic should not be here, but in the widget update
+		if(visControl.state.getNumCams() > 1)
+		{
+			visControl.updateCameraComboBox(comboCamera);
+			visControl.updateCameraPropGrid(gridCameraProperties,visControl.state.getActiveCam());
+		}
+		else
+			gridCameraProperties->Clear();
 	}
 	
 }
@@ -4959,6 +5049,80 @@ void MainWindowFrame::OnClose(wxCloseEvent &event)
  	 Destroy();
 }
 
+void MainWindowFrame::realignCameraButton(unsigned int direction)
+{
+	if(checkAlignCamResize->IsChecked())
+		visControl.scene.ensureVisible(direction);
+	else
+	{
+		//move the camera from its current position to the target direction
+		Camera *cam=visControl.scene.getActiveCam();
+		if(cam->type() == CAM_LOOKAT)
+		{
+			BoundCube bc = visControl.scene.getBound();
+			CameraLookAt *cLook=(CameraLookAt*)cam;
+			cLook->setTarget(bc.getCentroid());
+			cLook->repositionAroundTarget(direction);
+
+			//set the "up" direction that we use by default
+			Point3D p;
+			switch(direction)
+			{
+				case CAMERA_DIR_XPLUS:
+					p=Point3D(0,0,1);
+					break;
+				case CAMERA_DIR_YPLUS:
+					p=Point3D(0,0,1);
+					break;
+				case CAMERA_DIR_ZPLUS:
+					p=Point3D(0,1,0);
+					break;
+				case CAMERA_DIR_XMINUS:
+					p=Point3D(0,0,-1);
+					break;
+				case CAMERA_DIR_YMINUS:
+					p=Point3D(0,0,-1);
+					break;
+				case CAMERA_DIR_ZMINUS:
+					p=Point3D(0,-1,0);
+					break;
+			}
+			cLook->setUpDirection(p);
+		}
+	}	
+
+	panelTop->forceRedraw();
+}
+
+void MainWindowFrame::OnButtonAlignCameraXPlus(wxCommandEvent &event)
+{
+	realignCameraButton(CAMERA_DIR_XPLUS);
+}	
+
+void MainWindowFrame::OnButtonAlignCameraYPlus(wxCommandEvent &event)
+{
+	realignCameraButton(CAMERA_DIR_YPLUS);
+}
+
+void MainWindowFrame::OnButtonAlignCameraZPlus(wxCommandEvent &event)
+{
+	realignCameraButton(CAMERA_DIR_ZPLUS);
+}
+
+void MainWindowFrame::OnButtonAlignCameraXMinus(wxCommandEvent &event)
+{
+	realignCameraButton(CAMERA_DIR_XMINUS);
+}
+
+void MainWindowFrame::OnButtonAlignCameraYMinus(wxCommandEvent &event)
+{
+	realignCameraButton(CAMERA_DIR_YMINUS);
+}
+
+void MainWindowFrame::OnButtonAlignCameraZMinus(wxCommandEvent &event)
+{
+	realignCameraButton(CAMERA_DIR_ZMINUS);
+}
 
 
 void MainWindowFrame::OnCheckPostProcess(wxCommandEvent &event)
@@ -5148,6 +5312,7 @@ void MainWindowFrame::restoreConfigDefaults()
 	{
 		visControl.state.setCamProperty(visControl.state.getActiveCam(), 
 					CAMERA_KEY_LOOKAT_PROJECTIONMODE,TRANS("Orthogonal"));
+		visControl.setActiveCam(visControl.state.getActiveCam());	
 	}
 }
 
@@ -5270,7 +5435,7 @@ void MainWindowFrame::SetCommandLineFiles(wxArrayString &files)
 	//Load them up as data.
 	for(unsigned int ui=0;ui<files.size();ui++)
 	{
-		loadedOK|=loadFile(files[ui],true);
+		loadedOK|=loadFile(files[ui],true,true);
 	}
 
 	requireFirstUpdate=loadedOK;
@@ -5729,12 +5894,12 @@ void MainWindowFrame::do_layout()
 #endif
     cropFxSizer->Add(checkFxCrop, 0, wxALL, 6);
     cropFxSizer->Add(checkFxCropCameraFrame, 0, wxLEFT, 15);
-    sizerFxCropLHS->Add(comboFxCropAxisOne, 0, wxRIGHT|wxBOTTOM|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5);
-    sizerFxCropLHS->Add(panelFxCropOne, 1, wxRIGHT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    cropFxBodyCentreSizer->Add(sizerFxCropLHS, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
+    sizerFxCropLHS->Add(comboFxCropAxisOne, 0, wxRIGHT|wxBOTTOM|wxEXPAND, 5);
+    sizerFxCropLHS->Add(panelFxCropOne, 1, wxRIGHT|wxEXPAND| 5);
+    cropFxBodyCentreSizer->Add(sizerFxCropLHS, 1, wxEXPAND, 0);
     sizerFxCropRHS->Add(comboFxCropAxisTwo, 0, wxLEFT|wxBOTTOM|wxEXPAND, 5);
-    sizerFxCropRHS->Add(panelFxCropTwo, 1, wxLEFT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
-    cropFxBodyCentreSizer->Add(sizerFxCropRHS, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
+    sizerFxCropRHS->Add(panelFxCropTwo, 1, wxLEFT|wxEXPAND, 5);
+    cropFxBodyCentreSizer->Add(sizerFxCropRHS, 1, wxEXPAND, 0);
     cropFxSizer->Add(cropFxBodyCentreSizer, 1, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 5);
     sizerFxCropGridLow->Add(labelFxCropDx, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL, 0);
     sizerFxCropGridLow->Add(textFxCropDx, 0, 0, 0);
@@ -5747,7 +5912,7 @@ void MainWindowFrame::do_layout()
     sizerFxCropGridLow->AddGrowableRow(2);
     sizerFxCropGridLow->AddGrowableCol(0);
     sizerFxCropGridLow->AddGrowableCol(1);
-    cropFxSizer->Add(sizerFxCropGridLow, 0, wxBOTTOM|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
+    cropFxSizer->Add(sizerFxCropGridLow, 0, wxBOTTOM|wxEXPAND, 5);
     noteFxPanelCrop->SetSizer(cropFxSizer);
     sizerFxStereo->Add(checkFxEnableStereo, 0, wxLEFT|wxTOP, 6);
     sizerFxStereo->Add(20, 20, 0, 0, 0);
@@ -5774,7 +5939,7 @@ void MainWindowFrame::do_layout()
     sizer_1->Add(textLimitOutput, 0, wxLEFT, 4);
     sizerTools->Add(sizer_1, 0, wxLEFT|wxEXPAND, 5);
     sizerTools->Add(checkCaching, 0, wxLEFT|wxTOP|wxBOTTOM, 5);
-    sizerToolsRamUsage->Add(labelMaxRamUsage, 0, wxRIGHT|wxALIGN_RIGHT, 5);
+    sizerToolsRamUsage->Add(labelMaxRamUsage, 0, wxRIGHT, 5);
     sizerToolsRamUsage->Add(spinCachePercent, 0, 0, 5);
     sizerTools->Add(sizerToolsRamUsage, 1, wxTOP|wxEXPAND, 5);
     noteTools->SetSizer(sizerTools);
@@ -5842,8 +6007,14 @@ void MainWindowFrame::do_filtergrid_prop_layout()
 
 void MainWindowFrame::do_cameragrid_prop_layout()
 {
+    sizerAlignCam_staticbox = new wxStaticBox(noteCamera, wxID_ANY, _("Align Camera"));
+
     wxBoxSizer* camPaneSizer = new wxBoxSizer(wxVERTICAL);
     wxBoxSizer* camTopRowSizer = new wxBoxSizer(wxHORIZONTAL);
+    sizerAlignCam_staticbox->Lower();
+    wxStaticBoxSizer* sizerAlignCam = new wxStaticBoxSizer(sizerAlignCam_staticbox, wxVERTICAL);
+    wxBoxSizer* sizerCamAlignMinus = new wxBoxSizer(wxHORIZONTAL);
+    wxBoxSizer* sizerCamAlignPlus = new wxBoxSizer(wxHORIZONTAL);
     
     camPaneSizer->Add(labelCameraName, 0, 0, 0);
     camTopRowSizer->Add(comboCamera, 3, 0, 0);
@@ -5851,6 +6022,16 @@ void MainWindowFrame::do_cameragrid_prop_layout()
     camPaneSizer->Add(camTopRowSizer, 0, wxTOP|wxBOTTOM|wxEXPAND, 4);
     camPaneSizer->Add(cameraNamePropertySepStaticLine, 0, wxEXPAND, 0);
     camPaneSizer->Add(gridCameraProperties, 1, wxEXPAND, 0);
+    sizerCamAlignPlus->Add(buttonAlignCamXPlus, 0, wxALIGN_CENTER|wxALL, 5);
+    sizerCamAlignPlus->Add(buttonAlignCamYPlus, 0, wxALIGN_CENTER|wxALL, 5);
+    sizerCamAlignPlus->Add(buttonAlignCamZPlus, 0, wxALIGN_CENTER|wxALL, 5);
+    sizerAlignCam->Add(sizerCamAlignPlus, 0, 0, 0);
+    sizerCamAlignMinus->Add(buttonAlignCamXMinus, 0, wxALIGN_CENTER|wxALL, 5);
+    sizerCamAlignMinus->Add(buttonAlignCamYMinus, 0, wxALIGN_CENTER|wxALL, 5);
+    sizerCamAlignMinus->Add(buttonAlignCamZMinus, 0, wxALIGN_CENTER|wxALL, 5);
+    sizerAlignCam->Add(sizerCamAlignMinus, 0, wxALIGN_CENTER, 0);
+    sizerAlignCam->Add(checkAlignCamResize, 0, wxALIGN_CENTER|wxALL, 4);
+    camPaneSizer->Add(sizerAlignCam, 1, 0, 0);
 
     noteCamera->SetSizer(camPaneSizer);
     noteCamera->Fit();
diff --git a/src/gui/mainFrame.h b/src/gui/mainFrame.h
index df8142e..5a70716 100644
--- a/src/gui/mainFrame.h
+++ b/src/gui/mainFrame.h
@@ -15,8 +15,15 @@
  *	You should have received a copy of the GNU General Public License
  *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-
-
+#include <wx/version.h> 
+
+#if !(wxCHECK_VERSION(3,1,0))
+	#if ( defined(__WIN32__) || defined(__WIN64__) )
+		#error "Your wx version is too low for windows. You need wx 3.1 or greater, due to wx bug 16222."
+	#else
+		#define FIX_WXPROPGRID_16222
+	#endif
+#endif
 // begin wxGlade: ::dependencies
 #include <wx/splitter.h>
 #include <wx/filename.h>
@@ -117,7 +124,7 @@ private:
 	//!Update the progress information in the status bar
 	void updateProgressStatus();
 	//!Perform an update to the 3D Scene. Returns false if refresh failed
-	bool doSceneUpdate();
+	bool doSceneUpdate(bool ensureResultVisible=false);
 	
 	//!Complete the scene update. Returns false if failed
 	void finishSceneUpdate(unsigned int errCode);
@@ -162,6 +169,8 @@ private:
 	bool currentlyUpdatingScene;
 	//!Have we aborted an update
 	bool haveAborted;
+	//!Should the gui ensure that the refresh result is visible at the next update?
+	bool ensureResultVisible;
 
 	//!source item when dragging a filter in the tree control
 	wxTreeItemId *filterTreeDragSource;
@@ -183,13 +192,14 @@ private:
 	std::map<std::string,size_t> filterMap;
    
 	//TODO: Refactor -  remove me.
-	// True if there are pending updates for the mahthgl window
+	// True if there are pending updates for the mathgl window
 	bool plotUpdates;
 
 	//List of pending messages to show in status bar
 	// first int is priority (eg MESSAGE_ERROR), string is message
 	std::list<std::pair<unsigned int, std::string > > statusQueue;
 protected:
+
     wxTimer *statusTimer; //One-shot timer that is used to clear the status bar
     wxTimer *updateTimer; //Periodically calls itself to check for updates from user interaction
     wxTimer *progressTimer; //Periodically calls itself to refresh progress status
@@ -212,7 +222,9 @@ protected:
 
 
     // begin wxGlade: MainWindowFrame::attributes
+    wxStaticBox* sizerAlignCam_staticbox;
     wxMenuBar* MainFrame_Menu;
+    wxStatusBar* MainFrame_statusbar;
     wxStaticText* lblSettings;
     wxComboBox* comboStash;
     wxButton* btnStashManage;
@@ -228,7 +240,9 @@ protected:
     wxPanel* filterTreePane;
     wxStaticText* propGridLabel;
     wxPropertyGrid* gridFilterPropGroup;
+#ifdef FIX_WXPROPGRID_16222
     wxPropertyGrid *backFilterPropGrid;
+#endif
     wxPanel* filterPropertyPane;
     wxSplitterWindow* filterSplitter;
     wxPanel* noteData;
@@ -237,7 +251,16 @@ protected:
     wxButton* buttonRemoveCam;
     wxStaticLine* cameraNamePropertySepStaticLine;
     wxPropertyGrid* gridCameraProperties;
+#ifdef FIX_WXPROPGRID_16222
     wxPropertyGrid* backCameraPropGrid;
+#endif
+    wxButton* buttonAlignCamXPlus;
+    wxButton* buttonAlignCamYPlus;
+    wxButton* buttonAlignCamZPlus;
+    wxButton* buttonAlignCamXMinus;
+    wxButton* buttonAlignCamYMinus;
+    wxButton* buttonAlignCamZMinus;
+    wxCheckBox* checkAlignCamResize;
     wxScrolledWindow* noteCamera;
     wxCheckBox* checkPostProcessing;
     wxCheckBox* checkFxCrop;
@@ -295,119 +318,129 @@ protected:
     wxSplitterWindow* splitTopBottom;
     wxPanel* panelRight;
     wxSplitterWindow* splitLeftRight;
-    wxStatusBar* MainFrame_statusbar;
     // end wxGlade
 
     //Set the state for the state menu
     void setSaveStatus();
+    //Perform camera realignment
+    void realignCameraButton(unsigned int direction);
+
 
     DECLARE_EVENT_TABLE();
 
 public:
-    virtual void OnFileOpen(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileMerge(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileSave(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileSaveAs(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileExportPlot(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileExportImage(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileExportIons(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileExportRange(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFileExit(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnViewControlPane(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnViewRawDataPane(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnHelpHelp(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnHelpContact(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnHelpAbout(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnComboStashText(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnComboStashEnter(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnComboStash(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnTreeEndDrag(wxTreeEvent &event); // wxGlade: <event_handler>
-    virtual void OnTreeKeyDown(wxKeyEvent &event); // wxGlade: <event_handler>
-    virtual void OnTreeSelectionPreChange(wxTreeEvent &event); // wxGlade: <event_handler>
-    virtual void OnTreeSelectionChange(wxTreeEvent &event); // wxGlade: <event_handler>
-    virtual void OnTreeDeleteItem(wxTreeEvent &event); // wxGlade: <event_handler>
-    virtual void OnTreeBeginDrag(wxTreeEvent &event); // wxGlade: <event_handler>
-    virtual void OnBtnExpandTree(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnBtnCollapseTree(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnBtnFilterTreeErrs(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnComboCameraText(wxCommandEvent &event); // wxGlade: <event_handler>
-
-    virtual void OnGridFilterPropertyChange(wxPropertyGridEvent &event); // wxGlade: <event_handler>
-    virtual void OnGridFilterDClick(wxPropertyGridEvent &event); // wxGlade: <event_handler>
-    virtual void OnComboCameraEnter(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnComboCamera(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileOpen(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileMerge(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileSave(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileSaveAs(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileExportPlot(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileExportImage(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileExportIons(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileExportRange(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnViewBackground(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFileExit(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnEditUndo(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnEditRedo(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnEditRange(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnEditPreferences(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnViewControlPane(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnViewRawDataPane(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnHelpHelp(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnHelpContact(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnHelpAbout(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnComboStashText(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnComboStashEnter(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnComboStash(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonStashDialog(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnTreeEndDrag(wxTreeEvent &event); // wxGlade: <event_handler>
+    void OnTreeKeyDown(wxKeyEvent &event); // wxGlade: <event_handler>
+    void OnTreeDeleteItem(wxTreeEvent &event); // wxGlade: <event_handler>
+    void OnTreeSelectionChange(wxTreeEvent &event); // wxGlade: <event_handler>
+    void OnTreeBeginDrag(wxTreeEvent &event); // wxGlade: <event_handler>
+    void OnTreeSelectionPreChange(wxTreeEvent &event); // wxGlade: <event_handler>
+    void OnBtnExpandTree(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnBtnCollapseTree(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnBtnFilterTreeErrs(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnComboCameraText(wxCommandEvent &event); // wxGlade: <event_handler>
+
+    void OnGridFilterPropertyChange(wxPropertyGridEvent &event); // wxGlade: <event_handler>
+    void OnGridFilterDClick(wxPropertyGridEvent &event); // wxGlade: <event_handler>
+    void OnComboCameraEnter(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnComboCamera(wxCommandEvent &event); // wxGlade: <event_handler>
     
 
-    virtual void OnEditUndo(wxCommandEvent &event);    
-    virtual void OnEditRedo(wxCommandEvent &event);    
-    virtual void OnEditRange(wxCommandEvent &event);    
-    virtual void OnEditPreferences(wxCommandEvent &event);    
    
-    virtual void OnButtonRemoveCam(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCheckPostProcess(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxCropCheck(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxCropCamFrameCheck(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxCropAxisOne(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxCropAxisTwo(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxStereoEnable(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxStereoCombo(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxStereoBaseline(wxScrollEvent &event); // wxGlade: <event_handler>
-    virtual void OnFxStereoLensFlip(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnButtonStashDialog(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCheckAlpha(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCheckLighting(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCheckCacheEnable(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCheckWeakRandom(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCacheRamUsageSpin(wxSpinEvent &event); // wxGlade: <event_handler>
-    virtual void OnSpectraListbox(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnCheckLimitOutput(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnTextLimitOutput(wxCommandEvent &event); // wxGlade: <event_handler>
-    virtual void OnTextLimitOutputEnter(wxCommandEvent &event); // wxGlade: <event_handler>
-
-    virtual void OnComboFilterEnter(wxCommandEvent &event); // 
-    virtual void OnComboFilter(wxCommandEvent &event); // 
-    virtual void OnComboFilterText(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonRemoveCam(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonAlignCameraXPlus(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonAlignCameraYPlus(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonAlignCameraZPlus(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonAlignCameraXMinus(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonAlignCameraYMinus(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnButtonAlignCameraZMinus(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCheckPostProcess(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxCropCheck(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxCropCamFrameCheck(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxCropAxisOne(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxCropAxisTwo(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxStereoEnable(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxStereoCombo(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnFxStereoBaseline(wxScrollEvent &event); // wxGlade: <event_handler>
+    void OnFxStereoLensFlip(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCheckAlpha(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCheckLighting(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCheckWeakRandom(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnSpectraListbox(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCheckLimitOutput(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnTextLimitOutput(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnTextLimitOutputEnter(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCheckCacheEnable(wxCommandEvent &event); // wxGlade: <event_handler>
+    void OnCacheRamUsageSpin(wxSpinEvent &event); // wxGlade: <event_handler>
+
+    void OnComboFilterEnter(wxCommandEvent &event); // 
+    void OnComboFilter(wxCommandEvent &event); // 
+    void OnComboFilterText(wxCommandEvent &event); // wxGlade: <event_handler>
     
-    virtual void OnStatusBarTimer(wxTimerEvent &event); // 
-    virtual void OnProgressTimer(wxTimerEvent &event);
-    virtual void OnProgressAbort(wxCommandEvent &event);
-    virtual void OnViewFullscreen(wxCommandEvent &event);
-    virtual void OnButtonRefresh(wxCommandEvent &event);
-    virtual void OnButtonGridCopy(wxCommandEvent &event);
-    virtual void OnButtonGridSave(wxCommandEvent &event);
-    virtual void OnRawDataUnsplit(wxSplitterEvent &event);
-    virtual void OnFilterPropDoubleClick(wxSplitterEvent &event);
-    virtual void OnControlUnsplit(wxSplitterEvent &event);
-    virtual void OnControlSplitMove(wxSplitterEvent &event);
-    virtual void OnFilterSplitMove(wxSplitterEvent &event);
-    virtual void OnTopBottomSplitMove(wxSplitterEvent &event);
-    virtual void OnSpectraUnsplit(wxSplitterEvent &event);
-    virtual void OnViewSpectraList(wxCommandEvent &event); 
-    virtual void OnViewPlotLegend(wxCommandEvent &event); 
-    virtual void OnViewWorldAxis(wxCommandEvent &event); 
-    virtual void OnViewBackground(wxCommandEvent &event);
-    virtual void OnClose(wxCloseEvent &evt);
-    virtual void OnComboCameraSetFocus(wxFocusEvent &evt);
-    virtual void OnComboStashSetFocus(wxFocusEvent &evt);
-    virtual void OnNoteDataView(wxNotebookEvent &evt);
-    virtual void OnGridCameraPropertyChange(wxPropertyGridEvent &event); // wxGlade: <event_handler>
-
-    virtual void OnFileExportVideo(wxCommandEvent &event);
-    virtual void OnFileExportFilterVideo(wxCommandEvent &event);
-    virtual void OnFileExportPackage(wxCommandEvent &event);
-    virtual void OnRecentFile(wxCommandEvent &event); // wxGlade: <event_handler>
-
-    virtual void OnTreeBeginLabelEdit(wxTreeEvent &evt);
-    virtual void OnTreeEndLabelEdit(wxTreeEvent &evt);
+    void OnStatusBarTimer(wxTimerEvent &event); // 
+    void OnProgressTimer(wxTimerEvent &event);
+    void OnProgressAbort(wxCommandEvent &event);
+    void OnViewFullscreen(wxCommandEvent &event);
+    void OnButtonRefresh(wxCommandEvent &event);
+    void OnButtonGridCopy(wxCommandEvent &event);
+    void OnButtonGridSave(wxCommandEvent &event);
+    void OnRawDataUnsplit(wxSplitterEvent &event);
+    void OnFilterPropDoubleClick(wxSplitterEvent &event);
+    void OnControlUnsplit(wxSplitterEvent &event);
+    void OnControlSplitMove(wxSplitterEvent &event);
+    void OnFilterSplitMove(wxSplitterEvent &event);
+    void OnTopBottomSplitMove(wxSplitterEvent &event);
+    void OnSpectraUnsplit(wxSplitterEvent &event);
+    void OnViewSpectraList(wxCommandEvent &event); 
+    void OnViewPlotLegend(wxCommandEvent &event); 
+    void OnViewWorldAxis(wxCommandEvent &event); 
+    void OnClose(wxCloseEvent &evt);
+    void OnComboCameraSetFocus(wxFocusEvent &evt);
+    void OnComboStashSetFocus(wxFocusEvent &evt);
+    void OnNoteDataView(wxNotebookEvent &evt);
+    void OnGridCameraPropertyChange(wxPropertyGridEvent &event); // wxGlade: <event_handler>
+
+    void OnFileExportVideo(wxCommandEvent &event);
+    void OnFileExportFilterVideo(wxCommandEvent &event);
+    void OnFileExportPackage(wxCommandEvent &event);
+    void OnRecentFile(wxCommandEvent &event); // wxGlade: <event_handler>
+
+    void OnTreeBeginLabelEdit(wxTreeEvent &evt);
+    void OnTreeEndLabelEdit(wxTreeEvent &evt);
     
-    virtual void OnUpdateTimer(wxTimerEvent &evt);
-    virtual void OnAutosaveTimer(wxTimerEvent &evt);
+    void OnUpdateTimer(wxTimerEvent &evt);
+    void OnAutosaveTimer(wxTimerEvent &evt);
 
-    virtual void OnCheckUpdatesThread(wxCommandEvent &evt);
-    virtual void OnFinishRefreshThread(wxCommandEvent &evt);
-    virtual void OnIdle(wxIdleEvent &evt);
+    void OnCheckUpdatesThread(wxCommandEvent &evt);
+    void OnFinishRefreshThread(wxCommandEvent &evt);
 
-    virtual void SetCommandLineFiles(wxArrayString &files);
+#ifdef FIX_WXPROPGRID_16222
+    void OnIdle(wxIdleEvent &evt);
+#endif
+    void SetCommandLineFiles(wxArrayString &files);
 
     //return type of file, based upon heuristic check
     static unsigned int guessFileType(const std::string &file);
diff --git a/src/gui/mathglPane.cpp b/src/gui/mathglPane.cpp
index 86d1a8a..e5caae6 100644
--- a/src/gui/mathglPane.cpp
+++ b/src/gui/mathglPane.cpp
@@ -354,9 +354,12 @@ void MathGLPane::render(wxPaintEvent &event)
 				tlY=draggingCurrent.y;
 				hRect = draggingStart.y - tlY;
 			}
-		
-			dc->SetBrush(wxBrush(*wxBLUE,wxTRANSPARENT));	
 
+#if wxCHECK_VERSION(3,1,0)
+			dc->SetBrush(wxBrush(*wxBLUE,wxBRUSHSTYLE_TRANSPARENT));	
+#else
+			dc->SetBrush(wxBrush(*wxBLUE,wxTRANSPARENT));	
+#endif
 			const int END_MARKER_SIZE=5;
 
 			//If the cursor is wholly below
@@ -1255,9 +1258,23 @@ void MathGLPane::drawInteractOverlay(wxDC *dc) const
 			//Select pen colour depending upon whether interaction
 			// is allowed
 			if(limitInteract)
-				drawPen= new wxPen(*wxLIGHT_GREY,2,wxSOLID);
+{
+
+				#if wxCHECK_VERSION(3,1,0)
+					drawPen = new wxPen(*wxLIGHT_GREY,2,wxPENSTYLE_SOLID);
+				#else
+					drawPen= new wxPen(*wxLIGHT_GREY,2,wxSOLID);
+				#endif
+}
+
 			else
-				drawPen= new wxPen(*wxBLACK,2,wxSOLID);
+{
+				#if wxCHECK_VERSION(3,1,0)
+					drawPen = new wxPen(*wxBLACK,2,wxPENSTYLE_SOLID);
+				#else
+					drawPen= new wxPen(*wxBLACK,2,wxSOLID);
+				#endif
+}
 			
 			dc->SetPen(*drawPen);
 			//Draw two arrows < > over the centre of the plot
@@ -1480,8 +1497,12 @@ void MathGLPane::drawRegionDraggingOverlay(wxDC *dc) const
 		dc->SetFont(font);
 	
 	wxPen *arrowPen;
-	arrowPen=  new wxPen(*wxBLACK,2,wxSOLID);
 
+#if wxCHECK_VERSION(3,1,0)
+	arrowPen=  new wxPen(*wxBLACK,2,wxPENSTYLE_SOLID);
+#else
+	arrowPen=  new wxPen(*wxBLACK,2,wxSOLID);
+#endif
 	dc->SetPen(*arrowPen);
 	const int ARROW_SIZE=8;
 	
diff --git a/src/testing/mglTesting.cpp b/src/testing/mglTesting.cpp
index 82668a1..0994eec 100644
--- a/src/testing/mglTesting.cpp
+++ b/src/testing/mglTesting.cpp
@@ -150,7 +150,7 @@ bool mglTest()
 		if(f)
 		{
 			float answer=std::numeric_limits<float>::max();
-			stream_cast(answer,f);
+			f >> answer;
 
 			//As an example, an "OK" image gave 177, a broken image 13000
 			const float THRESHOLD=2000;
diff --git a/src/testing/testing.cpp b/src/testing/testing.cpp
index 7d4c982..27eceaa 100644
--- a/src/testing/testing.cpp
+++ b/src/testing/testing.cpp
@@ -29,6 +29,7 @@
 
 
 #include "backend/filters/allFilter.h"
+#include "backend/APT/vtk.h"
 #include "backend/state.h"
 #include "backend/configFile.h"
 #include "backend/filters/algorithms/binomial.h"
@@ -74,9 +75,12 @@ bool abundanceTests();
 //run the tests for algorithms/ 
 bool algorithmTests();
 
+//Check some external file formats that we can write to
+bool fileFormatTests();
+
 bool basicFunctionTests()
 {
-	testStringFuncs();
+	TEST(testStringFuncs(),"String function test");
 
 	//Test point parsing routines
 	{
@@ -179,6 +183,10 @@ bool runUnitTests()
 
 	if(!testIsoSurface())
 		return false;
+
+
+	if(!fileFormatTests())
+		return false;
 	cerr << " OK" << endl << endl;
 
 	return true;
@@ -427,7 +435,7 @@ bool locateDataTests()
 		if(str.size())
 		{
 			manifest.open(str.c_str());
-			manifestOK=manifest;
+			manifestOK=manifest.good();
 		}
 	}
 
@@ -553,7 +561,7 @@ bool algorithmTests()
 {
 	if(!testAnderson())
 		return false;
-	if(!testBackgroundFit())
+	if(!testBackgroundFitMaths())
 		return false;
 
 	if(!K3DMk2Tests())
@@ -564,4 +572,10 @@ bool algorithmTests()
 	return true;
 }
 
+bool fileFormatTests()
+{
+	return testVTKExport();
+}
+
+
 #endif
diff --git a/src/wx/propertyGridUpdater.h b/src/wx/propertyGridUpdater.h
index f6252e8..d12303a 100644
--- a/src/wx/propertyGridUpdater.h
+++ b/src/wx/propertyGridUpdater.h
@@ -24,7 +24,7 @@
 
 #include <map>
 
-const long PROPERTY_GRID_STYLE= 0;
+const long PROPERTY_GRID_STYLE= wxPG_SPLITTER_AUTO_CENTER;
 const long PROPERTY_GRID_EXTRA_STYLE= wxPG_EX_HELP_AS_TOOLTIPS;
 
 //Build a property grid for the 
diff --git a/src/wx/wxcommon.cpp b/src/wx/wxcommon.cpp
index bcf22dd..2a1bbd4 100644
--- a/src/wx/wxcommon.cpp
+++ b/src/wx/wxcommon.cpp
@@ -515,7 +515,6 @@ void combineWxImage(wxImage &base, const wxImage &overlay)
 	unsigned int height=base.GetHeight();
 
 
-	wxImage debugIm(width,height);
 	//Now loop through each pixel and perform
 	// combine operation
 	#pragma omp parallel for
@@ -526,7 +525,6 @@ void combineWxImage(wxImage &base, const wxImage &overlay)
 		{
 			rgbaOv[3] = overlay.GetAlpha(ui,uj);
 
-			debugIm.SetRGB(ui,uj,rgbaOv[3], rgbaOv[3],rgbaOv[3]);
 			if(rgbaOv[3])
 			{
 				//obtain src rgb
@@ -540,16 +538,13 @@ void combineWxImage(wxImage &base, const wxImage &overlay)
 		
 		
 				for(unsigned int chan=0;chan<3;chan++)
-				{
 					rgbIm[chan] = (unsigned char) (float(255-rgbaOv[3])/255.0f*rgbIm[chan] + float(rgbaOv[3]/255.0f)*rgbaOv[chan]);
-				}
 				
 				base.SetRGB(ui,uj,rgbIm[0],rgbIm[1],rgbIm[2]);	
 			}
 		}
 	}	
 
-	debugIm.SaveFile("debug.png",wxBITMAP_TYPE_PNG);
 }
 
 	
diff --git a/src/wx/wxcomponents.cpp b/src/wx/wxcomponents.cpp
index 074c9cc..35a9b7f 100644
--- a/src/wx/wxcomponents.cpp
+++ b/src/wx/wxcomponents.cpp
@@ -326,11 +326,11 @@ void CopyGrid::copyData()
 		//Copy title from header
 		if(cols.size())
 		{
-			for(int ui=0;ui<cols.size();ui++)
+			for(int ui=0;ui<(int)cols.size();ui++)
 			{
 				data+=stlStr(GetColLabelValue(ui));
 
-				if(ui<cols.size()-1)
+				if(ui<(int)cols.size()-1)
 					data+="\t";
 			}
 			data+=endline;
@@ -360,7 +360,7 @@ void CopyGrid::copyData()
 			}
 			data+=endline;
 
-			for(int r=0;r<rows.size(); r++)
+			for(int r=0;r<(int)rows.size(); r++)
 			{
 			    for(int  c=0; c<GetNumberCols(); c++)
 			    {
diff --git a/translations/3Depict_base.pot b/translations/3Depict_base.pot
index dda1c9f..b78fe44 100644
--- a/translations/3Depict_base.pot
+++ b/translations/3Depict_base.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-04-26 23:23+0100\n"
+"POT-Creation-Date: 2016-05-31 11:15+1000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -17,437 +17,362 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../src/gl/cameras.cpp:596
-msgid "Lock"
+#: ../src/gui/glPane.cpp:642
+msgid "Use shift/ctrl-space or double tap to alter reset axis"
 msgstr ""
 
-#: ../src/gl/cameras.cpp:603 ../src/backend/filters/ionClip.cpp:528
-#: ../src/backend/filters/ionClip.cpp:550
-#: ../src/backend/filters/ionClip.cpp:572
-#: ../src/backend/filters/ionClip.cpp:609
-#: ../src/backend/filters/compositionProfile.cpp:993
-#: ../src/backend/filters/compositionProfile.cpp:1031
-#: ../src/backend/filters/spatialAnalysis.cpp:846
-#: ../src/backend/filters/transform.cpp:1202
-#: ../src/backend/filters/transform.cpp:1229
-#: ../src/backend/filters/transform.cpp:1255
-#: ../src/backend/filters/annotation.cpp:568
-msgid "Origin"
+#: ../src/gui/glPane.cpp:938
+msgid "Image progress"
 msgstr ""
 
-#: ../src/gl/cameras.cpp:611 ../src/backend/filters/spatialAnalysis.cpp:769
-msgid "Target"
+#: ../src/gui/glPane.cpp:939
+msgid "Rendering tiles..."
 msgstr ""
 
-#: ../src/gl/cameras.cpp:617
-msgid "Up Dir."
+#: ../src/gui/glPane.cpp:1132
+msgid "Animation progress"
 msgstr ""
 
-#: ../src/gl/cameras.cpp:625 ../src/gl/cameras.cpp:728
-msgid "Perspective"
+#: ../src/gui/glPane.cpp:1133
+msgid "Rendering sequence..."
 msgstr ""
 
-#: ../src/gl/cameras.cpp:627 ../src/gl/cameras.cpp:730
-#: ../src/gui/mainFrame.cpp:5150
-msgid "Orthogonal"
+#: ../src/gui/glPane.cpp:1171
+msgid "Saving Image "
 msgstr ""
 
-#: ../src/gl/cameras.cpp:631
-msgid "Projection"
+#: ../src/gui/glPane.cpp:1171 ../src/gui/mainFrame.cpp:4401
+#: ../src/gui/mainFrame.cpp:4405 ../src/gui/mainFrame.cpp:4418
+#: ../src/backend/filters/dataLoad.cpp:321
+msgid " of "
 msgstr ""
 
-#: ../src/gl/cameras.cpp:640
-msgid "Field of View (deg)"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:40
+msgid "Range Sources"
 msgstr ""
 
-#: ../src/gl/cameras.cpp:646
-msgid "View size"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:42
+msgid "Details"
 msgstr ""
 
-#: ../src/wx/wxcomponents.cpp:191
-msgid "Save Data..."
+#: ../src/gui/dialogs/ExportRngDialog.cpp:53
+msgid "Source Filter"
 msgstr ""
 
-#: ../src/wx/wxcomponents.cpp:192
-msgid "Text File (*.txt)|*.txt|All Files (*)|*"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:54
+#: ../src/backend/filters/rangeFile.cpp:656
+msgid "Ions"
 msgstr ""
 
-#: ../src/wx/wxcomponents.cpp:204
-msgid "Error saving file. Check output dir is writable."
+#: ../src/gui/dialogs/ExportRngDialog.cpp:55
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1587
+#: ../src/backend/filters/voxelise.cpp:834
+#: ../src/backend/filters/rangeFile.cpp:723
+msgid "Ranges"
 msgstr ""
 
-#: ../src/wx/wxcomponents.cpp:204 ../src/gui/dialogs/ExportRngDialog.cpp:170
-#: ../src/gui/mainFrame.cpp:1448 ../src/gui/mainFrame.cpp:1573
-#: ../src/gui/mainFrame.cpp:1622 ../src/gui/mainFrame.cpp:1698
-#: ../src/gui/mainFrame.cpp:2245 ../src/gui/mainFrame.cpp:2311
-#: ../src/gui/mainFrame.cpp:2404 ../src/gui/mainFrame.cpp:2517
-msgid "Save error"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:88
+msgid "Param"
 msgstr ""
 
-#: ../src/common/basics.cpp:183
-msgid "in the future?"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:89
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1200
+#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:105
+#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:352
+#: ../src/backend/filters/dataLoad.cpp:581
+msgid "Value"
 msgstr ""
 
-#: ../src/common/basics.cpp:234
-msgid "a decade ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:90
+msgid "Value2"
 msgstr ""
 
-#: ../src/common/basics.cpp:235
-msgid "a year ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:97
+msgid "Ion Name"
 msgstr ""
 
-#: ../src/common/basics.cpp:236
-msgid "a month ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:98
+msgid "Num Ranges"
 msgstr ""
 
-#: ../src/common/basics.cpp:237
-msgid "a week ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:116
+#: ../src/gui/dialogs/rangeEditDialog.cpp:696 ../src/backend/filter.cpp:53
+msgid "Ion"
 msgstr ""
 
-#: ../src/common/basics.cpp:238
-msgid "a day ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:117
+msgid "Range Start"
 msgstr ""
 
-#: ../src/common/basics.cpp:239
-msgid "an hour ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:118
+msgid "Range end"
 msgstr ""
 
-#: ../src/common/basics.cpp:240
-msgid "45 minutes ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:151 ../src/gui/mainFrame.cpp:2376
+msgid "Save pos..."
 msgstr ""
 
-#: ../src/common/basics.cpp:241
-msgid "30 minutes ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:152
+msgid ""
+"Cameca/Ametek RRNG (*.rrng)|*.rrng|ORNL format RNG (*.rng)|*.rng|Cameca ENV "
+"(*.env)|*.env|All Files (*)|*"
 msgstr ""
 
-#: ../src/common/basics.cpp:242
-msgid "20 minutes ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:184 ../src/gui/mainFrame.cpp:1463
+#: ../src/gui/mainFrame.cpp:1638 ../src/gui/mainFrame.cpp:1713
+#: ../src/gui/mainFrame.cpp:2266 ../src/gui/mainFrame.cpp:2443
+#: ../src/gui/mainFrame.cpp:2556
+msgid "Unable to save. Check output destination can be written to."
 msgstr ""
 
-#: ../src/common/basics.cpp:243
-msgid "15 minutes ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:187 ../src/gui/mainFrame.cpp:1463
+#: ../src/gui/mainFrame.cpp:1588 ../src/gui/mainFrame.cpp:1637
+#: ../src/gui/mainFrame.cpp:1713 ../src/gui/mainFrame.cpp:2265
+#: ../src/gui/mainFrame.cpp:2338 ../src/gui/mainFrame.cpp:2442
+#: ../src/gui/mainFrame.cpp:2555 ../src/wx/wxcomponents.cpp:204
+msgid "Save error"
 msgstr ""
 
-#: ../src/common/basics.cpp:244
-msgid "10 minutes ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:253
+msgid "Export Range"
 msgstr ""
 
-#: ../src/common/basics.cpp:245
-msgid "5 minutes ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:258
+msgid "List of rangefiles in filter tree"
 msgstr ""
 
-#: ../src/common/basics.cpp:246
-msgid "a minute ago"
+#: ../src/gui/dialogs/ExportRngDialog.cpp:260
+msgid "Detailed view of selected range"
 msgstr ""
 
-#: ../src/common/basics.cpp:247
-msgid "30 seconds ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:92
+msgid "Cameca/Ametek RRNG"
 msgstr ""
 
-#: ../src/common/basics.cpp:248
-msgid "10 seconds ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:93
+msgid "Oak-Ridge RNG"
 msgstr ""
 
-#: ../src/common/basics.cpp:249
-msgid "a second ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:94
+msgid "Cameca/Ametek ENV"
 msgstr ""
 
-#: ../src/common/basics.cpp:254
-msgid "a few decades ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:156
+msgid "Key frames"
 msgstr ""
 
-#: ../src/common/basics.cpp:255
-msgid "a few years ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:157
+msgid "Output Data"
 msgstr ""
 
-#: ../src/common/basics.cpp:256
-msgid "a few months ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:158
+msgid "Filters and properties"
 msgstr ""
 
-#: ../src/common/basics.cpp:257
-msgid "a few weeks ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:164
+msgid "Dir : "
 msgstr ""
 
-#: ../src/common/basics.cpp:258
-msgid "a few days ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:167
+msgid "Output only when refresh required"
 msgstr ""
 
-#: ../src/common/basics.cpp:259
-msgid "a few hours ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:169
+msgid "Data Types:"
 msgstr ""
 
-#: ../src/common/basics.cpp:266
-msgid "a few minutes ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:170
+msgid "3D Images"
 msgstr ""
 
-#: ../src/common/basics.cpp:269
-msgid "a few seconds ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:171
+msgid "File Prefix: "
 msgstr ""
 
-#: ../src/common/basics.cpp:296
-msgid "moments ago"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:173
+msgid "Size : "
 msgstr ""
 
-#: ../src/common/colourmap.cpp:242
-msgid "Jet"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:175
+msgid "..."
 msgstr ""
 
-#: ../src/common/colourmap.cpp:243
-msgid "Hot"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:176
+msgid "Point data"
 msgstr ""
 
-#: ../src/common/colourmap.cpp:244
-msgid "Cold"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:177
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1586
+msgid "Plots"
 msgstr ""
 
-#: ../src/common/colourmap.cpp:245
-msgid "Grey"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:178
+msgid "Voxel data"
 msgstr ""
 
-#: ../src/common/colourmap.cpp:246
-msgid "Cyclic"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:179
+msgid "Range files"
 msgstr ""
 
-#: ../src/common/colourmap.cpp:247
-msgid "General"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:180
+msgid "Format"
 msgstr ""
 
-#: ../src/common/colourmap.cpp:248
-msgid "Blue"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:197
+#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:104
+#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:350
+msgid "Frame"
 msgstr ""
 
-#: ../src/common/colourmap.cpp:249
-msgid "Pseudo-Random"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:702
+msgid "transition frame"
 msgstr ""
 
-#: ../src/common/constants.cpp:22
-msgid ""
-"Range Files (*.rng; *.env; *.rrng)|*.rng;*.env;*.rrng;*.RRNG;*.RNG;*.ENV|RNG "
-"File (*.rng)|*.rng;*.RNG|Environment File (*.env)|*.env;*.ENV|RRNG Files (*."
-"rrng)|*.rrng;*.RRNG|All Files (*)|*"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:702
+#: ../src/gui/mainFrame.cpp:1690
+msgid "Frame count"
 msgstr ""
 
-#: ../src/gui/glPane.cpp:628
-msgid "Use shift/ctrl-space or double tap to alter reset axis"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:774
+msgid "Key frame : Colour"
 msgstr ""
 
-#: ../src/gui/glPane.cpp:901
-msgid "Image progress"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:827
+msgid "File existed, but was unable to read or interpret file contents."
 msgstr ""
 
-#: ../src/gui/glPane.cpp:902
-msgid "Rendering tiles..."
+#: ../src/gui/dialogs/animateFilterDialog.cpp:828
+msgid "String load failed"
 msgstr ""
 
-#: ../src/gui/glPane.cpp:1091
-msgid "Animation progress"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:849
+msgid "Keyframe : decimal"
 msgstr ""
 
-#: ../src/gui/glPane.cpp:1092
-msgid "Rendering sequence..."
+#: ../src/gui/dialogs/animateFilterDialog.cpp:858
+msgid "Keyframe : integer"
 msgstr ""
 
-#: ../src/gui/glPane.cpp:1130
-msgid "Saving Image "
+#: ../src/gui/dialogs/animateFilterDialog.cpp:867
+msgid "Keyframe : 3D Point"
 msgstr ""
 
-#: ../src/gui/glPane.cpp:1130 ../src/gui/mainFrame.cpp:4329
-#: ../src/gui/mainFrame.cpp:4333 ../src/gui/mainFrame.cpp:4346
-#: ../src/backend/filters/dataLoad.cpp:321
-msgid " of "
+#: ../src/gui/dialogs/animateFilterDialog.cpp:995
+msgid "Select or create new folder"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:40
-msgid "Range Sources"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1175
+msgid "Export Animation"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:42
-msgid "Details"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1176
+msgid "Select filter"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:53
-msgid "Source Filter"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1177
+msgid "Select property"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:54
-#: ../src/backend/filters/rangeFile.cpp:654
-msgid "Ions"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1179
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1198
+msgid "Filter"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:55
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1587
-#: ../src/backend/filters/voxelise.cpp:834
-#: ../src/backend/filters/rangeFile.cpp:721
-msgid "Ranges"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1180
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1199
+msgid "Property"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:88
-msgid "Param"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1181
+#: ../src/backend/filters/annotation.cpp:545
+#: ../src/backend/filters/annotation.cpp:551
+#: ../src/backend/filters/transform.cpp:1150
+#: ../src/backend/filters/ionDownsample.cpp:465
+#: ../src/backend/filters/spatialAnalysis.cpp:1173
+msgid "Mode"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:89
-#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:105
-#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:352
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1177
-#: ../src/backend/filters/dataLoad.cpp:581
-msgid "Value"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1182
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:68
+msgid "Start Frame"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:90
-msgid "Value2"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1183
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:70
+msgid "End Frame"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:97
-msgid "Ion Name"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1184
+msgid "Keyframe table"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:98
-msgid "Num Ranges"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1185
+msgid "Remove the selected keyframe from the table"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:116
-#: ../src/gui/dialogs/rangeEditDialog.cpp:696 ../src/backend/filter.cpp:50
-msgid "Ion"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1186
+msgid "Enter where the animation frames will be exported to"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:117
-msgid "Range Start"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1187
+msgid "Browse to directory where the animation frames will be exported to"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:118
-msgid "Range end"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1189
+msgid ""
+"Title for files, result will be saved as #-name.png, where # is image number."
 msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:151 ../src/gui/mainFrame.cpp:2348
-msgid "Save pos..."
-msgstr ""
-
-#: ../src/gui/dialogs/ExportRngDialog.cpp:152
-msgid "ORNL format RNG (*.rng)|*.rng|All Files (*)|*"
-msgstr ""
-
-#: ../src/gui/dialogs/ExportRngDialog.cpp:167 ../src/gui/mainFrame.cpp:1448
-#: ../src/gui/mainFrame.cpp:1623 ../src/gui/mainFrame.cpp:1698
-#: ../src/gui/mainFrame.cpp:2246 ../src/gui/mainFrame.cpp:2405
-#: ../src/gui/mainFrame.cpp:2518
-msgid "Unable to save. Check output destination can be written to."
-msgstr ""
-
-#: ../src/gui/dialogs/ExportRngDialog.cpp:236
-msgid "Export Range"
-msgstr ""
-
-#: ../src/gui/dialogs/ExportRngDialog.cpp:241
-msgid "List of rangefiles in filter tree"
-msgstr ""
-
-#: ../src/gui/dialogs/ExportRngDialog.cpp:243
-msgid "Detailed view of selected range"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:221
-msgid "Show Overlays"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:246
-msgid "e.g. H2O"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:561
-#: ../src/gui/dialogs/rangeEditDialog.cpp:695 ../src/gui/mainFrame.cpp:5801
-#: ../src/backend/filter.cpp:51
-msgid "Plot"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:562
-msgid "Short Name"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:563
-msgid "Long Name"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:564
-#: ../src/backend/filters/voxelise.cpp:975
-#: ../src/backend/filters/compositionProfile.cpp:1134
-#: ../src/backend/filters/annotation.cpp:901
-#: ../src/backend/filters/spectrumPlot.cpp:668
-msgid "Colour"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:697
-#: ../src/backend/filters/annotation.cpp:605
-#: ../src/backend/filters/annotation.cpp:646
-#: ../src/backend/filters/annotation.cpp:815
-msgid "Start"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:698
-#: ../src/backend/filters/annotation.cpp:613
-#: ../src/backend/filters/annotation.cpp:655
-#: ../src/backend/filters/annotation.cpp:823
-msgid "End"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1260
-msgid "Range or ion?"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1261
-msgid "Select type to add"
-msgstr ""
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1542
-msgid "Range Editor"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1190
+msgid "Target resolution (image size)"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1546
-msgid "Enable or disable all overlays"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1191
+msgid "Select frame for property display"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1547
-msgid "Entered overlays, use delete to remove"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1192
+msgid "Enter frame number to change frame (eg 1/20)"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1548
-msgid "Available plots for ranging"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1193
+msgid "Save point data (POS files) in output folder?"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1549
-msgid "Enter species to display as overlay, e.g. SiO2"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1194
+msgid "Save plots (as text files) in output folder?"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1550
-msgid "Editable ranges"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1195
+msgid "Save voxel data (raw files) in output folder?"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1551
-msgid "Editable ions"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1196
+msgid "Save range files  in output folder?"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1586
-#: ../src/gui/dialogs/animateFilterDialog.cpp:177
-msgid "Plots"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1201
+msgid "Animation parameters for current frame"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1588
-msgid "Overlay"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1202
+msgid "Abort animation"
 msgstr ""
 
-#: ../src/gui/dialogs/autosaveDialog.cpp:39
-msgid "Remove &All"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1203
+msgid "Run Animation"
 msgstr ""
 
-#: ../src/gui/dialogs/autosaveDialog.cpp:123
-msgid "Restore state?"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1274
+msgid "Filter view"
 msgstr ""
 
-#: ../src/gui/dialogs/autosaveDialog.cpp:133
-msgid "Multiple autosave states were found; would you like to restore one?"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1275
+msgid "Frame view"
 msgstr ""
 
-#: ../src/gui/dialogs/filterErrorDialog.cpp:37 ../src/backend/filter.cpp:456
-#: ../src/backend/filter.cpp:459
+#: ../src/gui/dialogs/filterErrorDialog.cpp:37 ../src/backend/filter.cpp:476
+#: ../src/backend/filter.cpp:479
 msgid "Error"
 msgstr ""
 
@@ -500,6 +425,35 @@ msgstr ""
 msgid "Available stashes"
 msgstr ""
 
+#: ../src/gui/dialogs/resolutionDialog.cpp:45
+msgid "Width :"
+msgstr ""
+
+#: ../src/gui/dialogs/resolutionDialog.cpp:47
+msgid "Height :"
+msgstr ""
+
+#: ../src/gui/dialogs/resolutionDialog.cpp:50
+#: ../src/gui/dialogs/prefDialog.cpp:85
+msgid "Reset"
+msgstr ""
+
+#: ../src/gui/dialogs/resolutionDialog.cpp:336
+msgid "Resolution Selection"
+msgstr ""
+
+#: ../src/gui/dialogs/autosaveDialog.cpp:39
+msgid "Remove &All"
+msgstr ""
+
+#: ../src/gui/dialogs/autosaveDialog.cpp:123
+msgid "Restore state?"
+msgstr ""
+
+#: ../src/gui/dialogs/autosaveDialog.cpp:133
+msgid "Multiple autosave states were found; would you like to restore one?"
+msgstr ""
+
 #: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:45
 msgid "Start Frame: "
 msgstr ""
@@ -512,12 +466,6 @@ msgstr ""
 msgid "From Table"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:104
-#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:350
-#: ../src/gui/dialogs/animateFilterDialog.cpp:196
-msgid "Frame"
-msgstr ""
-
 #: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:240
 msgid "Select text file..."
 msgstr ""
@@ -566,466 +514,317 @@ msgstr ""
 msgid "Accept data values"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:56
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:60
 msgid "Keyframe Data"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:57
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:61
 msgid "Transition"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:60
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:64
 msgid "Step"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:61
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:65
 msgid "Ramp"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:64
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1158
-msgid "Start Frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:66
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1159
-msgid "End Frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:69
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:73
 msgid "Initial Value"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:70
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:74
 msgid "startColour"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:71
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:75
 msgid "Final Value"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:72
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:76
 msgid "endColour"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:235
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:250
 msgid "Key Frame : Colour"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:237
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:252
 msgid "Colour at the start of the transtition"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:238
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:253
 msgid "Colour at end of transition"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:92
-msgid "Oak-Ridge RNG"
+#: ../src/gui/dialogs/prefDialog.cpp:73
+msgid "Panel Display"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:93
-msgid "Cameca/Ametek RRNG"
+#: ../src/gui/dialogs/prefDialog.cpp:75
+msgid "Online Updates"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:94
-msgid "Cameca/Ametek ENV"
+#: ../src/gui/dialogs/prefDialog.cpp:77 ../src/gui/dialogs/prefDialog.cpp:560
+msgid "Startup"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:156
-msgid "Key frames"
+#: ../src/gui/dialogs/prefDialog.cpp:78
+msgid "Camera Speed"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:157
-msgid "Output Data"
+#: ../src/gui/dialogs/prefDialog.cpp:79
+msgid "Available Filters"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:158
-msgid "Filters and properties"
+#: ../src/gui/dialogs/prefDialog.cpp:84
+msgid "Reset All"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:164
-msgid "Dir : "
+#: ../src/gui/dialogs/prefDialog.cpp:87
+msgid "Show all panels"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:167
-msgid "Output only when refresh required"
+#: ../src/gui/dialogs/prefDialog.cpp:88
+msgid "Remember last"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:169
-msgid "Data Types:"
+#: ../src/gui/dialogs/prefDialog.cpp:89
+msgid "Show Selected"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:170
-msgid "3D Images"
+#: ../src/gui/dialogs/prefDialog.cpp:92
+msgid "Control Pane"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:171
-msgid "File Suffix: "
+#: ../src/gui/dialogs/prefDialog.cpp:93
+msgid "Raw Data Panel"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:173
-msgid "Size : "
+#: ../src/gui/dialogs/prefDialog.cpp:94 ../src/gui/mainFrame.cpp:691
+msgid "Plot List"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:175
-msgid "..."
+#: ../src/gui/dialogs/prefDialog.cpp:96
+msgid "Periodically notify about available updates"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:176
-msgid "Point data"
+#: ../src/gui/dialogs/prefDialog.cpp:98
+msgid "Prefer orthographic at startup"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:178
-msgid "Voxel data"
+#: ../src/gui/dialogs/prefDialog.cpp:99
+msgid "Move Rate"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:179
-msgid "Range files"
+#: ../src/gui/dialogs/prefDialog.cpp:100 ../src/gui/dialogs/prefDialog.cpp:104
+msgid "(slow)"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:180
-msgid "Format"
+#: ../src/gui/dialogs/prefDialog.cpp:102 ../src/gui/dialogs/prefDialog.cpp:106
+msgid "(fast)"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:681
-msgid "transition frame"
+#: ../src/gui/dialogs/prefDialog.cpp:103
+msgid "Zoom Rate"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:681
-#: ../src/gui/mainFrame.cpp:1675
-msgid "Frame count"
+#: ../src/gui/dialogs/prefDialog.cpp:416
+msgid "Show all panels when starting program"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:753
-msgid "Key frame : Colour"
+#: ../src/gui/dialogs/prefDialog.cpp:419
+msgid "Show panels visible at last shutdown when starting program"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:806
-msgid "File existed, but was unable to read or interpret file contents."
+#: ../src/gui/dialogs/prefDialog.cpp:426
+msgid "Show selected panels when starting program"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:807
-msgid "String load failed"
+#: ../src/gui/dialogs/prefDialog.cpp:475
+msgid "Preferences"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:828
-msgid "Keyframe : decimal"
+#: ../src/gui/dialogs/prefDialog.cpp:477
+msgid "Set the method of panel layout when starting the program"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:837
-msgid "Keyframe : integer"
+#: ../src/gui/dialogs/prefDialog.cpp:480
+msgid ""
+"Lets the program check the internet to see if updates to the program version "
+"are available, then notifies you about updates now and again."
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:846
-msgid "Keyframe : 3D Point"
+#: ../src/gui/dialogs/prefDialog.cpp:482
+msgid ""
+"By default, use an orthographic camera at startup. State files will override "
+"this preference."
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:971
-msgid "Select or create new folder"
+#: ../src/gui/dialogs/prefDialog.cpp:483
+msgid "Camera translation, orbit and swivel rates. "
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1151
-msgid "Export Animation"
+#: ../src/gui/dialogs/prefDialog.cpp:484
+msgid "Camera zooming rate."
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1152
-msgid "Select filter"
+#: ../src/gui/dialogs/prefDialog.cpp:486
+msgid "Reset the filter initial values back to program defaults"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1153
-msgid "Select property"
+#: ../src/gui/dialogs/prefDialog.cpp:487
+msgid "Reset all filter initial values back to program defaults"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1155
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1175
-msgid "Filter"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1156
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1176
-msgid "Property"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1157
-#: ../src/backend/filters/voxelise.cpp:861
-#: ../src/backend/filters/spatialAnalysis.cpp:978
-#: ../src/backend/filters/transform.cpp:1119
-#: ../src/backend/filters/annotation.cpp:545
-#: ../src/backend/filters/annotation.cpp:551
-#: ../src/backend/filters/ionDownsample.cpp:465
-msgid "Mode"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1160
-msgid "Keyframe table"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1161
-msgid "Remove the selected keyframe from the table"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1162
-msgid "Enter where the animation frames will be exported to"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1163
-msgid "Browse to directory where the animation frames will be exported to"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1165
-msgid ""
-"Title for files, result will be saved as #-name.png, where # is image number."
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1166
-msgid "Target resolution (image size)"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1168
-msgid "Select frame for property display"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1169
-msgid "Enter frame number to change frame (eg 1/20)"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1170
-msgid "Save point data (POS files) in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1171
-msgid "Save plots (as text files) in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1172
-msgid "Save voxel data (raw files) in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1173
-msgid "Save range files  in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1178
-msgid "Animation parameters for current frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1179
-msgid "Abort animation"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1180
-msgid "Run Animation"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1251
-msgid "Filter view"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1252
-msgid "Frame view"
-msgstr ""
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:45
-msgid "Width :"
-msgstr ""
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:47
-msgid "Height :"
-msgstr ""
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:50
-#: ../src/gui/dialogs/prefDialog.cpp:85
-msgid "Reset"
+#: ../src/gui/dialogs/prefDialog.cpp:559
+msgid "Filt. Default"
 msgstr ""
 
-#: ../src/gui/dialogs/resolutionDialog.cpp:336
-msgid "Resolution Selection"
+#: ../src/gui/dialogs/prefDialog.cpp:561
+msgid "Camera"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:62
+#: ../src/gui/dialogs/ExportPos.cpp:63
 msgid "Export:"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:63
-#: ../src/backend/filters/boundingBox.cpp:527
+#: ../src/gui/dialogs/ExportPos.cpp:64
+#: ../src/backend/filters/boundingBox.cpp:567
 msgid "Visible"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:64
+#: ../src/gui/dialogs/ExportPos.cpp:65
 msgid "Selected Data"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:66
+#: ../src/gui/dialogs/ExportPos.cpp:67
 msgid "Available Data"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:72
+#: ../src/gui/dialogs/ExportPos.cpp:73
 msgid "Selection"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:97 ../src/gui/dialogs/ExportPos.cpp:100
+#: ../src/gui/dialogs/ExportPos.cpp:98 ../src/gui/dialogs/ExportPos.cpp:101
 msgid "Index"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:98 ../src/gui/dialogs/ExportPos.cpp:101
-#: ../src/backend/filters/compositionProfile.cpp:604
-#: ../src/backend/filters/spatialAnalysis.cpp:2282
-#: ../src/backend/filters/spatialAnalysis.cpp:2375
-#: ../src/backend/filters/spatialAnalysis.cpp:2435
-#: ../src/backend/filters/spatialAnalysis.cpp:3388
-#: ../src/backend/filters/spatialAnalysis.cpp:3591
-#: ../src/backend/filters/spatialAnalysis.cpp:3650
+#: ../src/gui/dialogs/ExportPos.cpp:99 ../src/gui/dialogs/ExportPos.cpp:102
+#: ../src/backend/filters/profile.cpp:604
+#: ../src/backend/filters/spatialAnalysis.cpp:2520
+#: ../src/backend/filters/spatialAnalysis.cpp:2613
+#: ../src/backend/filters/spatialAnalysis.cpp:2673
+#: ../src/backend/filters/spatialAnalysis.cpp:3628
+#: ../src/backend/filters/spatialAnalysis.cpp:3831
+#: ../src/backend/filters/spatialAnalysis.cpp:3890
 #: ../src/backend/filters/spectrumPlot.cpp:65
 msgid "Count"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:446
+#: ../src/gui/dialogs/ExportPos.cpp:451
 msgid "Export Pos Data"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:449
+#: ../src/gui/dialogs/ExportPos.cpp:454
 msgid "Tree of filters, select leaves to show ion data."
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:451
+#: ../src/gui/dialogs/ExportPos.cpp:456
 msgid "Add all data from all filters"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:452
+#: ../src/gui/dialogs/ExportPos.cpp:457
 msgid "Add all data from currently selected filter"
 msgstr ""
 
-#: ../src/gui/dialogs/ExportPos.cpp:453
+#: ../src/gui/dialogs/ExportPos.cpp:458
 msgid "Add selected data from currently selected filter"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:73
-msgid "Panel Display"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:75
-msgid "Online Updates"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:77 ../src/gui/dialogs/prefDialog.cpp:560
-msgid "Startup"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:78
-msgid "Camera Speed"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:79
-msgid "Available Filters"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:84
-msgid "Reset All"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:87
-msgid "Show all panels"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:88
-msgid "Remember last"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:89
-msgid "Show Selected"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:92
-msgid "Control Pane"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:93
-msgid "Raw Data Panel"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:94 ../src/gui/mainFrame.cpp:676
-msgid "Plot List"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:96
-msgid "Periodically notify about available updates"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:98
-msgid "Prefer orthographic at startup"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:221
+msgid "Show Overlays"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:99
-msgid "Move Rate"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:246
+msgid "e.g. H2O"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:100 ../src/gui/dialogs/prefDialog.cpp:104
-msgid "(slow)"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:561
+#: ../src/gui/dialogs/rangeEditDialog.cpp:695 ../src/gui/mainFrame.cpp:5966
+#: ../src/backend/filter.cpp:54
+msgid "Plot"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:102 ../src/gui/dialogs/prefDialog.cpp:106
-msgid "(fast)"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:562
+msgid "Short Name"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:103
-msgid "Zoom Rate"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:563
+msgid "Long Name"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:416
-msgid "Show all panels when starting program"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:564
+#: ../src/backend/filters/annotation.cpp:901
+#: ../src/backend/filters/voxelise.cpp:976
+#: ../src/backend/filters/profile.cpp:1155
+#: ../src/backend/filters/spectrumPlot.cpp:676
+msgid "Colour"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:419
-msgid "Show panels visible at last shutdown when starting program"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:697
+#: ../src/backend/filters/annotation.cpp:605
+#: ../src/backend/filters/annotation.cpp:646
+#: ../src/backend/filters/annotation.cpp:815
+msgid "Start"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:426
-msgid "Show selected panels when starting program"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:698
+#: ../src/backend/filters/annotation.cpp:613
+#: ../src/backend/filters/annotation.cpp:655
+#: ../src/backend/filters/annotation.cpp:823
+msgid "End"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:475
-msgid "Preferences"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1260
+msgid "Range or ion?"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:477
-msgid "Set the method of panel layout when starting the program"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1261
+msgid "Select type to add"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:480
-msgid ""
-"Lets the program check the internet to see if updates to the program version "
-"are available, then notifies you about updates now and again."
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1542
+msgid "Range Editor"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:482
-msgid ""
-"By default, use an orthographic camera at startup. State files will override "
-"this preference."
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1546
+msgid "Enable or disable all overlays"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:483
-msgid "Camera translation, orbit and swivel rates. "
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1547
+msgid "Entered overlays, use delete to remove"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:484
-msgid "Camera zooming rate."
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1548
+msgid "Available plots for ranging"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:486
-msgid "Reset the filter initial values back to program defaults"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1549
+msgid "Enter species to display as overlay, e.g. SiO2"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:487
-msgid "Reset all filter initial values back to program defaults"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1550
+msgid "Editable ranges"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:559
-msgid "Filt. Default"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1551
+msgid "Editable ions"
 msgstr ""
 
-#: ../src/gui/dialogs/prefDialog.cpp:561
-msgid "Camera"
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1588
+msgid "Overlay"
 msgstr ""
 
 #: ../src/gui/mainFrame.cpp:119
@@ -1050,12 +849,12 @@ msgstr ""
 msgid "Bounding Box"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:144 ../src/backend/filters/ionClip.cpp:628
+#: ../src/gui/mainFrame.cpp:144 ../src/backend/filters/ionClip.cpp:629
 #: ../src/backend/filters/ionClip.h:66
 msgid "Clipping"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:145 ../src/backend/filters/clusterAnalysis.h:150
+#: ../src/gui/mainFrame.cpp:145 ../src/backend/filters/clusterAnalysis.h:151
 msgid "Cluster Analysis"
 msgstr ""
 
@@ -1099,542 +898,546 @@ msgstr ""
 msgid "Voxelisation"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:442
+#: ../src/gui/mainFrame.cpp:451
 msgid "OpenGL Failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:443 ../src/gui/mainFrame.cpp:445
+#: ../src/gui/mainFrame.cpp:452 ../src/gui/mainFrame.cpp:454
 msgid ""
 "Unable to initialise the openGL (3D) panel. Program cannot start. Please "
 "check your video drivers."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:466
+#: ../src/gui/mainFrame.cpp:475
 msgid "&Open...\tCtrl+O"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:466
+#: ../src/gui/mainFrame.cpp:475
 msgid "Open state file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:467
+#: ../src/gui/mainFrame.cpp:476
 msgid "&Merge...\tCtrl+Shift+O"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:467
+#: ../src/gui/mainFrame.cpp:476
 msgid "Merge other file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:471
+#: ../src/gui/mainFrame.cpp:480
 msgid "&Recent"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:472
+#: ../src/gui/mainFrame.cpp:481
 msgid "&Save\tCtrl+S"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:472
+#: ../src/gui/mainFrame.cpp:481
 msgid "Save state to file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:474
+#: ../src/gui/mainFrame.cpp:483
 msgid "Save &As...\tCtrl+Shift+S"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:474
+#: ../src/gui/mainFrame.cpp:483
 msgid "Save current state to new file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:477
+#: ../src/gui/mainFrame.cpp:486
 msgid "&Plot...\tCtrl+P"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:477
+#: ../src/gui/mainFrame.cpp:486
 msgid "Export Current Plot"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:478
+#: ../src/gui/mainFrame.cpp:487
 msgid "&Image...\tCtrl+I"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:478
+#: ../src/gui/mainFrame.cpp:487
 msgid "Export Current 3D View"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:479
+#: ../src/gui/mainFrame.cpp:488
 msgid "Ion&s...\tCtrl+N"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:479
+#: ../src/gui/mainFrame.cpp:488
 msgid "Export Ion Data"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:480
+#: ../src/gui/mainFrame.cpp:489
 msgid "Ran&ges...\tCtrl+G"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:480
+#: ../src/gui/mainFrame.cpp:489
 msgid "Export Range Data"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:481
+#: ../src/gui/mainFrame.cpp:490
 msgid "&Animate Filters...\tCtrl+T"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:481
+#: ../src/gui/mainFrame.cpp:490
 msgid "Export Animated Filter"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:482
+#: ../src/gui/mainFrame.cpp:491
 msgid "Ani&mate Camera...\tCtrl+M"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:482
+#: ../src/gui/mainFrame.cpp:491
 msgid "Export Animated Camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:483
+#: ../src/gui/mainFrame.cpp:492
 msgid "Pac&kage...\tCtrl+K"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:483
+#: ../src/gui/mainFrame.cpp:492
 msgid "Export analysis package"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:485
+#: ../src/gui/mainFrame.cpp:494
 msgid "&Export"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:488
+#: ../src/gui/mainFrame.cpp:497
 msgid "&Quit\tCtrl+Q"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:488 ../src/gui/mainFrame.cpp:490
+#: ../src/gui/mainFrame.cpp:497 ../src/gui/mainFrame.cpp:499
 msgid "Exit Program"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:490
+#: ../src/gui/mainFrame.cpp:499
 msgid "E&xit"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:492
+#: ../src/gui/mainFrame.cpp:501
 msgid "&File"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:496
+#: ../src/gui/mainFrame.cpp:505
 msgid "&Background Colour...\tCtrl+B"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:496
+#: ../src/gui/mainFrame.cpp:505
 msgid "Change background colour"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:500
+#: ../src/gui/mainFrame.cpp:509
 msgid "&Control Pane\tF2"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:500 ../src/gui/mainFrame.cpp:503
+#: ../src/gui/mainFrame.cpp:509 ../src/gui/mainFrame.cpp:512
 msgid "Toggle left control pane"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:503
+#: ../src/gui/mainFrame.cpp:512
 msgid "&Control Pane\tAlt+C"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:509
+#: ../src/gui/mainFrame.cpp:518
 msgid "&Raw Data Pane\tF3"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:509 ../src/gui/mainFrame.cpp:512
+#: ../src/gui/mainFrame.cpp:518 ../src/gui/mainFrame.cpp:521
 msgid "Toggle raw data  pane (bottom)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:512
+#: ../src/gui/mainFrame.cpp:521
 msgid "&Raw Data Pane\tAlt+R"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:516
+#: ../src/gui/mainFrame.cpp:525
 msgid "&Plot List\tF4"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:516 ../src/gui/mainFrame.cpp:518
+#: ../src/gui/mainFrame.cpp:525 ../src/gui/mainFrame.cpp:527
 msgid "Toggle plot list"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:518
+#: ../src/gui/mainFrame.cpp:527
 msgid "&Plot List\tAlt+P"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:524
+#: ../src/gui/mainFrame.cpp:533
 msgid "&Legend\tCtrl+L"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:524
+#: ../src/gui/mainFrame.cpp:533
 msgid "Toggle Legend display"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:526
+#: ../src/gui/mainFrame.cpp:535
 msgid "P&lot..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:527
+#: ../src/gui/mainFrame.cpp:536
 msgid "&Axis\tCtrl+Shift+I"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:527
+#: ../src/gui/mainFrame.cpp:536
 msgid "Toggle World Axis display"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:532
+#: ../src/gui/mainFrame.cpp:541
 msgid "&Fullscreen mode\tF11"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:532 ../src/gui/mainFrame.cpp:534
+#: ../src/gui/mainFrame.cpp:541 ../src/gui/mainFrame.cpp:543
 msgid "Next fullscreen mode: with toolbars"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:534
+#: ../src/gui/mainFrame.cpp:543
 msgid "&Fullscreen mode\tCtrl+Shift+F"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:539
+#: ../src/gui/mainFrame.cpp:548
 msgid "&Undo\tCtrl+Z"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:541
+#: ../src/gui/mainFrame.cpp:550
 msgid "&Redo\tCtrl+Y"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:544
+#: ../src/gui/mainFrame.cpp:553
 msgid "&Range"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:547
+#: ../src/gui/mainFrame.cpp:556
 msgid "&Preferences"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:549
+#: ../src/gui/mainFrame.cpp:558
 msgid "&Edit"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:552
+#: ../src/gui/mainFrame.cpp:561
 msgid "&View"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:554
+#: ../src/gui/mainFrame.cpp:563
 msgid "&Help...\tCtrl+H"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:554
+#: ../src/gui/mainFrame.cpp:563
 msgid "Show help files and documentation"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:555
+#: ../src/gui/mainFrame.cpp:564
 msgid "&Contact..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:555
+#: ../src/gui/mainFrame.cpp:564
 msgid "Open contact page"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:557
+#: ../src/gui/mainFrame.cpp:566
 msgid "&About..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:557
+#: ../src/gui/mainFrame.cpp:566
 msgid "Information about this program"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:558
+#: ../src/gui/mainFrame.cpp:567
 msgid "&Help"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:560
+#: ../src/gui/mainFrame.cpp:569
 msgid "Stashed Filters"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:565
+#: ../src/gui/mainFrame.cpp:574
 msgid "New Filters"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:595
+#: ../src/gui/mainFrame.cpp:604
 msgid "Auto Refresh"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:601
+#: ../src/gui/mainFrame.cpp:610
 msgid "Filter settings"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:604
+#: ../src/gui/mainFrame.cpp:613
 msgid "Camera Name"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:611
+#: ../src/gui/mainFrame.cpp:625
+msgid "Resize to Fit"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:627
 msgid "3D Post-processing"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:613
+#: ../src/gui/mainFrame.cpp:629
 msgid "Enable Cropping"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:615 ../src/gui/mainFrame.cpp:626
+#: ../src/gui/mainFrame.cpp:631 ../src/gui/mainFrame.cpp:642
 msgid "x-y"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:616 ../src/gui/mainFrame.cpp:627
+#: ../src/gui/mainFrame.cpp:632 ../src/gui/mainFrame.cpp:643
 msgid "x-z"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:617 ../src/gui/mainFrame.cpp:628
+#: ../src/gui/mainFrame.cpp:633 ../src/gui/mainFrame.cpp:644
 msgid "y-x"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:618 ../src/gui/mainFrame.cpp:629
+#: ../src/gui/mainFrame.cpp:634 ../src/gui/mainFrame.cpp:645
 msgid "y-z"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:619 ../src/gui/mainFrame.cpp:630
+#: ../src/gui/mainFrame.cpp:635 ../src/gui/mainFrame.cpp:646
 msgid "z-x"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:620 ../src/gui/mainFrame.cpp:631
+#: ../src/gui/mainFrame.cpp:636 ../src/gui/mainFrame.cpp:647
 msgid "z-y"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:635
+#: ../src/gui/mainFrame.cpp:651
 msgid "Use camera coordinates"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:636
+#: ../src/gui/mainFrame.cpp:652
 msgid "dX"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:638
+#: ../src/gui/mainFrame.cpp:654
 msgid "dY"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:640
+#: ../src/gui/mainFrame.cpp:656
 msgid "dZ"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:642
+#: ../src/gui/mainFrame.cpp:658
 msgid "Enable Anaglyphic Stereo"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:643
+#: ../src/gui/mainFrame.cpp:659
 msgid "Flip Channels"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:644
+#: ../src/gui/mainFrame.cpp:660
 msgid "Anaglyph Mode"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:646
+#: ../src/gui/mainFrame.cpp:662
 msgid "Red-Blue"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:647
+#: ../src/gui/mainFrame.cpp:663
 msgid "Red-Green"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:648
+#: ../src/gui/mainFrame.cpp:664
 msgid "Red-Cyan"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:649
+#: ../src/gui/mainFrame.cpp:665
 msgid "Green-Magenta"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:653
+#: ../src/gui/mainFrame.cpp:669
 msgid "Baseline Separation"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:655 ../src/backend/filters/voxelise.cpp:937
-#: ../src/backend/filters/voxelise.cpp:1105
-#: ../src/backend/filters/compositionProfile.cpp:1143
-#: ../src/backend/filters/boundingBox.cpp:654
-#: ../src/backend/filters/annotation.cpp:906
+#: ../src/gui/mainFrame.cpp:671 ../src/backend/filters/annotation.cpp:906
+#: ../src/backend/filters/voxelise.cpp:938
+#: ../src/backend/filters/voxelise.cpp:1106
+#: ../src/backend/filters/profile.cpp:1164
+#: ../src/backend/filters/boundingBox.cpp:731
 #: ../src/backend/filters/dataLoad.cpp:666
-#: ../src/backend/filters/spectrumPlot.cpp:675
+#: ../src/backend/filters/spectrumPlot.cpp:683
 msgid "Appearance"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:656
+#: ../src/gui/mainFrame.cpp:672
 msgid "Smooth && translucent objects"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:658
+#: ../src/gui/mainFrame.cpp:674
 msgid "3D lighting"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:661
+#: ../src/gui/mainFrame.cpp:677
 msgid "Performance"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:662
+#: ../src/gui/mainFrame.cpp:678
 msgid "Fast and weak randomisation."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:664
+#: ../src/gui/mainFrame.cpp:680
 msgid "Limit Output Pts"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:670
+#: ../src/gui/mainFrame.cpp:685
 msgid "Filter caching"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:672
+#: ../src/gui/mainFrame.cpp:687
 msgid "Max. Ram usage (%)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:743
+#: ../src/gui/mainFrame.cpp:759
 msgid "Warning: Your configuration file appears to be invalid:\n"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:744
+#: ../src/gui/mainFrame.cpp:760
 msgid "\tConfig Load: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1018
+#: ../src/gui/mainFrame.cpp:1054
 msgid "Current state has not been saved, would you like to save it now?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1019
+#: ../src/gui/mainFrame.cpp:1055
 msgid "State changed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1037
+#: ../src/gui/mainFrame.cpp:1073
 msgid "Readable files (*.xml, *.pos, *.txt,*.csv, *.ato)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1039
+#: ../src/gui/mainFrame.cpp:1075
 msgid "XML State File (*.xml)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1040
+#: ../src/gui/mainFrame.cpp:1076
 msgid "POS File (*.pos)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1041
+#: ../src/gui/mainFrame.cpp:1077
 msgid "LAWATAP ATO File (*.ato)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1042
+#: ../src/gui/mainFrame.cpp:1078
 msgid "Text File (*.txt, *.csv)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1043
+#: ../src/gui/mainFrame.cpp:1079
 msgid "All Files (*)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1056 ../src/gui/mainFrame.cpp:1112
+#: ../src/gui/mainFrame.cpp:1092 ../src/gui/mainFrame.cpp:1141
 msgid "Select Data or State File..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1113
+#: ../src/gui/mainFrame.cpp:1142
 msgid ""
 "3Depict file (*.xml, *.pos,*.txt)|*.xml;*.pos;*.txt|POS File (*.pos)|*.pos|"
 "XML State File (*.xml)|*.xml|All Files (*)|*"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1124
+#: ../src/gui/mainFrame.cpp:1153
 msgid "Merged file."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1231
+#: ../src/gui/mainFrame.cpp:1256
 msgid "Tip: You can use ⌘ (command) to merge"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1233
+#: ../src/gui/mainFrame.cpp:1258
 msgid "Tip: You can use ctrl to merge"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1276
+#: ../src/gui/mainFrame.cpp:1292
 msgid "Load error"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1277
+#: ../src/gui/mainFrame.cpp:1293
 msgid ""
 "Error loading state file.\n"
 "See console for more info."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1285
+#: ../src/gui/mainFrame.cpp:1301
 msgid ""
 "This state file contains filters that can be unsafe to run\n"
 "Do you wish to remove these before continuing?."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1286
+#: ../src/gui/mainFrame.cpp:1302
 msgid "Security warning"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1469 ../src/gui/mainFrame.cpp:1565
-#: ../src/gui/mainFrame.cpp:1990
+#: ../src/gui/mainFrame.cpp:1484 ../src/gui/mainFrame.cpp:1580
+#: ../src/gui/mainFrame.cpp:2010
 msgid "Unable to save"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1470
+#: ../src/gui/mainFrame.cpp:1485
 msgid "No plot available. Please create a plot before exporting."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1474
+#: ../src/gui/mainFrame.cpp:1489
 msgid "Save plot..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1475
+#: ../src/gui/mainFrame.cpp:1490
 msgid ""
 "By Extension (svg,png)|*.svg;*.png|Scalable Vector Graphics File (*.svg)|*."
 "svg|PNG File (*.png)|*.png|All Files (*)|*"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1529
+#: ../src/gui/mainFrame.cpp:1544
 msgid "Select type for save"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1530
+#: ../src/gui/mainFrame.cpp:1545
 msgid "Choose file type"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1550 ../src/gui/mainFrame.cpp:1607
-#: ../src/gui/mainFrame.cpp:1643
+#: ../src/gui/mainFrame.cpp:1565 ../src/gui/mainFrame.cpp:1622
+#: ../src/gui/mainFrame.cpp:1658
 msgid "Choose resolution"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1566
+#: ../src/gui/mainFrame.cpp:1581
 msgid "Unknown file extension. Please use \"svg\" or \"png\""
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1577
+#: ../src/gui/mainFrame.cpp:1592
 msgid "Saved plot: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1584 ../src/gui/mainFrame.cpp:1636
+#: ../src/gui/mainFrame.cpp:1599 ../src/gui/mainFrame.cpp:1651
 msgid "Save Image..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1585 ../src/gui/mainFrame.cpp:1637
+#: ../src/gui/mainFrame.cpp:1600 ../src/gui/mainFrame.cpp:1652
 msgid "PNG File (*.png)|*.png|All Files (*)|*"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1599
+#: ../src/gui/mainFrame.cpp:1614
 msgid "File already exists. Overwrite?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1600 ../src/gui/mainFrame.cpp:2378
-#: ../src/gui/mainFrame.cpp:2475 ../src/gui/mainFrame.cpp:2498
+#: ../src/gui/mainFrame.cpp:1615 ../src/gui/mainFrame.cpp:2407
+#: ../src/gui/mainFrame.cpp:2513 ../src/gui/mainFrame.cpp:2536
 msgid "Overwrite?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1627 ../src/gui/mainFrame.cpp:1703
+#: ../src/gui/mainFrame.cpp:1642 ../src/gui/mainFrame.cpp:1718
 msgid "Saved 3D View :"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1657
+#: ../src/gui/mainFrame.cpp:1672
 msgid "Program limitation"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1658
+#: ../src/gui/mainFrame.cpp:1673
 msgid ""
 "Limitation on the screenshot dimension; please ensure that both width and "
 "height exceed the initial values,\n"
@@ -1642,367 +1445,386 @@ msgid ""
 " If this bothers, please submit a bug."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1675
+#: ../src/gui/mainFrame.cpp:1690
 msgid "Number of frames"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1835
+#: ../src/gui/mainFrame.cpp:1744
+msgid "Abo&rt"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:1746
+msgid "&Refresh"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:1855
 msgid "Cannot animate with no filters."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1913
+#: ../src/gui/mainFrame.cpp:1933
 msgid "Animating"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1914
+#: ../src/gui/mainFrame.cpp:1934
 msgid "Performing refresh"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1940
+#: ../src/gui/mainFrame.cpp:1960
 msgid "Filter property change failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1962
+#: ../src/gui/mainFrame.cpp:1982
 msgid "Refresh failed on frame :"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1991
+#: ../src/gui/mainFrame.cpp:2011
 msgid "Image save failed for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2016
+#: ../src/gui/mainFrame.cpp:2036
 msgid "Ion save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2017
+#: ../src/gui/mainFrame.cpp:2037
 msgid "Unable to save ions for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2048
+#: ../src/gui/mainFrame.cpp:2068
 msgid "Plot save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2049
+#: ../src/gui/mainFrame.cpp:2069
 msgid "Unable to save plot or frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2090
+#: ../src/gui/mainFrame.cpp:2110
 msgid "Range save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2091
+#: ../src/gui/mainFrame.cpp:2111
 msgid "Unable to save range for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2120
+#: ../src/gui/mainFrame.cpp:2140
 msgid "Voxel save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2121
+#: ../src/gui/mainFrame.cpp:2141
 msgid "Unable to save voxels for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2150
+#: ../src/gui/mainFrame.cpp:2170
 msgid "Animate failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2174 ../src/gui/mainFrame.cpp:2333
-#: ../src/gui/mainFrame.cpp:2430
+#: ../src/gui/mainFrame.cpp:2194 ../src/gui/mainFrame.cpp:2360
+#: ../src/gui/mainFrame.cpp:2468
 msgid "No filters means no data to export"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2188
+#: ../src/gui/mainFrame.cpp:2208
 msgid "Package name"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2189
+#: ../src/gui/mainFrame.cpp:2209
 msgid "Package directory name"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2191
+#: ../src/gui/mainFrame.cpp:2211
 msgid "AnalysisPackage"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2204
+#: ../src/gui/mainFrame.cpp:2224
 msgid "Package folder already exists, won't overwrite."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2205
+#: ../src/gui/mainFrame.cpp:2225
 msgid "Not available"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2230
+#: ../src/gui/mainFrame.cpp:2250
 msgid ""
 "Package folder creation failed\n"
 "check writing to this location is possible."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2231
+#: ../src/gui/mainFrame.cpp:2251
 msgid "Folder creation failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2251
+#: ../src/gui/mainFrame.cpp:2271
 msgid "Copying"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2252
+#: ../src/gui/mainFrame.cpp:2272
 msgid "Copying referenced files"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2311
+#: ../src/gui/mainFrame.cpp:2338
 msgid "Error copying file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2320
+#: ../src/gui/mainFrame.cpp:2347
 msgid "Saved package: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2344
+#: ../src/gui/mainFrame.cpp:2371
 msgid "Export"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2349
-msgid "POS Data (*.pos)|*.pos|All Files (*)|*"
+#: ../src/gui/mainFrame.cpp:2377
+msgid ""
+"POS Data (*.pos)|*.pos|Text File (*.txt)|*.txt|VTK Legacy (*.vtk)|*.vtk|All "
+"Files (*)|*"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2377 ../src/gui/mainFrame.cpp:2474
+#: ../src/gui/mainFrame.cpp:2406 ../src/gui/mainFrame.cpp:2512
 msgid "File already exists, overwrite?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2409
+#: ../src/gui/mainFrame.cpp:2447
 msgid "Saved ions: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2434
+#: ../src/gui/mainFrame.cpp:2472
 msgid "Export Ranges"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2456
+#: ../src/gui/mainFrame.cpp:2494
 msgid "Save state..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2457
+#: ../src/gui/mainFrame.cpp:2495
 msgid "XML state file (*.xml)|*.xml|All Files (*)|*"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2497
+#: ../src/gui/mainFrame.cpp:2535
 msgid "Files have been referred to using relative paths. Keep relative paths?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2530
+#: ../src/gui/mainFrame.cpp:2568
 msgid "Saved state: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2606
+#: ../src/gui/mainFrame.cpp:2644
 msgid "Range editor"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2863
+#: ../src/gui/mainFrame.cpp:2901
 msgid "Manual not found locally. Launching web browser"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2872
+#: ../src/gui/mainFrame.cpp:2910
 msgid "Opening contact page in external web browser"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2880
+#: ../src/gui/mainFrame.cpp:2918
 msgid "No filter stashes to edit."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2884
+#: ../src/gui/mainFrame.cpp:2922
 msgid "Filter Stashes"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2901
+#: ../src/gui/mainFrame.cpp:2939
 msgid "Quick and dirty analysis for point data."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2911
+#: ../src/gui/mainFrame.cpp:2949
 msgid "Compiled with wx Version: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2932
+#: ../src/gui/mainFrame.cpp:2970
 msgid "Press enter to store new stash"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2938
+#: ../src/gui/mainFrame.cpp:2976
 msgid "Press enter to restore stash"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2971
+#: ../src/gui/mainFrame.cpp:3009
 msgid "Unable to create stash, selection invalid"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2978
+#: ../src/gui/mainFrame.cpp:3016
 msgid "Created new filter tree stash"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3083
+#: ../src/gui/mainFrame.cpp:3123
 msgid "Filter type not a data source - can't be at tree base"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3223
+#: ../src/gui/mainFrame.cpp:3263
 msgid "Moving - Hold ⌘ (command) to copy"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3225
+#: ../src/gui/mainFrame.cpp:3265
 msgid "Moving - Hold control to copy"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3545
+#: ../src/gui/mainFrame.cpp:3604
 msgid "Press enter to store new camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3547
+#: ../src/gui/mainFrame.cpp:3606
 msgid "Press enter to restore camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3572 ../src/gui/mainFrame.cpp:3613
+#: ../src/gui/mainFrame.cpp:3631 ../src/gui/mainFrame.cpp:3672
 msgid "Restored camera: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3590
+#: ../src/gui/mainFrame.cpp:3649
 msgid "Stored camera: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3676
+#: ../src/gui/mainFrame.cpp:3735
 msgid "Select an item from the filter tree before choosing a new filter"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3678
+#: ../src/gui/mainFrame.cpp:3737
 msgid "Load data source (file->open) before choosing a new filter"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3704
+#: ../src/gui/mainFrame.cpp:3763
 msgid "Select RNG File..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3725
+#: ../src/gui/mainFrame.cpp:3784
 msgid "Failed reading range file."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3729
+#: ../src/gui/mainFrame.cpp:3788
 msgid "Error loading file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3788 ../src/gui/mainFrame.cpp:3882
-#: ../src/gui/mainFrame.cpp:5284 ../src/gui/mainFrame.cpp:5803
+#: ../src/gui/mainFrame.cpp:3849 ../src/gui/mainFrame.cpp:3944
+#: ../src/gui/mainFrame.cpp:5449 ../src/gui/mainFrame.cpp:5968
 msgid "Cons."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3844
+#: ../src/gui/mainFrame.cpp:3907
 msgid "Refresh Aborted."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3886
+#: ../src/gui/mainFrame.cpp:3948
 msgid "*Cons."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3888
+#: ../src/gui/mainFrame.cpp:3950
 msgid "§Cons."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3945
+#: ../src/gui/mainFrame.cpp:4007
 msgid "Complete"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4030
+#: ../src/gui/mainFrame.cpp:4105
 msgid "msgs"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4071
+#: ../src/gui/mainFrame.cpp:4146
 msgid "Autosave complete."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4281
+#: ../src/gui/mainFrame.cpp:4350
 msgid "Aborting...."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4344
+#: ../src/gui/mainFrame.cpp:4416
 msgid "Updated."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4352
+#: ../src/gui/mainFrame.cpp:4425
+msgid "Calculating..."
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:4428
 msgid "\\% Done (Esc aborts)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4354
+#: ../src/gui/mainFrame.cpp:4430
 msgid "\\% Done"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4624
+#: ../src/gui/mainFrame.cpp:4704
 msgid "Tip: You can shift-click to force full refresh, if required"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4686
+#: ../src/gui/mainFrame.cpp:4766
 msgid "No data to save"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4860
+#: ../src/gui/mainFrame.cpp:4950
 msgid "Aborting..."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4866
+#: ../src/gui/mainFrame.cpp:4956
 msgid ""
 "Waiting for refresh to abort. Exiting could lead to the program "
 "backgrounding. Exit anyway? "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4867 ../src/gui/mainFrame.cpp:4887
+#: ../src/gui/mainFrame.cpp:4957 ../src/gui/mainFrame.cpp:4977
 msgid "Confirmation request"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4886
+#: ../src/gui/mainFrame.cpp:4976
 msgid "Are you sure you wish to exit 3Depict?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5312
+#: ../src/gui/mainFrame.cpp:5314 ../src/gl/cameras.cpp:627
+#: ../src/gl/cameras.cpp:730
+msgid "Orthogonal"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:5477
 msgid "Update Notice: New version "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5312
+#: ../src/gui/mainFrame.cpp:5477
 msgid " found online."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5316
+#: ../src/gui/mainFrame.cpp:5481
 msgid "Online Check: "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5316
+#: ../src/gui/mainFrame.cpp:5481
 msgid " is up-to-date."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5406
+#: ../src/gui/mainFrame.cpp:5571
 msgid "An auto-save state was found, would you like to restore it?."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5407
+#: ../src/gui/mainFrame.cpp:5572
 msgid "Autosave"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5414
+#: ../src/gui/mainFrame.cpp:5579
 msgid "Unable to load autosave file.."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5605
+#: ../src/gui/mainFrame.cpp:5770
 msgid "List of available filters"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5607
+#: ../src/gui/mainFrame.cpp:5772
 msgid "Tree - drag to move items, hold ⌘ for copy. Tap delete to remove items"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5609
+#: ../src/gui/mainFrame.cpp:5774
 msgid ""
 "Tree - drag to move items, hold Ctrl for copy. Tap delete to remove items."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5611
+#: ../src/gui/mainFrame.cpp:5776
 msgid ""
 "Enable/Disable automatic updates of data when filter change takes effect"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5614
+#: ../src/gui/mainFrame.cpp:5779
 msgid ""
 "Enable/Disable \"Alpha blending\" (transparency) in rendering system. "
 "Blending is used to smooth objects (avoids artefacts known as \"jaggies\") "
@@ -2010,14 +1832,14 @@ msgid ""
 "but look more blocky"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5615
+#: ../src/gui/mainFrame.cpp:5780
 msgid ""
 "Enable/Disable lighting calculations in rendering, for objects that request "
 "this. Lighting provides important depth cues for objects comprised of 3D "
 "surfaces. Disabling may allow faster rendering in complex scenes"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5616
+#: ../src/gui/mainFrame.cpp:5781
 msgid ""
 "Enable/Disable weak randomisation (Galois linear feedback shift register). "
 "Strong randomisation uses a much slower random selection method, but "
@@ -2025,14 +1847,14 @@ msgid ""
 "recommended for final analyses"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5618
+#: ../src/gui/mainFrame.cpp:5783
 msgid ""
 "Limit the number of points that can be displayed in the 3D  scene. Does not "
 "affect filter tree calculations. Disabling this can severely reduce "
 "performance, due to large numbers of points being visible at once."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5619
+#: ../src/gui/mainFrame.cpp:5784
 msgid ""
 "Enable/Disable caching of intermediate results during filter updates. "
 "Disabling caching will use less system RAM, though changes to any filter "
@@ -2040,2195 +1862,2733 @@ msgid ""
 "computations"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5621
+#: ../src/gui/mainFrame.cpp:5786
 msgid "Camera data information"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5625
+#: ../src/gui/mainFrame.cpp:5790
 msgid "Enable/disable visual effects on final 3D output"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5627
+#: ../src/gui/mainFrame.cpp:5792
 msgid "Enable cropping post-process effect"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5630
+#: ../src/gui/mainFrame.cpp:5795
 msgid ""
 "Colour based 3D effect enable/disable - requires appropriate colour filter "
 "3D glasses."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5631
+#: ../src/gui/mainFrame.cpp:5796
 msgid "Glasses colour mode"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5633
+#: ../src/gui/mainFrame.cpp:5798
 msgid ""
 "Level of separation between left and right images, which sets 3D depth to "
 "visual distortion tradeoff"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5637
+#: ../src/gui/mainFrame.cpp:5802
 msgid "X"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5638
+#: ../src/gui/mainFrame.cpp:5803
 msgid "Y"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5639
+#: ../src/gui/mainFrame.cpp:5804
 msgid "Save raw data to file"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5640
+#: ../src/gui/mainFrame.cpp:5805
 msgid "Copy raw data to clipboard"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5641
+#: ../src/gui/mainFrame.cpp:5806
 msgid "Manage \"stashed\" data."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5642
+#: ../src/gui/mainFrame.cpp:5807
 msgid "Program text output"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5643
+#: ../src/gui/mainFrame.cpp:5808
 msgid "Select active camera, or type to create new named camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5644
+#: ../src/gui/mainFrame.cpp:5809
 msgid "Remove the selected camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5645
+#: ../src/gui/mainFrame.cpp:5810
 msgid "Perform cropping from coordinate frame of camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5646
+#: ../src/gui/mainFrame.cpp:5811
 msgid ""
 "Set the maximum amount of RAM to use in order to speed repeat computations"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5647
+#: ../src/gui/mainFrame.cpp:5812
 msgid "Collapse the filter tree"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5648
+#: ../src/gui/mainFrame.cpp:5813
 msgid "Expand the filter tree"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5649
+#: ../src/gui/mainFrame.cpp:5814
 msgid "Process the filter tree, hold shift to purge cached filter data"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5763
+#: ../src/gui/mainFrame.cpp:5928
 msgid "Crop"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5764
+#: ../src/gui/mainFrame.cpp:5929
 msgid "Stereo"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5781
+#: ../src/gui/mainFrame.cpp:5946
 #: ../src/backend/filters/externalProgram.cpp:596
-#: ../src/backend/filters/ionColour.cpp:316
-#: ../src/backend/filters/spectrumPlot.cpp:604
+#: ../src/backend/filters/ionColour.cpp:308
+#: ../src/backend/filters/spectrumPlot.cpp:612
 msgid "Data"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5782
+#: ../src/gui/mainFrame.cpp:5947
 msgid "Cam"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5783
+#: ../src/gui/mainFrame.cpp:5948
 msgid "Post"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5784
+#: ../src/gui/mainFrame.cpp:5949
 msgid "Tools"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5802
+#: ../src/gui/mainFrame.cpp:5967
 msgid "Raw"
 msgstr ""
 
+#: ../src/gui/mainFrame.cpp:6010
+msgid "Align Camera"
+msgstr ""
+
 #: ../src/gui/mathglPane.cpp:259
 msgid "No plots selected."
 msgstr ""
 
-#: ../src/gui/mathglPane.cpp:1198
+#: ../src/gui/mathglPane.cpp:1201
 msgid ""
 "Unable to allocate requested memory.\n"
 " Try a lower resolution, or save as vector (SVG)."
 msgstr ""
 
-#: ../src/gui/mathglPane.cpp:1200
+#: ../src/gui/mathglPane.cpp:1203
 msgid "Plotting functions returned an error:\n"
 msgstr ""
 
-#: ../src/gui/mathglPane.cpp:1202
+#: ../src/gui/mathglPane.cpp:1205
 msgid "File readback check failed"
 msgstr ""
 
-#: ../src/gui/mathglPane.cpp:1204
+#: ../src/gui/mathglPane.cpp:1207
 msgid "Filesize during readback appears to be zero."
 msgstr ""
 
-#: ../src/3Depict.cpp:375
-msgid "File : "
+#: ../src/backend/filter.cpp:55
+msgid "2D Plot"
 msgstr ""
 
-#: ../src/3Depict.cpp:375
-msgid " does not exist. Skipping"
+#: ../src/backend/filter.cpp:56
+msgid "Draw"
 msgstr ""
 
-#: ../src/backend/configFile.cpp:187
-msgid "Config file present, but is not valid (root node test)"
+#: ../src/backend/filter.cpp:57
+msgid "Range"
 msgstr ""
 
-#: ../src/backend/configFile.cpp:228
-msgid "Unable to interpret recent file entry"
+#: ../src/backend/filter.cpp:58
+msgid "Voxel"
 msgstr ""
 
-#: ../src/backend/configFile.cpp:268
-msgid "Unable to determine filter type in defaults listing."
+#: ../src/backend/filter.cpp:192 ../src/backend/filters/ionColour.cpp:411
+msgid "Aborted"
 msgstr ""
 
-#: ../src/backend/configFile.cpp:605
-msgid "Online access for non win32/apple platforms is intentionally disabled, "
+#: ../src/backend/state.cpp:151
+msgid ""
+"This file is a \"state\" file for the 3Depict program, and stores "
+"information about a particular analysis session. This file should be a valid "
+"\"XML\" file"
 msgstr ""
 
-#: ../src/backend/configFile.cpp:606
+#: ../src/backend/state.cpp:319
+msgid "Failed to allocate parser"
+msgstr ""
+
+#: ../src/backend/state.cpp:354
 msgid ""
-"regardless of the settings you use here. Use your package manager to keep up-"
-"to-date"
+"Unable to retrieve root node in input state file... Is this really a non-"
+"empty XML file?"
 msgstr ""
 
-#: ../src/backend/plot.cpp:28 ../src/backend/filters/algorithms/mass.cpp:25
-#: ../src/backend/filters/voxelise.cpp:124
-#: ../src/backend/filters/voxelise.cpp:130
-#: ../src/backend/filters/spectrumPlot.cpp:76
-msgid "None"
+#: ../src/backend/state.cpp:361
+msgid "Base state node missing. Is this really a state XML file??"
 msgstr ""
 
-#: ../src/backend/plot.cpp:29
-msgid "Moving avg."
+#: ../src/backend/state.cpp:390
+msgid "State was created by a newer version of this program.. "
 msgstr ""
 
-#: ../src/backend/plot.cpp:33
-msgid "Lines"
+#: ../src/backend/state.cpp:391
+msgid "file reading will continue, but may fail."
 msgstr ""
 
-#: ../src/backend/plot.cpp:34
-msgid "Bars"
+#: ../src/backend/state.cpp:396
+msgid ""
+"Warning, unparseable version number in state file. File reading will "
+"continue, but may fail"
+msgstr ""
+
+#: ../src/backend/state.cpp:403
+msgid "Unable to find the \"writer\" node"
+msgstr ""
+
+#: ../src/backend/state.cpp:413
+msgid "Unable to find the \"backcolour\" node."
+msgstr ""
+
+#: ../src/backend/state.cpp:420
+msgid "\"backcolour\" node missing \"r\" value."
+msgstr ""
+
+#: ../src/backend/state.cpp:425
+msgid "Unable to interpret \"backColour\" node's \"r\" value."
+msgstr ""
+
+#: ../src/backend/state.cpp:433
+msgid "\"backcolour\" node missing \"g\" value."
+msgstr ""
+
+#: ../src/backend/state.cpp:439
+msgid "Unable to interpret \"backColour\" node's \"g\" value."
+msgstr ""
+
+#: ../src/backend/state.cpp:447
+msgid "\"backcolour\" node missing \"b\" value."
+msgstr ""
+
+#: ../src/backend/state.cpp:453
+msgid "Unable to interpret \"backColour\" node's \"b\" value."
+msgstr ""
+
+#: ../src/backend/state.cpp:460
+msgid "\"backcolour\"s rgb values must be in range [0,1]"
+msgstr ""
+
+#: ../src/backend/state.cpp:488
+msgid "Unable to find or interpret \"showaxis\" node"
+msgstr ""
+
+#: ../src/backend/state.cpp:532
+msgid "Unable to locate \"filtertree\" node."
+msgstr ""
+
+#: ../src/backend/state.cpp:548
+msgid "Cameras section missing \"active\" node."
+msgstr ""
+
+#: ../src/backend/state.cpp:556
+msgid "Unable to find property \"value\"  for \"cameras->active\" node."
+msgstr ""
+
+#: ../src/backend/state.cpp:562
+msgid "Unable to interpret property \"value\"  for \"cameras->active\" node."
+msgstr ""
+
+#: ../src/backend/state.cpp:582
+msgid "Failed to interpret camera state for camera : "
+msgstr ""
+
+#: ../src/backend/state.cpp:590
+msgid "Unable to interpret the camera type for camera : "
+msgstr ""
+
+#: ../src/backend/state.cpp:648
+msgid "Unable to locate stash name for stash "
+msgstr ""
+
+#: ../src/backend/state.cpp:655
+msgid "Empty stash name for stash "
+msgstr ""
+
+#: ../src/backend/state.cpp:664
+msgid "No filter tree for stash:"
+msgstr ""
+
+#: ../src/backend/state.cpp:670
+msgid "For stash "
+msgstr ""
+
+#: ../src/backend/state.cpp:702
+msgid "Unrecognised effect :"
+msgstr ""
+
+#: ../src/backend/state.cpp:712
+msgid "Duplicate effect found"
+msgstr ""
+
+#: ../src/backend/state.cpp:712
+msgid " cannot use."
+msgstr ""
+
+#: ../src/backend/state.cpp:722
+msgid "Error reading effect : "
+msgstr ""
+
+#: ../src/backend/state.cpp:927
+msgid "-merge"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:44 ../src/backend/APT/APTFileIO.cpp:79
+#: ../src/backend/APT/APTFileIO.cpp:103
+msgid "Error opening file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:45
+msgid "Only found header, no data"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:46
+msgid "Unable to reopen file after first scan"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:47
+msgid "Error whilst reading file contents"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:48 ../src/backend/APT/APTFileIO.cpp:49
+msgid "Unexpected file format"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:50
+msgid "Insufficient memory to continue"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:54
+msgid "Memory allocation failure on POS load"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:55
+msgid "Error opening pos file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:56
+msgid "Pos file empty"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:57
+msgid "Pos file size appears to have non-integer number of entries"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:58
+msgid "Error reading from pos file (after open)"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:59
+msgid "Error - Found NaN in pos file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:60
+msgid "Error - Found Inf in pos file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:61
+msgid "Pos load aborted by interrupt."
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:80
+msgid "No numerical data found"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:81
+msgid "Error re-opening file, after first scan"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:82
+msgid "Unable to read file contents after open"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:83
+msgid "Error interpreting field in file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:84
+msgid "Incorrect number of fields in file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:85 ../src/backend/APT/APTFileIO.cpp:107
+msgid "Unable to allocate memory to store data"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:104
+msgid "File is empty"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:105
+msgid "Filesize does not match expected format"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:106
+msgid "File version number not <4, as expected"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:108
+msgid "Unable to detect endian-ness in file"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:48
+msgid "Error opening file, check name and permissions."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:49
+msgid ""
+"Error interpreting range file header, expecting ion count and range count, "
+"respectively."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:50
+msgid ""
+"Range file appears to be empty, check file is a proper range file and is not "
+"empty."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:51
+msgid "Error reading the long name for ion."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:52
+msgid "Error reading the short name for ion."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:53
+msgid ""
+"Error reading colour data in the file, expecting 3 decimal values, space "
+"separated."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:54
+msgid ""
+"Tried skipping to table separator line (line with dashes), but did not find "
+"it."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:55
+msgid ""
+"Number of ions in the table header did not match the number specified at the "
+"start of the file"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:56
+msgid ""
+"Unexpected failure whilst trying to skip over range lead-in data (bit before "
+"range start value)"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:57
+msgid ""
+"Range table had an incorrect number of entries, should be 2 or 3 + number of "
+"ranges"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:58
+msgid "Unable to read range start and end values"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:59
+msgid "Unable to read range table entry"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:60
+msgid ""
+"Error reading file, unexpected format, are you sure it is a proper range "
+"file?"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:61
+msgid ""
+"Too many ranges appeared to have range entries with no usable data (eg, all "
+"blank)"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:62
+msgid ""
+"Range file appears to contain malformed data, check things like start and "
+"ends of m/c are not equal or flipped."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:63
+msgid "Range file appears to be inconsistent (eg, overlapping ranges)"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:64
+msgid "No ion name mapping found  for multiple ion."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:65
+msgid "Polyatomic extension range matches multiple masses in first section"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:66
+msgid "Range file is exceedingly large. Refusing to open"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:1404
+msgid ""
+"Range headings do not match order of the ions listed in the name "
+"specifications. The name specification ordering will be used when reading "
+"the range table, as the range heading section is declared as a comment in "
+"the file-format specifications, and is not to be intepreted by this program. "
+"Check range-species associations actually match what you expect."
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:73
+msgid "Arrow"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:74
+msgid "Text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:75
+msgid "Arrow+Text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:76
+msgid "Angle"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:77
+msgid "Ruler"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:524
+msgid "Enable"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:527
+msgid "Enable/disable annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:548
+msgid "Type or style of annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:564
+#: ../src/backend/filters/annotation.cpp:668
+msgid "Text of annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:568
+#: ../src/backend/filters/ionClip.cpp:529
+#: ../src/backend/filters/ionClip.cpp:551
+#: ../src/backend/filters/ionClip.cpp:573
+#: ../src/backend/filters/ionClip.cpp:610
+#: ../src/backend/filters/transform.cpp:1233
+#: ../src/backend/filters/transform.cpp:1260
+#: ../src/backend/filters/transform.cpp:1286
+#: ../src/backend/filters/profile.cpp:1013
+#: ../src/backend/filters/profile.cpp:1051
+#: ../src/backend/filters/spatialAnalysis.cpp:1041 ../src/gl/cameras.cpp:603
+msgid "Origin"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:572
+msgid "Position of annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:576
+#: ../src/backend/filters/annotation.cpp:683
+#: ../src/backend/filters/annotation.cpp:742
+#: ../src/backend/filters/annotation.cpp:831
+msgid "Up dir"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:580
+#: ../src/backend/filters/annotation.cpp:835
+msgid "Vector for up direction of annotation text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:584
+#: ../src/backend/filters/annotation.cpp:690
+#: ../src/backend/filters/annotation.cpp:734
+#: ../src/backend/filters/annotation.cpp:839
+msgid "Across dir"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:588
+#: ../src/backend/filters/annotation.cpp:843
+msgid "Reading direction for annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:593
+#: ../src/backend/filters/annotation.cpp:675
+#: ../src/backend/filters/annotation.cpp:769
+msgid "Text size"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:597
+#: ../src/backend/filters/annotation.cpp:679
+#: ../src/backend/filters/annotation.cpp:851
+msgid "Relative size of annotation text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:609
+#: ../src/backend/filters/annotation.cpp:650
+msgid "3D position for tail of arrow"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:617
+#: ../src/backend/filters/annotation.cpp:659
+msgid "3D Position to which arrow points"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:620
+#: ../src/backend/filters/annotation.cpp:730
+msgid "Positioning"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:625
+#: ../src/backend/filters/annotation.cpp:697
+msgid "Tip radius"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:629
+msgid "Size of the arrow head"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:633
+msgid "Line size"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:637
+msgid "Thickness of line used to draw arrow stem"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:671
+msgid "Options"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:707
+msgid "Position A"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:711
+msgid "Location of first non-central vertex"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:715
+msgid "Origin "
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:719
+msgid "Location of central vertex"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:723
+msgid "Position B"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:727
+msgid "Location of second non-central vertex"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:738
+msgid "Reading direction for angle text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:743
+msgid "Vector for up direction of angle text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:751
+msgid "Reflexive"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:754
+msgid "Measure interor (enabled) or exterior angle (disabled)"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:759
+msgid "Show Angle"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:763
+msgid "Display angle text (when enabled)"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:773
+msgid "Size of angle text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:791
+msgid "Digit format"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:795
+msgid ""
+"Format of angle text; # for numeral position, '.' for separator, eg ##.## "
+"gives 12.34"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:801
+#: ../src/backend/filters/annotation.cpp:886
+msgid "Sphere size"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:805
+#: ../src/backend/filters/annotation.cpp:890
+msgid "Marker sphere size for manipulating tool"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:819
+msgid "Ruler beginning 3D location"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:827
+msgid "Ruler finish 3D location"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:848
+#: ../src/backend/filters/boundingBox.cpp:715
+msgid "Font Size"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:857
+msgid "Fixed ticks"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:860
+msgid ""
+"Use fixed (enabled) number of text markers, or one every fixed distance "
+"(disabled)"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:867
+msgid "Num Ticks"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:870
+msgid "Number of tick marks along ruler"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:877
+msgid "Tick Spacing"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:880
+msgid "Distance between tick marks along ruler"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:904
+msgid "Colour for ruler and ticks"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:65 ../src/backend/filters/profile.cpp:53
+msgid "Sphere"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:66
+msgid "Plane"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:67
+msgid "Cylinder"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:68
+msgid "Aligned box"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:498
+#: ../src/backend/filters/profile.cpp:991
+msgid "Primitive"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:501
+msgid "Shape of clipping object"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:507
+#: ../src/backend/filters/profile.cpp:997
+msgid "Show Primitive"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:510
+msgid "Display the 3D interaction object"
 msgstr ""
 
-#: ../src/backend/plot.cpp:35
-msgid "Steps"
+#: ../src/backend/filters/ionClip.cpp:515
+msgid "Invert Clip"
 msgstr ""
 
-#: ../src/backend/plot.cpp:36
-msgid "Stem"
+#: ../src/backend/filters/ionClip.cpp:518
+msgid ""
+"Switch between retaining points inside (false) and outside (true) of "
+"primitive"
 msgstr ""
 
-#: ../src/backend/plot.cpp:37
-msgid "Points"
+#: ../src/backend/filters/ionClip.cpp:532
+#: ../src/backend/filters/profile.cpp:1054
+msgid "Position for centre of sphere"
 msgstr ""
 
-#: ../src/backend/plot.cpp:39
-msgid "Density"
+#: ../src/backend/filters/ionClip.cpp:537
+#: ../src/backend/filters/ionClip.cpp:597
+#: ../src/backend/filters/profile.cpp:1037
+#: ../src/backend/filters/profile.cpp:1059
+#: ../src/backend/filters/spatialAnalysis.cpp:134
+#: ../src/backend/filters/spatialAnalysis.cpp:1058
+msgid "Radius"
 msgstr ""
 
-#: ../src/backend/plot.cpp:40
-msgid "Scatter"
+#: ../src/backend/filters/ionClip.cpp:540
+#: ../src/backend/filters/profile.cpp:1062
+msgid "Radius of sphere"
 msgstr ""
 
-#: ../src/backend/plot.cpp:739 ../src/backend/plot.cpp:747
-msgid "Multiple data types"
+#: ../src/backend/filters/ionClip.cpp:554
+msgid "Position that plane passes through"
 msgstr ""
 
-#: ../src/backend/plot.cpp:1581
-msgid "error"
+#: ../src/backend/filters/ionClip.cpp:559
+msgid "Plane Normal"
 msgstr ""
 
-#: ../src/backend/plot.cpp:1821
-msgid "Amplitude"
+#: ../src/backend/filters/ionClip.cpp:562
+msgid "Perpendicular direction for plane"
 msgstr ""
 
-#: ../src/backend/filtertree.cpp:1146
-msgid "WARNING: Skipping node "
+#: ../src/backend/filters/ionClip.cpp:576
+msgid "Centre of cylinder"
 msgstr ""
 
-#: ../src/backend/filtertree.cpp:1146
-msgid " as it was not recognised"
+#: ../src/backend/filters/ionClip.cpp:581
+#: ../src/backend/filters/transform.cpp:1294
+#: ../src/backend/filters/profile.cpp:1021
+#: ../src/backend/filters/spatialAnalysis.cpp:1049
+msgid "Axis"
 msgstr ""
 
-#: ../src/backend/filtertree.cpp:1184
-msgid "Error processing node: "
+#: ../src/backend/filters/ionClip.cpp:584
+msgid "Positive vector for cylinder"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:259
-msgid "Collate Input"
+#: ../src/backend/filters/ionClip.cpp:589
+#: ../src/backend/filters/profile.cpp:1029
+msgid "Lock Axis Mag."
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:348
-msgid "Execute"
+#: ../src/backend/filters/ionClip.cpp:592
+msgid "Prevent changing length of cylinder during 3D interaction"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:389
-msgid "Collate output"
+#: ../src/backend/filters/ionClip.cpp:600
+#: ../src/backend/filters/profile.cpp:1040
+#: ../src/backend/filters/spatialAnalysis.cpp:1061
+msgid "Radius of cylinder"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:564
-#: ../src/backend/filters/externalProgram.cpp:578
-msgid "Command"
+#: ../src/backend/filters/ionClip.cpp:613
+msgid "Centre of axis aligned box"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:567
-msgid ""
-"Full command to send to operating system. See manual for escape sequence "
-"meanings"
+#: ../src/backend/filters/ionClip.cpp:618
+msgid "Corner offset"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:571
-msgid "Work Dir"
+#: ../src/backend/filters/ionClip.cpp:621
+msgid "Vector to corner of box"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:574
-msgid "Directory to run the command in"
+#: ../src/backend/filters/voxelise.cpp:111
+msgid "None (Raw count)"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:581
-msgid "Cleanup input"
+#: ../src/backend/filters/voxelise.cpp:112
+msgid "Volume (Density)"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:584
-msgid "Erase input files when command completed"
+#: ../src/backend/filters/voxelise.cpp:113
+msgid "All Ions (conc)"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:589
-msgid "Cache"
+#: ../src/backend/filters/voxelise.cpp:114
+msgid "Ratio (Num/Denom)"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:592
-msgid ""
-"Assume program does not alter its output, unless inputs from 3Depict are "
-"altered"
+#: ../src/backend/filters/voxelise.cpp:118
+msgid "Point Cloud"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:26
-msgid "Flat TOF"
+#: ../src/backend/filters/voxelise.cpp:119
+msgid "Isosurface"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:33
-msgid "INsufficient bins to perform fit"
+#: ../src/backend/filters/voxelise.cpp:120
+msgid "Axial slice"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:34
-msgid "Insufficient counts to perform fit"
+#: ../src/backend/filters/voxelise.cpp:124
+#: ../src/backend/filters/voxelise.cpp:130
+#: ../src/backend/filters/algorithms/mass.cpp:25
+#: ../src/backend/filters/spectrumPlot.cpp:76 ../src/backend/plot.cpp:28
+msgid "None"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:35
-msgid "Insufficient data to perform fit"
+#: ../src/backend/filters/voxelise.cpp:125
+msgid "Gaussian (blur)"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:36
-msgid "Data did not appear to be random noise - cannot fit noise level"
+#: ../src/backend/filters/voxelise.cpp:126
+msgid "Lapl. of Gauss. (edges)"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:65
-#: ../src/backend/filters/compositionProfile.cpp:53
-msgid "Sphere"
+#: ../src/backend/filters/voxelise.cpp:131
+msgid "Linear"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:66
-msgid "Plane"
+#: ../src/backend/filters/voxelise.cpp:564
+msgid "Voxel Limits (min,max): ("
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:67
-msgid "Cylinder"
+#: ../src/backend/filters/voxelise.cpp:709
+msgid "Fixed width"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:68
-msgid "Aligned box"
+#: ../src/backend/filters/voxelise.cpp:713
+msgid "If true, use fixed size voxels, otherwise use fixed count"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:497
-#: ../src/backend/filters/compositionProfile.cpp:971
-msgid "Primitive"
+#: ../src/backend/filters/voxelise.cpp:719
+msgid "Bin width x"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:500
-msgid "Shape of clipping object"
+#: ../src/backend/filters/voxelise.cpp:723
+msgid "Voxel size in X direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:506
-#: ../src/backend/filters/compositionProfile.cpp:977
-msgid "Show Primitive"
+#: ../src/backend/filters/voxelise.cpp:727
+msgid "Bin width y"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:509
-msgid "Display the 3D interaction object"
+#: ../src/backend/filters/voxelise.cpp:730
+msgid "Voxel size in Y direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:514
-msgid "Invert Clip"
+#: ../src/backend/filters/voxelise.cpp:736
+msgid "Bin width z"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:517
-msgid ""
-"Switch between retaining points inside (false) and outside (true) of "
-"primitive"
+#: ../src/backend/filters/voxelise.cpp:739
+msgid "Voxel size in Z direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:531
-#: ../src/backend/filters/compositionProfile.cpp:1034
-msgid "Position for centre of sphere"
+#: ../src/backend/filters/voxelise.cpp:746
+msgid "Num bins x"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:536
-#: ../src/backend/filters/ionClip.cpp:596
-#: ../src/backend/filters/compositionProfile.cpp:1017
-#: ../src/backend/filters/compositionProfile.cpp:1039
-#: ../src/backend/filters/spatialAnalysis.cpp:121
-#: ../src/backend/filters/spatialAnalysis.cpp:863
-msgid "Radius"
+#: ../src/backend/filters/voxelise.cpp:750
+msgid "Number of voxels to use in X direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:539
-#: ../src/backend/filters/compositionProfile.cpp:1042
-msgid "Radius of sphere"
+#: ../src/backend/filters/voxelise.cpp:755
+msgid "Num bins y"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:553
-msgid "Position that plane passes through"
+#: ../src/backend/filters/voxelise.cpp:758
+msgid "Number of voxels to use in Y direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:558
-msgid "Plane Normal"
+#: ../src/backend/filters/voxelise.cpp:764
+msgid "Num bins z"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:561
-msgid "Perpendicular direction for plane"
+#: ../src/backend/filters/voxelise.cpp:766
+msgid "Number of voxels to use in Z direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:575
-msgid "Centre of cylinder"
+#: ../src/backend/filters/voxelise.cpp:796
+msgid "Normalise by"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:580
-#: ../src/backend/filters/compositionProfile.cpp:1001
-#: ../src/backend/filters/spatialAnalysis.cpp:854
-#: ../src/backend/filters/transform.cpp:1263
-msgid "Axis"
+#: ../src/backend/filters/voxelise.cpp:799
+msgid "Method to use to normalise scalar value in each voxel"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:583
-msgid "Positive vector for cylinder"
+#: ../src/backend/filters/voxelise.cpp:802
+msgid "Computation"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:588
-#: ../src/backend/filters/compositionProfile.cpp:1009
-msgid "Lock Axis Mag."
+#: ../src/backend/filters/voxelise.cpp:809
+#: ../src/backend/filters/spatialAnalysis.cpp:1233
+#: ../src/backend/filters/spatialAnalysis.cpp:1254
+msgid "Numerator"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:591
-msgid "Prevent changing length of cylinder during 3D interaction"
+#: ../src/backend/filters/voxelise.cpp:812
+msgid "Parmeter \"a\" used in fraction (a/b) to get voxel value"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:599
-#: ../src/backend/filters/compositionProfile.cpp:1020
-#: ../src/backend/filters/spatialAnalysis.cpp:866
-msgid "Radius of cylinder"
+#: ../src/backend/filters/voxelise.cpp:829
+msgid "Enable this ion for numerator"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:612
-msgid "Centre of axis aligned box"
+#: ../src/backend/filters/voxelise.cpp:841
+#: ../src/backend/filters/voxelise.cpp:862
+#: ../src/backend/filters/spatialAnalysis.cpp:1261
+#: ../src/backend/filters/spatialAnalysis.cpp:1280
+msgid "Denominator"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:617
-msgid "Corner offset"
+#: ../src/backend/filters/voxelise.cpp:844
+msgid "Parameter \"b\" used in fraction (a/b) to get voxel value"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:620
-msgid "Vector to corner of box"
+#: ../src/backend/filters/voxelise.cpp:858
+msgid "Enable this ion for denominator contribution"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:82
-#: ../src/backend/filters/clusterAnalysis.cpp:1040
-msgid "Size Distribution"
+#: ../src/backend/filters/voxelise.cpp:880
+#: ../src/backend/filters/voxelise.cpp:911
+msgid "Filtering"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:83
-msgid "Chemistry Distribution"
+#: ../src/backend/filters/voxelise.cpp:884
+msgid "Smoothing method to use on voxels"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:493
-msgid "No range data. Can't cluster."
+#: ../src/backend/filters/voxelise.cpp:887
+msgid "Processing"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:504
-msgid ""
-"No ranges selected for cluster \"core\". Cannot continue with clustering."
+#: ../src/backend/filters/voxelise.cpp:893
+msgid "Standard Dev"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:513
-msgid ""
-"No ranges selected for cluster \"bulk\". Cannot continue with clustering."
+#: ../src/backend/filters/voxelise.cpp:897
+msgid "Filtering Scale"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:679
-msgid "Morphology Plot"
+#: ../src/backend/filters/voxelise.cpp:903
+msgid "Kernel Size"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:680
-msgid "\\lambda_1:\\lambda_2 ratio"
+#: ../src/backend/filters/voxelise.cpp:907
+msgid ""
+"Filter radius, in multiples of std. dev. Larger -> slower, more accurate"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:681
-msgid "\\lambda_2:\\lambda_3 ratio"
+#: ../src/backend/filters/voxelise.cpp:927
+msgid "Representation"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:726
-msgid "No clusters had sufficient dimensionality to compute singular values"
+#: ../src/backend/filters/voxelise.cpp:930
+msgid "3D display method"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:784
-msgid "Found :"
+#: ../src/backend/filters/voxelise.cpp:941
+msgid "Spot size"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:786
-msgid " clusters"
+#: ../src/backend/filters/voxelise.cpp:944
+msgid "Size of the spots to use for display"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:868
-msgid "Compositions (fractional, core+bulk)"
+#: ../src/backend/filters/voxelise.cpp:949
+#: ../src/backend/filters/voxelise.cpp:984
+#: ../src/backend/filters/voxelise.cpp:1056
+msgid "Transparency"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:870
-msgid "Compositions (fractional, core only)"
+#: ../src/backend/filters/voxelise.cpp:952
+msgid "How \"see through\" each point is (0 - opaque, 1 - invisible)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:888
-msgid "Frequencies (core+bulk)"
+#: ../src/backend/filters/voxelise.cpp:961
+msgid "Surf. param."
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:919
-msgid "Core Link + Erode"
+#: ../src/backend/filters/voxelise.cpp:964
+msgid "Isovalue"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:923
-#: ../src/backend/filters/clusterAnalysis.cpp:931
-#: ../src/backend/filters/spatialAnalysis.cpp:605
-#: ../src/backend/filters/spatialAnalysis.cpp:613
-#: ../src/backend/filters/transform.cpp:1126
-#: ../src/backend/filters/ionInfo.cpp:546
-msgid "Algorithm"
+#: ../src/backend/filters/voxelise.cpp:967
+msgid "Scalar value to show as isosurface"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:927
-msgid "Cluster algorithm mode"
+#: ../src/backend/filters/voxelise.cpp:972
+#: ../src/backend/filters/voxelise.cpp:1037
+#: ../src/backend/filters/spatialAnalysis.cpp:2344
+#: ../src/backend/filters/spatialAnalysis.cpp:2397
+msgid "Surface"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:938
-msgid "Core Classify"
+#: ../src/backend/filters/voxelise.cpp:979
+msgid "Colour of isosurface"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:941
-msgid ""
-"Enable core-classifcation pre-step in clustering (Stephenson et al, 2007)"
+#: ../src/backend/filters/voxelise.cpp:987
+#: ../src/backend/filters/voxelise.cpp:1059
+msgid "How \"see through\" each facet is (0 - opaque, 1 - invisible)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:947
-msgid "Core Classify Dist"
+#: ../src/backend/filters/voxelise.cpp:998
+msgid "Slice param."
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:950
-msgid "Restrict only atoms by distance to be cluster sources"
+#: ../src/backend/filters/voxelise.cpp:1006
+msgid "Slice Axis"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:955
-msgid "Classify Knn Max"
+#: ../src/backend/filters/voxelise.cpp:1009
+msgid "Normal for the planar slice"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:958
-msgid ""
-"Require that the kth NN (this number) is within the classify distance, to be "
-"a cluster source"
+#: ../src/backend/filters/voxelise.cpp:1016
+msgid "Slice Coord"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:964
-msgid "Core Link Dist"
+#: ../src/backend/filters/voxelise.cpp:1019
+msgid "Fractional coordinate that slice plane passes through"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:967
-msgid "Distance between clusters to allow linking"
+#: ../src/backend/filters/voxelise.cpp:1024
+msgid "Interp. Mode"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:972
-msgid "Bulk Link"
+#: ../src/backend/filters/voxelise.cpp:1032
+msgid "Interpolation mode for direction normal to slice"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:975
-#: ../src/backend/filters/clusterAnalysis.cpp:993
-msgid "Enable  linking of non-cluster species - eg for composition analysis "
+#: ../src/backend/filters/voxelise.cpp:1048
+msgid "Colour mode"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:982
-msgid "Bulk Link (Envelope) Dist"
+#: ../src/backend/filters/voxelise.cpp:1051
+#: ../src/backend/filters/ionColour.cpp:261
+msgid "Colour scheme used to assign points colours by value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:985
-msgid ""
-"Distance from core points that form cluster that is used to grab surrounding "
-"bulk points"
+#: ../src/backend/filters/voxelise.cpp:1064
+#: ../src/backend/filters/ionColour.cpp:273
+msgid "Show Bar"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:990
-msgid "Erosion"
+#: ../src/backend/filters/voxelise.cpp:1071
+msgid "Auto Bounds"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:999
-msgid "Erode Dist"
+#: ../src/backend/filters/voxelise.cpp:1072
+msgid "Auto-compute min/max values in map"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1002
-msgid ""
-"Distance from unclustered material in which bulk points are eroded from "
-"cluster"
+#: ../src/backend/filters/voxelise.cpp:1082
+#: ../src/backend/filters/ionColour.cpp:294
+msgid "Map start"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1008
-msgid "Clustering Params"
+#: ../src/backend/filters/voxelise.cpp:1083
+#: ../src/backend/filters/ionColour.cpp:295
+msgid "Assign points with this value to the first colour in map"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1013
-msgid "Size Cropping"
+#: ../src/backend/filters/voxelise.cpp:1090
+#: ../src/backend/filters/ionColour.cpp:302
+msgid "Map end"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1016
-msgid "Remove clusters based upon size distribution"
+#: ../src/backend/filters/voxelise.cpp:1091
+#: ../src/backend/filters/ionColour.cpp:303
+msgid "Assign points with this value to the last colour in map"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1023
-msgid "Min Size"
+#: ../src/backend/filters/transform.cpp:84
+msgid "Translate"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1026
-msgid "Remove clusters below this size"
+#: ../src/backend/filters/transform.cpp:85
+msgid "Scale (isotropic)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1031
-msgid "Max Size"
+#: ../src/backend/filters/transform.cpp:86
+msgid "Scale (anisotropic)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1034
-msgid "Remove clusters above this size"
+#: ../src/backend/filters/transform.cpp:87
+msgid "Rotate"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1043
-msgid "Show number of clusters as a function of cluster size"
+#: ../src/backend/filters/transform.cpp:88
+msgid "Value Shuffle"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1049
-msgid "Log Scale"
+#: ../src/backend/filters/transform.cpp:89
+msgid "Spatial Noise"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1052
-msgid "Use logarithmic scale for size distribution"
+#: ../src/backend/filters/transform.cpp:90
+msgid "Translate Value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1059
-msgid "Morphology Dist."
+#: ../src/backend/filters/transform.cpp:91
+msgid "Crop Value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1062
-msgid "Create a plot showing cluster aspect ratio"
+#: ../src/backend/filters/transform.cpp:95
+msgid "Specify"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1068
-msgid "Cluster Id"
+#: ../src/backend/filters/transform.cpp:96
+msgid "Boundbox Centre"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1071
-msgid "Assign cluster output a unique per-cluster value (id)."
+#: ../src/backend/filters/transform.cpp:97
+msgid "Mass Centre"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1078
-msgid "Chemistry Dist."
+#: ../src/backend/filters/transform.cpp:1008
+#: ../src/backend/filters/clusterAnalysis.cpp:1956
+#: ../src/backend/filters/spatialAnalysis.cpp:635
+#: ../src/backend/filters/spatialAnalysis.cpp:2298
+#: ../src/backend/filters/spatialAnalysis.cpp:2727
+#: ../src/backend/filters/spatialAnalysis.cpp:3016
+#: ../src/backend/filters/spatialAnalysis.cpp:3689
+#: ../src/backend/filters/spatialAnalysis.cpp:3952
+#: ../src/backend/filters/spatialAnalysis.cpp:4165
+msgid "Collate"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1081
-msgid "Create a plot showing chemistry for each cluster size"
+#: ../src/backend/filters/transform.cpp:1027
+msgid "Mass-to-Charge (Da/e)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1088
-#: ../src/backend/filters/compositionProfile.cpp:1087
-#: ../src/backend/filters/spatialAnalysis.cpp:921
-#: ../src/backend/filters/ionInfo.cpp:462
-msgid "Normalise"
+#: ../src/backend/filters/transform.cpp:1081
+msgid "Shuffle"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1091
-msgid "Convert cluster counts to composition"
+#: ../src/backend/filters/transform.cpp:1105
+msgid "Splice"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1097
-msgid "Postprocess"
+#: ../src/backend/filters/transform.cpp:1153
+msgid "Algorithm to use to transform point data"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1116
-msgid "If selected, use as \"core\" ion type (can make clusters)"
+#: ../src/backend/filters/transform.cpp:1157
+#: ../src/backend/filters/ionInfo.cpp:546
+#: ../src/backend/filters/clusterAnalysis.cpp:943
+#: ../src/backend/filters/clusterAnalysis.cpp:951
+#: ../src/backend/filters/spatialAnalysis.cpp:800
+#: ../src/backend/filters/spatialAnalysis.cpp:808
+msgid "Algorithm"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1121
-msgid "Core Ranges"
+#: ../src/backend/filters/transform.cpp:1170
+msgid "Origin mode"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1135
-msgid ""
-"If selected, use as \"bulk\" ion type (can be included in existing clusters)"
+#: ../src/backend/filters/transform.cpp:1173
+msgid "Select how transform origin is computed"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1140
-msgid "Bulk Ranges"
+#: ../src/backend/filters/transform.cpp:1178
+msgid "Show marker"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1156
-msgid "Max. Sep + Erode"
+#: ../src/backend/filters/transform.cpp:1182
+msgid "Display an interactive object to set transform origin"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1894
-msgid " --------------------------- Parameter selection notice ------------- "
+#: ../src/backend/filters/transform.cpp:1184
+msgid "Display a small marker to denote transform origin"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1895
-msgid "You have specified a bulk distance larger than half your link distance."
+#: ../src/backend/filters/transform.cpp:1200
+msgid "Translation"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1896
-msgid ""
-"You can do this; thats OK, but the output is no longer independent of the "
-"computational process;"
+#: ../src/backend/filters/transform.cpp:1203
+msgid "Translation vector for transform"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1897
-msgid ""
-"This will be a problem in the case where two or more clusters can equally "
-"lay claim to a \"bulk\" ion. "
+#: ../src/backend/filters/transform.cpp:1215
+msgid "Offset"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1898
-msgid ""
-" If your inter-cluster distance is sufficiently large (larger than your bulk "
-"linking distance), then you can get away with this."
+#: ../src/backend/filters/transform.cpp:1219
+msgid "Scalar to use to offset each point's associated value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1899
-msgid ""
-" In theory it is possible to \"join\" the clusters, but this has not been "
-"implemented for speed reasons."
+#: ../src/backend/filters/transform.cpp:1236
+#: ../src/backend/filters/transform.cpp:1263
+msgid "Origin of scale trasnform"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1900
-msgid ""
-"If you want this, please contact the author, or just use the source to add "
-"this in yourself."
+#: ../src/backend/filters/transform.cpp:1243
+#: ../src/backend/filters/transform.cpp:1270
+msgid "Scale Fact."
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1901
-msgid "---------------------------------------------------------------------- "
+#: ../src/backend/filters/transform.cpp:1246
+#: ../src/backend/filters/transform.cpp:1273
+msgid "Enlargement factor for scaling around origin"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1911
-#: ../src/backend/filters/spatialAnalysis.cpp:2060
-#: ../src/backend/filters/spatialAnalysis.cpp:2489
-#: ../src/backend/filters/spatialAnalysis.cpp:2775
-#: ../src/backend/filters/spatialAnalysis.cpp:3449
-#: ../src/backend/filters/transform.cpp:977
-msgid "Collate"
+#: ../src/backend/filters/transform.cpp:1289
+msgid "Origin of rotation"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1930
-msgid "Build Core"
+#: ../src/backend/filters/transform.cpp:1297
+msgid "Axis around which to revolve"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1958
-msgid "Core"
+#: ../src/backend/filters/transform.cpp:1302
+msgid "Angle (deg)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2097
-msgid "Bulk"
+#: ../src/backend/filters/transform.cpp:1305
+msgid "Angle to perform rotation (ACW, as viewed from axis towards origin)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2227
-msgid "Erode"
+#: ../src/backend/filters/transform.cpp:1322
+msgid "Noise Type"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2301
-msgid "Re-Collate"
+#: ../src/backend/filters/transform.cpp:1325
+msgid "Method to use to degrade point data"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2358
-msgid "Classify Core"
+#: ../src/backend/filters/transform.cpp:1332
+msgid "Noise level"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2449
-msgid "Build Bulk"
+#: ../src/backend/filters/transform.cpp:1334
+msgid "Standard dev."
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2694
-#: ../src/backend/filters/clusterAnalysis.cpp:2893
-msgid "Cluster Size"
+#: ../src/backend/filters/transform.cpp:1342
+msgid "Amplitude of noise"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2695
-#: ../src/backend/filters/clusterAnalysis.cpp:2897
-msgid "Frequency"
+#: ../src/backend/filters/transform.cpp:1356
+msgid "Min Value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2895
-msgid "Composition"
+#: ../src/backend/filters/transform.cpp:1360
+msgid "Minimum value to use for crop"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:111
-msgid "None (Raw count)"
+#: ../src/backend/filters/transform.cpp:1364
+msgid "Max Value"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:112
-msgid "Volume (Density)"
+#: ../src/backend/filters/transform.cpp:1368
+msgid "Maximum value to use for crop"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:113
-msgid "All Ions (conc)"
+#: ../src/backend/filters/transform.cpp:1377
+msgid "Transform Params"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:114
-msgid "Ratio (Num/Denom)"
+#: ../src/backend/filters/transform.cpp:1738
+msgid "White"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:118
-msgid "Point Cloud"
+#: ../src/backend/filters/transform.cpp:1740
+msgid "Gaussian"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:119
-msgid "Isosurface"
+#: ../src/backend/filters/externalProgram.cpp:259
+msgid "Collate Input"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:120
-msgid "Axial slice"
+#: ../src/backend/filters/externalProgram.cpp:348
+msgid "Execute"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:125
-msgid "Gaussian (blur)"
+#: ../src/backend/filters/externalProgram.cpp:389
+msgid "Collate output"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:126
-msgid "Lapl. of Gauss. (edges)"
+#: ../src/backend/filters/externalProgram.cpp:564
+#: ../src/backend/filters/externalProgram.cpp:578
+msgid "Command"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:131
-msgid "Linear"
+#: ../src/backend/filters/externalProgram.cpp:567
+msgid ""
+"Full command to send to operating system. See manual for escape sequence "
+"meanings"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:564
-msgid "Voxel Limits (min,max): ("
+#: ../src/backend/filters/externalProgram.cpp:571
+msgid "Work Dir"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:709
-msgid "Fixed width"
+#: ../src/backend/filters/externalProgram.cpp:574
+msgid "Directory to run the command in"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:713
-msgid "If true, use fixed size voxels, otherwise use fixed count"
+#: ../src/backend/filters/externalProgram.cpp:581
+msgid "Cleanup input"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:719
-msgid "Bin width x"
+#: ../src/backend/filters/externalProgram.cpp:584
+msgid "Erase input files when command completed"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:723
-msgid "Voxel size in X direction"
+#: ../src/backend/filters/externalProgram.cpp:589
+msgid "Cache"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:727
-msgid "Bin width y"
+#: ../src/backend/filters/externalProgram.cpp:592
+msgid ""
+"Assume program does not alter its output, unless inputs from 3Depict are "
+"altered"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:730
-msgid "Voxel size in Y direction"
+#: ../src/backend/filters/algorithms/mass.cpp:26
+msgid "Flat TOF"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:736
-msgid "Bin width z"
+#: ../src/backend/filters/algorithms/mass.cpp:33
+msgid "INsufficient bins to perform fit"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:739
-msgid "Voxel size in Z direction"
+#: ../src/backend/filters/algorithms/mass.cpp:34
+msgid "Insufficient counts to perform fit"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:746
-msgid "Num bins x"
+#: ../src/backend/filters/algorithms/mass.cpp:35
+msgid "Insufficient data to perform fit"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:750
-msgid "Number of voxels to use in X direction"
+#: ../src/backend/filters/algorithms/mass.cpp:36
+msgid "Data did not appear to be random noise - cannot fit noise level"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:755
-msgid "Num bins y"
+#: ../src/backend/filters/ionInfo.cpp:37
+msgid "Rectilinear"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:758
-msgid "Number of voxels to use in Y direction"
+#: ../src/backend/filters/ionInfo.cpp:38
+msgid "Convex hull"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:764
-msgid "Num bins z"
+#: ../src/backend/filters/ionInfo.cpp:200
+msgid "No ions"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:766
-msgid "Number of voxels to use in Z direction"
+#: ../src/backend/filters/ionInfo.cpp:226
+#: ../src/backend/filters/spectrumPlot.cpp:432
+msgid ""
+"Background fit failed - input data was considered ill formed (gauss-test)"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:796
-msgid "Normalise by"
+#: ../src/backend/filters/ionInfo.cpp:227
+msgid "Following data has not been corrected"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:799
-msgid "Method to use to normalise scalar value in each voxel"
+#: ../src/backend/filters/ionInfo.cpp:279
+msgid "--Counts--"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:802
-msgid "Computation"
+#: ../src/backend/filters/ionInfo.cpp:289
+msgid "Total Ranged\t"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:809
-msgid "Numerator"
+#: ../src/backend/filters/ionInfo.cpp:294
+msgid "Total (incl. unranged)\t"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:812
-msgid "Parmeter \"a\" used in fraction (a/b) to get voxel value"
+#: ../src/backend/filters/ionInfo.cpp:307
+msgid "n/a"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:829
-msgid "Enable this ion for numerator"
+#: ../src/backend/filters/ionInfo.cpp:317
+#: ../src/backend/filters/ionDownsample.cpp:496
+msgid "Unranged"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:841
-msgid "Denominator"
+#: ../src/backend/filters/ionInfo.cpp:330
+msgid "Number of points : "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:844
-msgid "Parameter \"b\" used in fraction (a/b) to get voxel value"
+#: ../src/backend/filters/ionInfo.cpp:359
+msgid "Rectilinear Bounds : "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:857
-msgid "Enable this ion for denominator contribution"
+#: ../src/backend/filters/ionInfo.cpp:364
+msgid "Volume (len^3): "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:879
-#: ../src/backend/filters/voxelise.cpp:910
-msgid "Filtering"
+#: ../src/backend/filters/ionInfo.cpp:381
+msgid "Convex Volume (len^3): "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:883
-msgid "Smoothing method to use on voxels"
+#: ../src/backend/filters/ionInfo.cpp:384
+msgid "Unable to compute volume"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:886
-msgid "Processing"
+#: ../src/backend/filters/ionInfo.cpp:413
+msgid "Ranged Density (pts/vol):"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:892
-msgid "Standard Dev"
+#: ../src/backend/filters/ionInfo.cpp:418
+msgid "Total Density (pts/vol):"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:896
-msgid "Filtering Scale"
+#: ../src/backend/filters/ionInfo.cpp:445
+msgid "Compositions"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:902
-msgid "Kernel Size"
+#: ../src/backend/filters/ionInfo.cpp:446
+msgid "Display compositional data for points in console"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:906
-msgid ""
-"Filter radius, in multiples of std. dev. Larger -> slower, more accurate"
+#: ../src/backend/filters/ionInfo.cpp:450
+msgid "Counts"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:926
-msgid "Representation"
+#: ../src/backend/filters/ionInfo.cpp:451
+msgid "Display count data for points in console"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:929
-msgid "3D display method"
+#: ../src/backend/filters/ionInfo.cpp:458
+msgid "Ion data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:940
-msgid "Spot size"
+#: ../src/backend/filters/ionInfo.cpp:462
+#: ../src/backend/filters/profile.cpp:1107
+#: ../src/backend/filters/clusterAnalysis.cpp:1108
+#: ../src/backend/filters/spatialAnalysis.cpp:1116
+msgid "Normalise"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:943
-msgid "Size of the spots to use for display"
+#: ../src/backend/filters/ionInfo.cpp:466
+msgid "Normalise count data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:948
-#: ../src/backend/filters/voxelise.cpp:983
-#: ../src/backend/filters/voxelise.cpp:1055
-msgid "Transparency"
+#: ../src/backend/filters/ionInfo.cpp:530
+msgid "Volume"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:951
-msgid "How \"see through\" each point is (0 - opaque, 1 - invisible)"
+#: ../src/backend/filters/ionInfo.cpp:533
+msgid "Compute volume for point data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:960
-msgid "Surf. param."
+#: ../src/backend/filters/ionInfo.cpp:549
+msgid "Select volume counting technique"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:963
-msgid "Isovalue"
+#: ../src/backend/filters/ionInfo.cpp:562
+msgid "Volume data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:966
-msgid "Scalar value to show as isosurface"
+#: ../src/backend/filters/rangeFile.cpp:120
+#: ../src/backend/filters/rangeFile.h:96
+msgid "Ranging"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:971
-#: ../src/backend/filters/voxelise.cpp:1036
-#: ../src/backend/filters/spatialAnalysis.cpp:2106
-#: ../src/backend/filters/spatialAnalysis.cpp:2159
-msgid "Surface"
+#: ../src/backend/filters/rangeFile.cpp:560
+#: ../src/backend/filters/rangeFile.cpp:580
+#: ../src/backend/filters/dataLoad.cpp:484
+#: ../src/backend/filters/dataLoad.cpp:505
+msgid "File"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:978
-msgid "Colour of isosurface"
+#: ../src/backend/filters/rangeFile.cpp:563
+msgid "File to use for range data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:986
-#: ../src/backend/filters/voxelise.cpp:1058
-msgid "How \"see through\" each facet is (0 - opaque, 1 - invisible)"
+#: ../src/backend/filters/rangeFile.cpp:573
+msgid "Drop unranged"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:997
-msgid "Slice param."
+#: ../src/backend/filters/rangeFile.cpp:575
+msgid "Remove unranged points when generating output"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1005
-msgid "Slice Axis"
+#: ../src/backend/filters/rangeFile.cpp:585
+msgid "Legend"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1008
-msgid "Normal for the planar slice"
+#: ../src/backend/filters/rangeFile.cpp:587
+msgid "Display colour legend for enabled ions"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1015
-msgid "Slice Coord"
+#: ../src/backend/filters/rangeFile.cpp:591
+msgid "View"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1018
-msgid "Fractional coordinate that slice plane passes through"
+#: ../src/backend/filters/rangeFile.cpp:607
+msgid "All Ions"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1023
-msgid "Interp. Mode"
+#: ../src/backend/filters/rangeFile.cpp:608
+msgid "Enable/disable all ions at once"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1031
-msgid "Interpolation mode for direction normal to slice"
+#: ../src/backend/filters/rangeFile.cpp:616
+msgid "Species"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1047
-msgid "Colour mode"
+#: ../src/backend/filters/rangeFile.cpp:623
+msgid "IonID "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1050
-#: ../src/backend/filters/ionColour.cpp:269
-msgid "Colour scheme used to assign points colours by value"
+#: ../src/backend/filters/rangeFile.cpp:624
+msgid "Enable/disable specified ion"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1063
-#: ../src/backend/filters/ionColour.cpp:281
-msgid "Show Bar"
+#: ../src/backend/filters/rangeFile.cpp:634
+msgid "Active Ion "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1070
-msgid "Auto Bounds"
+#: ../src/backend/filters/rangeFile.cpp:636
+msgid "If true, ion is used in output"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1071
-msgid "Auto-compute min/max values in map"
+#: ../src/backend/filters/rangeFile.cpp:646
+msgid "Colour "
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1081
-#: ../src/backend/filters/ionColour.cpp:302
-msgid "Map start"
+#: ../src/backend/filters/rangeFile.cpp:650
+msgid "Colour used to represent ion"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1082
-#: ../src/backend/filters/ionColour.cpp:303
-msgid "Assign points with this value to the first colour in map"
+#: ../src/backend/filters/rangeFile.cpp:673
+msgid "All Ranges"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1089
-#: ../src/backend/filters/ionColour.cpp:310
-msgid "Map end"
+#: ../src/backend/filters/rangeFile.cpp:674
+msgid "Enable/disable all ranges"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1090
-#: ../src/backend/filters/ionColour.cpp:311
-msgid "Assign points with this value to the last colour in map"
+#: ../src/backend/filters/rangeFile.cpp:689
+msgid "Active Rng "
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:265
-msgid "Colour Map"
+#: ../src/backend/filters/rangeFile.cpp:692
+msgid ""
+"Enable/disable specified range (ion must also be enabled to activiate range)"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:273
-msgid "Reverse map"
+#: ../src/backend/filters/rangeFile.cpp:696
+msgid "Ion "
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:274
-msgid "Reverse the colour scale"
+#: ../src/backend/filters/rangeFile.cpp:699
+msgid "Name of ion associate to this range"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:287
-msgid "Opacity"
+#: ../src/backend/filters/rangeFile.cpp:708
+msgid "Start rng "
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:294
-msgid "Num Colours"
+#: ../src/backend/filters/rangeFile.cpp:711
+msgid "Start value for range"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:296
-msgid "Number of unique colours to use in colour map"
+#: ../src/backend/filters/rangeFile.cpp:716
+msgid "End rng "
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:417 ../src/backend/filter.cpp:172
-msgid "Aborted"
+#: ../src/backend/filters/rangeFile.cpp:719
+msgid "Stopping value for range`"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:51
+#: ../src/backend/filters/profile.cpp:51
 msgid "Cylinder (axial)"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:52
+#: ../src/backend/filters/profile.cpp:52
 msgid "Cylinder (radial)"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:591
+#: ../src/backend/filters/profile.cpp:591
 msgid "Distance"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:599
+#: ../src/backend/filters/profile.cpp:599
 msgid "Fraction"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:601
+#: ../src/backend/filters/profile.cpp:601
 msgid "Density (\\frac{\\#}{len^3})"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:628
+#: ../src/backend/filters/profile.cpp:628
 msgid "Freq. Profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:680
+#: ../src/backend/filters/profile.cpp:680
 msgid "No data remained in profile - cannot display result"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:965
+#: ../src/backend/filters/profile.cpp:967
+msgid "Total Density"
+msgstr ""
+
+#: ../src/backend/filters/profile.cpp:971
+msgid "Do not do per-species analysis, perform density computation only"
+msgstr ""
+
+#: ../src/backend/filters/profile.cpp:985
 msgid "Primitive type"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:969
+#: ../src/backend/filters/profile.cpp:989
 msgid "Basic shape to use for profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:981
+#: ../src/backend/filters/profile.cpp:1001
 msgid "Display the 3D composition profile interaction object"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:996
-#: ../src/backend/filters/spatialAnalysis.cpp:849
+#: ../src/backend/filters/profile.cpp:1016
+#: ../src/backend/filters/spatialAnalysis.cpp:1044
 msgid "Position for centre of cylinder"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1004
+#: ../src/backend/filters/profile.cpp:1024
 msgid "Vector between ends of cylinder"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1012
+#: ../src/backend/filters/profile.cpp:1032
 msgid "Prevent length of cylinder changing during interaction"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1055
+#: ../src/backend/filters/profile.cpp:1075
 msgid "Fixed Bin Num"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1058
+#: ../src/backend/filters/profile.cpp:1078
 msgid ""
 "If true, use a fixed number of bins for profile, otherwise use fixed step "
 "size"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1065
-#: ../src/backend/filters/spatialAnalysis.cpp:690
-#: ../src/backend/filters/spatialAnalysis.cpp:826
+#: ../src/backend/filters/profile.cpp:1085
+#: ../src/backend/filters/spatialAnalysis.cpp:887
+#: ../src/backend/filters/spatialAnalysis.cpp:1021
 msgid "Num Bins"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1070
+#: ../src/backend/filters/profile.cpp:1090
 msgid "Number of bins to use for profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1076
-#: ../src/backend/filters/spectrumPlot.cpp:572
+#: ../src/backend/filters/profile.cpp:1096
+#: ../src/backend/filters/spectrumPlot.cpp:580
 msgid "Bin width"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1082
+#: ../src/backend/filters/profile.cpp:1102
 msgid "Size of each bin in profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1091
+#: ../src/backend/filters/profile.cpp:1111
 msgid "Convert bin counts into relative frequencies in each bin"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1095
+#: ../src/backend/filters/profile.cpp:1115
 msgid "Min. events"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1099
+#: ../src/backend/filters/profile.cpp:1119
 msgid "Drop data that does not have this many events"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1102
+#: ../src/backend/filters/profile.cpp:1122
 msgid "Settings"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1124
-#: ../src/backend/filters/spectrumPlot.cpp:661
+#: ../src/backend/filters/profile.cpp:1144
+#: ../src/backend/filters/spectrumPlot.cpp:669
 msgid "Plot Type"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1127
+#: ../src/backend/filters/profile.cpp:1147
 msgid "Visual style for plot"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1137
+#: ../src/backend/filters/profile.cpp:1158
 msgid "Colour of plot"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1153
+#: ../src/backend/filters/profile.cpp:1174
 msgid "Err. Estimator"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1156
+#: ../src/backend/filters/profile.cpp:1177
 msgid "Method of estimating error associated with each bin"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1163
+#: ../src/backend/filters/profile.cpp:1184
 msgid "Avg. Window"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1166
+#: ../src/backend/filters/profile.cpp:1187
 msgid "Number of bins to include in moving average filter"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1170
+#: ../src/backend/filters/profile.cpp:1191
 msgid "Error analysis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:111
-msgid "Local Density"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:112
-msgid "Density Filtering"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:113
-msgid "Radial Distribution"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:114
-msgid "Axial Distribution"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:115
-msgid "Binomial Distribution"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:116
-msgid "Point Em/Replacement"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:120
-msgid "Neighbour Count"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:608
-msgid "Spatial analysis algorithm to use"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:631
-msgid "Stop Mode"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:634
-msgid "Method to use to terminate algorithm when examining each point"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:641
-msgid "NN Max"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:644
-msgid "Maximum number of neighbours to examine"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:651
-msgid "Normalise bins"
+#: ../src/backend/filters/boundingBox.cpp:64
+msgid "Box only"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:654
-msgid ""
-"Normalise counts by binwidth. Needed when comparing NN histograms against "
-"one another"
+#: ../src/backend/filters/boundingBox.cpp:65
+msgid "Tick"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:660
-msgid "Show Random"
+#: ../src/backend/filters/boundingBox.cpp:66
+msgid "Dimension"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:663
-msgid "Show a fitted (density matched) theoretical distribution"
+#: ../src/backend/filters/boundingBox.cpp:571
+msgid "If true, show box, otherwise hide box"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:674
-msgid "Dist Max"
+#: ../src/backend/filters/boundingBox.cpp:584
+msgid "Style"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:677
-msgid "Maximum distance from each point for search"
+#: ../src/backend/filters/boundingBox.cpp:587
+msgid "Box display mode"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:693
-#: ../src/backend/filters/spatialAnalysis.cpp:829
-msgid "Number of bins for output 1D RDF plot"
+#: ../src/backend/filters/boundingBox.cpp:590
+msgid "Display mode"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:699
-msgid "Surface Remove"
+#: ../src/backend/filters/boundingBox.cpp:599
+msgid "Fixed Tick Num"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:702
+#: ../src/backend/filters/boundingBox.cpp:603
 msgid ""
-"Exclude surface as part of source to minimise bias in RDF (at cost of "
-"increased noise)"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:709
-msgid "Remove Dist"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:712
-msgid "Minimum distance to remove from surface"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:720
-#: ../src/backend/filters/spatialAnalysis.cpp:834
-msgid "Plot colour "
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:723
-#: ../src/backend/filters/spatialAnalysis.cpp:837
-msgid "Colour of output plot"
+"If true, evenly use specified number of ticks. Otherwise, use distance to "
+"determine tick count"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:727
-#: ../src/backend/filters/spatialAnalysis.cpp:815
-#: ../src/backend/filters/spatialAnalysis.cpp:820
-#: ../src/backend/filters/spatialAnalysis.cpp:869
-#: ../src/backend/filters/spatialAnalysis.cpp:908
-msgid "Alg. Params."
+#: ../src/backend/filters/boundingBox.cpp:611
+msgid "Num X"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:740
-msgid "Source"
+#: ../src/backend/filters/boundingBox.cpp:614
+msgid "Tick count in X direction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:743
-msgid "Ions to use for initiating RDF search"
+#: ../src/backend/filters/boundingBox.cpp:619
+msgid "Num Y"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:756
-msgid "Enable/disable ion as source"
+#: ../src/backend/filters/boundingBox.cpp:622
+msgid "Tick count in Y direction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:762
-msgid "Source Ion"
+#: ../src/backend/filters/boundingBox.cpp:627
+msgid "Num Z"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:772
-msgid "Enable/disable all ions as target"
+#: ../src/backend/filters/boundingBox.cpp:630
+msgid "Tick count in Z direction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:784
-msgid "Enable/disable this ion as target"
+#: ../src/backend/filters/boundingBox.cpp:636
+msgid "Spacing X"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:789
-msgid "Target Ion"
+#: ../src/backend/filters/boundingBox.cpp:640
+msgid "Distance between ticks on X axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:799
-msgid "Cutoff"
+#: ../src/backend/filters/boundingBox.cpp:644
+msgid "Spacing Y"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:802
-msgid "Remove points with local density above/below this value"
+#: ../src/backend/filters/boundingBox.cpp:648
+msgid "Distance between ticks on Y axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:808
-msgid "Retain Upper"
+#: ../src/backend/filters/boundingBox.cpp:652
+msgid "Spacing Z"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:811
-msgid "Retain either points with density above (enabled) or below cutoff"
+#: ../src/backend/filters/boundingBox.cpp:656
+msgid "Distance between ticks on Z axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:857
-msgid "Vector between centre and end of cylinder"
+#: ../src/backend/filters/boundingBox.cpp:664
+msgid "Ticks X"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:876
-#: ../src/backend/filters/spatialAnalysis.cpp:3587
-#: ../src/backend/filters/spatialAnalysis.cpp:3646
-msgid "Block size"
+#: ../src/backend/filters/boundingBox.cpp:668
+msgid "Display tick marks on X axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:879
-msgid "Number of ions to use per block"
+#: ../src/backend/filters/boundingBox.cpp:672
+msgid "Ticks Y"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:886
-msgid "Max Block Aspect"
+#: ../src/backend/filters/boundingBox.cpp:676
+msgid "Display tick marks on Y axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:889
-msgid ""
-"Maximum allowable block aspect ratio. Blocks above this aspect are "
-"discarded. Setting too high decreases correlation strength. Too low causes "
-"loss of statistical power."
+#: ../src/backend/filters/boundingBox.cpp:680
+msgid "Ticks Z"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:900
-msgid "Extrusion Direction"
+#: ../src/backend/filters/boundingBox.cpp:684
+msgid "Display tick marks on Z axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:903
-msgid "Direction in which blocks are extended during construction."
+#: ../src/backend/filters/boundingBox.cpp:687
+msgid "Tick marks"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:912
-msgid "Plot Counts"
+#: ../src/backend/filters/boundingBox.cpp:694
+msgid "Box Colour"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:915
-msgid "Show the counts in the binomial histogram"
+#: ../src/backend/filters/boundingBox.cpp:698
+msgid "Colour of the bounding box"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:924
-msgid ""
-"Normalise the counts in the binomial histogram to a probability density "
-"function"
+#: ../src/backend/filters/boundingBox.cpp:703
+msgid "Line thickness"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:938
-msgid "Display Grid"
+#: ../src/backend/filters/boundingBox.cpp:707
+msgid "Thickness of the lines used to draw the box"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:947
-msgid "View Options"
+#: ../src/backend/filters/boundingBox.cpp:718
+msgid "Relative size for text"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:953
-msgid "Data File"
+#: ../src/backend/filters/boundingBox.cpp:723
+msgid "Abs. Coords"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:957
-msgid "Pos file of points to subtract/replace/etc"
+#: ../src/backend/filters/boundingBox.cpp:726
+msgid "Show labels using aboslute coo-ordinates"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:962
-msgid "Match Tol."
+#: ../src/backend/filters/ionDownsample.cpp:191
+msgid "Sampling"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:965
-msgid "Tolerance to allow for matching"
+#: ../src/backend/filters/ionDownsample.cpp:447
+msgid "By Count"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:981
-msgid "Replacment condition"
+#: ../src/backend/filters/ionDownsample.cpp:450
+msgid "Sample up to a fixed number of ions"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:987
-msgid "Replace value"
+#: ../src/backend/filters/ionDownsample.cpp:456
+msgid "Per Species"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:990
-msgid "Use value data from file when replacing ions"
+#: ../src/backend/filters/ionDownsample.cpp:460
+msgid "Use species specific (from ranging) sampling values"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:995
-msgid "Replacement"
+#: ../src/backend/filters/ionDownsample.cpp:489
+msgid "Sampling value for species"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2092
-#: ../src/backend/filters/spatialAnalysis.cpp:2145
-#: ../src/backend/filters/spatialAnalysis.cpp:2495
-#: ../src/backend/filters/spatialAnalysis.cpp:2781
-#: ../src/backend/filters/spatialAnalysis.cpp:3300
-msgid "Build"
+#: ../src/backend/filters/ionDownsample.cpp:505
+#: ../src/backend/filters/ionDownsample.cpp:529
+msgid "Sampling rates"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2199
-#: ../src/backend/filters/spatialAnalysis.cpp:2518
-#: ../src/backend/filters/spatialAnalysis.cpp:2805
-msgid "Analyse"
+#: ../src/backend/filters/ionDownsample.cpp:513
+msgid "Output Count"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2278
-#: ../src/backend/filters/spatialAnalysis.cpp:2368
-#: ../src/backend/filters/spatialAnalysis.cpp:2434
-msgid "Radial Distance"
+#: ../src/backend/filters/ionDownsample.cpp:516
+msgid "Sample up to this value of points"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2280
-#: ../src/backend/filters/spatialAnalysis.cpp:2373
-msgid "Count/Distance"
+#: ../src/backend/filters/ionDownsample.cpp:521
+msgid "Out Fraction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2285
-#: ../src/backend/filters/spatialAnalysis.cpp:2378
-msgid "NN Freq."
+#: ../src/backend/filters/ionDownsample.cpp:525
+msgid "Sample this fraction of points"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2425
-msgid "Warning, "
+#: ../src/backend/filters/clusterAnalysis.cpp:84
+#: ../src/backend/filters/clusterAnalysis.cpp:1060
+msgid "Size Distribution"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2426
-msgid ""
-" points were unable to find neighbour points that exceeded the search "
-"radius, and thus terminated prematurely"
+#: ../src/backend/filters/clusterAnalysis.cpp:85
+msgid "Chemistry Distribution"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2436
-msgid " RDF"
+#: ../src/backend/filters/clusterAnalysis.cpp:503
+msgid "No range data. Can't cluster."
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2714
-#: ../src/backend/filters/spatialAnalysis.cpp:3011
-msgid "Number Density (\\#/Vol^3)"
+#: ../src/backend/filters/clusterAnalysis.cpp:514
+msgid ""
+"No ranges selected for cluster \"core\". Cannot continue with clustering."
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2736
-#: ../src/backend/filters/spatialAnalysis.cpp:3031
-msgid "Warning,"
+#: ../src/backend/filters/clusterAnalysis.cpp:523
+msgid ""
+"No ranges selected for cluster \"bulk\". Cannot continue with clustering."
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2737
-#: ../src/backend/filters/spatialAnalysis.cpp:3032
-msgid " points were un-analysable. These have been dropped"
+#: ../src/backend/filters/clusterAnalysis.cpp:689
+msgid "Morphology Plot"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2759
-#: ../src/backend/filters/spatialAnalysis.cpp:3054
-msgid "And so on..."
+#: ../src/backend/filters/clusterAnalysis.cpp:690
+msgid "\\lambda_1:\\lambda_2 ratio"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3136
-msgid "Extract"
+#: ../src/backend/filters/clusterAnalysis.cpp:691
+msgid "\\lambda_2:\\lambda_3 ratio"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3209
-msgid "Reduce"
+#: ../src/backend/filters/clusterAnalysis.cpp:736
+msgid "No clusters had sufficient dimensionality to compute singular values"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3318
-msgid "Compute"
+#: ../src/backend/filters/clusterAnalysis.cpp:794
+msgid "Found :"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3364
-msgid "Insufficient points to complete analysis"
+#: ../src/backend/filters/clusterAnalysis.cpp:796
+msgid " clusters"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3387
-msgid "Axial Distance"
+#: ../src/backend/filters/clusterAnalysis.cpp:888
+msgid "Compositions (fractional, core+bulk)"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3389
-msgid " 1D Dist. Func."
+#: ../src/backend/filters/clusterAnalysis.cpp:890
+msgid "Compositions (fractional, core only)"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3458
-msgid "Binomial"
+#: ../src/backend/filters/clusterAnalysis.cpp:908
+msgid "Frequencies (core+bulk)"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3589
-#: ../src/backend/filters/spatialAnalysis.cpp:3648
-msgid "Rel. Frequency"
+#: ../src/backend/filters/clusterAnalysis.cpp:939
+msgid "Core Link + Erode"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:81
-msgid "Translate"
+#: ../src/backend/filters/clusterAnalysis.cpp:947
+msgid "Cluster algorithm mode"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:82
-msgid "Scale (isotropic)"
+#: ../src/backend/filters/clusterAnalysis.cpp:958
+msgid "Core Classify"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:83
-msgid "Scale (anisotropic)"
+#: ../src/backend/filters/clusterAnalysis.cpp:961
+msgid ""
+"Enable core-classifcation pre-step in clustering (Stephenson et al, 2007)"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:84
-msgid "Rotate"
+#: ../src/backend/filters/clusterAnalysis.cpp:967
+msgid "Core Classify Dist"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:85
-msgid "Value Shuffle"
+#: ../src/backend/filters/clusterAnalysis.cpp:970
+msgid "Restrict only atoms by distance to be cluster sources"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:86
-msgid "Spatial Noise"
+#: ../src/backend/filters/clusterAnalysis.cpp:975
+msgid "Classify Knn Max"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:87
-msgid "Translate Value"
+#: ../src/backend/filters/clusterAnalysis.cpp:978
+msgid ""
+"Require that the kth NN (this number) is within the classify distance, to be "
+"a cluster source"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:91
-msgid "Specify"
+#: ../src/backend/filters/clusterAnalysis.cpp:984
+msgid "Core Link Dist"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:92
-msgid "Boundbox Centre"
+#: ../src/backend/filters/clusterAnalysis.cpp:987
+msgid "Distance between clusters to allow linking"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:93
-msgid "Mass Centre"
+#: ../src/backend/filters/clusterAnalysis.cpp:992
+msgid "Bulk Link"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:996
-msgid "Mass-to-Charge (amu/e)"
+#: ../src/backend/filters/clusterAnalysis.cpp:995
+#: ../src/backend/filters/clusterAnalysis.cpp:1012
+msgid "Enable  linking of non-cluster species - eg for composition analysis "
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1050
-msgid "Shuffle"
+#: ../src/backend/filters/clusterAnalysis.cpp:1002
+msgid "Bulk Link (Envelope) Dist"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1074
-msgid "Splice"
+#: ../src/backend/filters/clusterAnalysis.cpp:1005
+msgid ""
+"Distance from core points that form cluster that is used to grab surrounding "
+"bulk points"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1122
-msgid "Algorithm to use to transform point data"
+#: ../src/backend/filters/clusterAnalysis.cpp:1009
+msgid "Erosion"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1139
-msgid "Origin mode"
+#: ../src/backend/filters/clusterAnalysis.cpp:1018
+msgid "Erode Dist"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1142
-msgid "Select how transform origin is computed"
+#: ../src/backend/filters/clusterAnalysis.cpp:1021
+msgid ""
+"Distance from unclustered material in which bulk points are eroded from "
+"cluster"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1147
-msgid "Show marker"
+#: ../src/backend/filters/clusterAnalysis.cpp:1028
+msgid "Clustering Params"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1151
-msgid "Display an interactive object to set transform origin"
+#: ../src/backend/filters/clusterAnalysis.cpp:1033
+msgid "Size Cropping"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1153
-msgid "Display a small marker to denote transform origin"
+#: ../src/backend/filters/clusterAnalysis.cpp:1036
+msgid "Remove clusters based upon size distribution"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1169
-msgid "Translation"
+#: ../src/backend/filters/clusterAnalysis.cpp:1043
+msgid "Min Size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1172
-msgid "Translation vector for transform"
+#: ../src/backend/filters/clusterAnalysis.cpp:1046
+msgid "Remove clusters below this size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1184
-msgid "Offset"
+#: ../src/backend/filters/clusterAnalysis.cpp:1051
+msgid "Max Size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1188
-msgid "Scalar to use to offset each point's associated value"
+#: ../src/backend/filters/clusterAnalysis.cpp:1054
+msgid "Remove clusters above this size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1205
-#: ../src/backend/filters/transform.cpp:1232
-msgid "Origin of scale trasnform"
+#: ../src/backend/filters/clusterAnalysis.cpp:1063
+msgid "Show number of clusters as a function of cluster size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1212
-#: ../src/backend/filters/transform.cpp:1239
-msgid "Scale Fact."
+#: ../src/backend/filters/clusterAnalysis.cpp:1069
+msgid "Log Scale"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1215
-#: ../src/backend/filters/transform.cpp:1242
-msgid "Enlargement factor for scaling around origin"
+#: ../src/backend/filters/clusterAnalysis.cpp:1072
+msgid "Use logarithmic scale for size distribution"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1258
-msgid "Origin of rotation"
+#: ../src/backend/filters/clusterAnalysis.cpp:1079
+msgid "Morphology Dist."
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1266
-msgid "Axis around which to revolve"
+#: ../src/backend/filters/clusterAnalysis.cpp:1082
+msgid "Create a plot showing cluster aspect ratio"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1271
-msgid "Angle (deg)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1088
+msgid "Cluster Id"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1274
-msgid "Angle to perform rotation (ACW, as viewed from axis towards origin)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1091
+msgid "Assign cluster output a unique per-cluster value (id)."
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1291
-msgid "Noise Type"
+#: ../src/backend/filters/clusterAnalysis.cpp:1098
+msgid "Chemistry Dist."
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1294
-msgid "Method to use to degrade point data"
+#: ../src/backend/filters/clusterAnalysis.cpp:1101
+msgid "Create a plot showing chemistry for each cluster size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1301
-msgid "Noise level"
+#: ../src/backend/filters/clusterAnalysis.cpp:1111
+msgid "Convert cluster counts to composition"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1303
-msgid "Standard dev."
+#: ../src/backend/filters/clusterAnalysis.cpp:1117
+msgid "Postprocess"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1311
-msgid "Amplitude of noise"
+#: ../src/backend/filters/clusterAnalysis.cpp:1136
+msgid "If selected, use as \"core\" ion type (can make clusters)"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1323
-msgid "Transform Params"
+#: ../src/backend/filters/clusterAnalysis.cpp:1141
+msgid "Core Ranges"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1660
-msgid "White"
+#: ../src/backend/filters/clusterAnalysis.cpp:1147
+msgid "Enable/Disable All"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1662
-msgid "Gaussian"
+#: ../src/backend/filters/clusterAnalysis.cpp:1152
+msgid "Enable/disable all ions"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:60
-msgid "Box only"
+#: ../src/backend/filters/clusterAnalysis.cpp:1165
+msgid ""
+"If selected, use as \"bulk\" ion type (can be included in existing clusters)"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:61
-msgid "Tick"
+#: ../src/backend/filters/clusterAnalysis.cpp:1170
+msgid "Bulk Ranges"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:62
-msgid "Dimension"
+#: ../src/backend/filters/clusterAnalysis.cpp:1186
+msgid "Max. Sep + Erode"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:531
-msgid "If true, show box, otherwise hide box"
+#: ../src/backend/filters/clusterAnalysis.cpp:1939
+msgid " --------------------------- Parameter selection notice ------------- "
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:544
-msgid "Style"
+#: ../src/backend/filters/clusterAnalysis.cpp:1940
+msgid "You have specified a bulk distance larger than half your link distance."
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:547
-msgid "Box display mode"
+#: ../src/backend/filters/clusterAnalysis.cpp:1941
+msgid ""
+"You can do this; thats OK, but the output is no longer independent of the "
+"computational process;"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:550
-msgid "Display mode"
+#: ../src/backend/filters/clusterAnalysis.cpp:1942
+msgid ""
+"This will be a problem in the case where two or more clusters can equally "
+"lay claim to a \"bulk\" ion. "
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:559
-msgid "Fixed Tick Num"
+#: ../src/backend/filters/clusterAnalysis.cpp:1943
+msgid ""
+" If your inter-cluster distance is sufficiently large (larger than your bulk "
+"linking distance), then you can get away with this."
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:563
+#: ../src/backend/filters/clusterAnalysis.cpp:1944
 msgid ""
-"If true, evenly use specified number of ticks. Otherwise, use distance to "
-"determine tick count"
+" In theory it is possible to \"join\" the clusters, but this has not been "
+"implemented for speed reasons."
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:571
-msgid "Num X"
+#: ../src/backend/filters/clusterAnalysis.cpp:1945
+msgid ""
+"If you want this, please contact the author, or just use the source to add "
+"this in yourself."
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:574
-msgid "Tick count in X direction"
+#: ../src/backend/filters/clusterAnalysis.cpp:1946
+msgid "---------------------------------------------------------------------- "
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:579
-msgid "Num Y"
+#: ../src/backend/filters/clusterAnalysis.cpp:1975
+msgid "Build Core"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:582
-msgid "Tick count in Y direction"
+#: ../src/backend/filters/clusterAnalysis.cpp:2003
+msgid "Core"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:587
-msgid "Num Z"
+#: ../src/backend/filters/clusterAnalysis.cpp:2126
+msgid "Bulk"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:590
-msgid "Tick count in Z direction"
+#: ../src/backend/filters/clusterAnalysis.cpp:2204
+msgid "Erode"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:596
-msgid "Spacing X"
+#: ../src/backend/filters/clusterAnalysis.cpp:2282
+msgid "Re-Collate"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:600
-msgid "Distance between ticks on X axis"
+#: ../src/backend/filters/clusterAnalysis.cpp:2337
+msgid "Classify Core"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:604
-msgid "Spacing Y"
+#: ../src/backend/filters/clusterAnalysis.cpp:2428
+msgid "Build Bulk"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:608
-msgid "Distance between ticks on Y axis"
+#: ../src/backend/filters/clusterAnalysis.cpp:2676
+#: ../src/backend/filters/clusterAnalysis.cpp:2879
+msgid "Cluster Size"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:612
-msgid "Spacing Z"
+#: ../src/backend/filters/clusterAnalysis.cpp:2677
+#: ../src/backend/filters/clusterAnalysis.cpp:2883
+msgid "Frequency"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:616
-msgid "Distance between ticks on Z axis"
+#: ../src/backend/filters/clusterAnalysis.cpp:2881
+msgid "Composition"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:619
-msgid "Tick marks"
+#: ../src/backend/filters/spatialAnalysis.cpp:123
+msgid "Local Density"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:626
-msgid "Box Colour"
+#: ../src/backend/filters/spatialAnalysis.cpp:124
+msgid "Density Filtering"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:630
-msgid "Colour of the bounding box"
+#: ../src/backend/filters/spatialAnalysis.cpp:125
+msgid "Radial Distribution"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:635
-msgid "Line thickness"
+#: ../src/backend/filters/spatialAnalysis.cpp:126
+msgid "Axial Distribution"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:639
-msgid "Thickness of the lines used to draw the box"
+#: ../src/backend/filters/spatialAnalysis.cpp:127
+msgid "Binomial Distribution"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:647
-#: ../src/backend/filters/annotation.cpp:848
-msgid "Font Size"
+#: ../src/backend/filters/spatialAnalysis.cpp:128
+msgid "Point Em/Replacement"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:650
-msgid "Relative size for text"
+#: ../src/backend/filters/spatialAnalysis.cpp:129
+msgid "Local Concentration"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:73
-msgid "Arrow"
+#: ../src/backend/filters/spatialAnalysis.cpp:133
+msgid "Neighbour Count"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:74
-msgid "Text"
+#: ../src/backend/filters/spatialAnalysis.cpp:643
+msgid "Load"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:75
-msgid "Arrow+Text"
+#: ../src/backend/filters/spatialAnalysis.cpp:660
+#: ../src/backend/filters/spatialAnalysis.cpp:2330
+#: ../src/backend/filters/spatialAnalysis.cpp:2383
+#: ../src/backend/filters/spatialAnalysis.cpp:2733
+#: ../src/backend/filters/spatialAnalysis.cpp:3022
+#: ../src/backend/filters/spatialAnalysis.cpp:3540
+#: ../src/backend/filters/spatialAnalysis.cpp:4184
+msgid "Build"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:76
-msgid "Angle"
+#: ../src/backend/filters/spatialAnalysis.cpp:705
+#: ../src/backend/filters/spatialAnalysis.cpp:3558
+#: ../src/backend/filters/spatialAnalysis.cpp:4073
+#: ../src/backend/filters/spatialAnalysis.cpp:4201
+msgid "Compute"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:77
-msgid "Ruler"
+#: ../src/backend/filters/spatialAnalysis.cpp:803
+msgid "Spatial analysis algorithm to use"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:524
-msgid "Enable"
+#: ../src/backend/filters/spatialAnalysis.cpp:827
+#: ../src/backend/filters/spatialAnalysis.cpp:878
+msgid "Stop Mode"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:527
-msgid "Enable/disable annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:830
+msgid "Method to use to terminate algorithm when examining each point"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:548
-msgid "Type or style of annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:837
+msgid "NN Max"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:564
-#: ../src/backend/filters/annotation.cpp:668
-msgid "Text of annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:840
+msgid "Maximum number of neighbours to examine"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:572
-msgid "Position of annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:847
+msgid "Normalise bins"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:576
-#: ../src/backend/filters/annotation.cpp:683
-#: ../src/backend/filters/annotation.cpp:742
-#: ../src/backend/filters/annotation.cpp:831
-msgid "Up dir"
+#: ../src/backend/filters/spatialAnalysis.cpp:850
+msgid ""
+"Normalise counts by binwidth. Needed when comparing NN histograms against "
+"one another"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:580
-#: ../src/backend/filters/annotation.cpp:835
-msgid "Vector for up direction of annotation text"
+#: ../src/backend/filters/spatialAnalysis.cpp:856
+msgid "Show Random"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:584
-#: ../src/backend/filters/annotation.cpp:690
-#: ../src/backend/filters/annotation.cpp:734
-#: ../src/backend/filters/annotation.cpp:839
-msgid "Across dir"
+#: ../src/backend/filters/spatialAnalysis.cpp:859
+msgid "Show a fitted (density matched) theoretical distribution"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:588
-#: ../src/backend/filters/annotation.cpp:843
-msgid "Reading direction for annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:870
+msgid "Dist Max"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:593
-#: ../src/backend/filters/annotation.cpp:675
-#: ../src/backend/filters/annotation.cpp:769
-msgid "Text size"
+#: ../src/backend/filters/spatialAnalysis.cpp:873
+msgid "Maximum distance from each point for search"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:597
-#: ../src/backend/filters/annotation.cpp:679
-#: ../src/backend/filters/annotation.cpp:851
-msgid "Relative size of annotation text"
+#: ../src/backend/filters/spatialAnalysis.cpp:890
+#: ../src/backend/filters/spatialAnalysis.cpp:1024
+msgid "Number of bins for output 1D RDF plot"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:609
-#: ../src/backend/filters/annotation.cpp:650
-msgid "3D position for tail of arrow"
+#: ../src/backend/filters/spatialAnalysis.cpp:896
+msgid "Surface Remove"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:617
-#: ../src/backend/filters/annotation.cpp:659
-msgid "3D Position to which arrow points"
+#: ../src/backend/filters/spatialAnalysis.cpp:899
+msgid ""
+"Exclude surface as part of source to minimise bias in RDF (at cost of "
+"increased noise)"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:620
-#: ../src/backend/filters/annotation.cpp:730
-msgid "Positioning"
+#: ../src/backend/filters/spatialAnalysis.cpp:906
+msgid "Remove Dist"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:625
-#: ../src/backend/filters/annotation.cpp:697
-msgid "Tip radius"
+#: ../src/backend/filters/spatialAnalysis.cpp:909
+msgid "Minimum distance to remove from surface"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:629
-msgid "Size of the arrow head"
+#: ../src/backend/filters/spatialAnalysis.cpp:917
+#: ../src/backend/filters/spatialAnalysis.cpp:1029
+msgid "Plot colour "
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:633
-msgid "Line size"
+#: ../src/backend/filters/spatialAnalysis.cpp:920
+#: ../src/backend/filters/spatialAnalysis.cpp:1032
+msgid "Colour of output plot"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:637
-msgid "Thickness of line used to draw arrow stem"
+#: ../src/backend/filters/spatialAnalysis.cpp:924
+#: ../src/backend/filters/spatialAnalysis.cpp:1010
+#: ../src/backend/filters/spatialAnalysis.cpp:1015
+#: ../src/backend/filters/spatialAnalysis.cpp:1064
+#: ../src/backend/filters/spatialAnalysis.cpp:1103
+msgid "Alg. Params."
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:671
-msgid "Options"
+#: ../src/backend/filters/spatialAnalysis.cpp:937
+#: ../src/backend/filters/spatialAnalysis.cpp:1207
+msgid "Source"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:707
-msgid "Position A"
+#: ../src/backend/filters/spatialAnalysis.cpp:940
+msgid "Ions to use for initiating RDF search"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:711
-msgid "Location of first non-central vertex"
+#: ../src/backend/filters/spatialAnalysis.cpp:953
+#: ../src/backend/filters/spatialAnalysis.cpp:1223
+#: ../src/backend/filters/spatialAnalysis.cpp:1249
+msgid "Enable/disable ion as source"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:715
-msgid "Origin "
+#: ../src/backend/filters/spatialAnalysis.cpp:958
+#: ../src/backend/filters/spatialAnalysis.cpp:1228
+msgid "Source Ion"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:719
-msgid "Location of central vertex"
+#: ../src/backend/filters/spatialAnalysis.cpp:965 ../src/gl/cameras.cpp:611
+msgid "Target"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:723
-msgid "Position B"
+#: ../src/backend/filters/spatialAnalysis.cpp:968
+#: ../src/backend/filters/spatialAnalysis.cpp:1264
+msgid "Enable/disable all ions as target"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:727
-msgid "Location of second non-central vertex"
+#: ../src/backend/filters/spatialAnalysis.cpp:980
+#: ../src/backend/filters/spatialAnalysis.cpp:1276
+msgid "Enable/disable this ion as target"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:738
-msgid "Reading direction for angle text"
+#: ../src/backend/filters/spatialAnalysis.cpp:984
+msgid "Target Ion"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:743
-msgid "Vector for up direction of angle text"
+#: ../src/backend/filters/spatialAnalysis.cpp:994
+msgid "Cutoff"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:751
-msgid "Reflexive"
+#: ../src/backend/filters/spatialAnalysis.cpp:997
+msgid "Remove points with local density above/below this value"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:754
-msgid "Measure interor (enabled) or exterior angle (disabled)"
+#: ../src/backend/filters/spatialAnalysis.cpp:1003
+msgid "Retain Upper"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:759
-msgid "Show Angle"
+#: ../src/backend/filters/spatialAnalysis.cpp:1006
+msgid "Retain either points with density above (enabled) or below cutoff"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:763
-msgid "Display angle text (when enabled)"
+#: ../src/backend/filters/spatialAnalysis.cpp:1052
+msgid "Vector between centre and end of cylinder"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:773
-msgid "Size of angle text"
+#: ../src/backend/filters/spatialAnalysis.cpp:1071
+#: ../src/backend/filters/spatialAnalysis.cpp:3827
+#: ../src/backend/filters/spatialAnalysis.cpp:3886
+msgid "Block size"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:791
-msgid "Digit format"
+#: ../src/backend/filters/spatialAnalysis.cpp:1074
+msgid "Number of ions to use per block"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:795
-msgid ""
-"Format of angle text; # for numeral position, '.' for separator, eg ##.## "
-"gives 12.34"
+#: ../src/backend/filters/spatialAnalysis.cpp:1081
+msgid "Max Block Aspect"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:801
-#: ../src/backend/filters/annotation.cpp:886
-msgid "Sphere size"
+#: ../src/backend/filters/spatialAnalysis.cpp:1084
+msgid ""
+"Maximum allowable block aspect ratio. Blocks above this aspect are "
+"discarded. Setting too high decreases correlation strength. Too low causes "
+"loss of statistical power."
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:805
-#: ../src/backend/filters/annotation.cpp:890
-msgid "Marker sphere size for manipulating tool"
+#: ../src/backend/filters/spatialAnalysis.cpp:1095
+msgid "Extrusion Direction"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:819
-msgid "Ruler beginning 3D location"
+#: ../src/backend/filters/spatialAnalysis.cpp:1098
+msgid "Direction in which blocks are extended during construction."
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:827
-msgid "Ruler finish 3D location"
+#: ../src/backend/filters/spatialAnalysis.cpp:1107
+msgid "Plot Counts"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:857
-msgid "Fixed ticks"
+#: ../src/backend/filters/spatialAnalysis.cpp:1110
+msgid "Show the counts in the binomial histogram"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:860
+#: ../src/backend/filters/spatialAnalysis.cpp:1119
 msgid ""
-"Use fixed (enabled) number of text markers, or one every fixed distance "
-"(disabled)"
+"Normalise the counts in the binomial histogram to a probability density "
+"function"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:867
-msgid "Num Ticks"
+#: ../src/backend/filters/spatialAnalysis.cpp:1133
+msgid "Display Grid"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:870
-msgid "Number of tick marks along ruler"
+#: ../src/backend/filters/spatialAnalysis.cpp:1142
+msgid "View Options"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:877
-msgid "Tick Spacing"
+#: ../src/backend/filters/spatialAnalysis.cpp:1148
+msgid "Data File"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:880
-msgid "Distance between tick marks along ruler"
+#: ../src/backend/filters/spatialAnalysis.cpp:1152
+msgid "Pos file of points to subtract/replace/etc"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:904
-msgid "Colour for ruler and ticks"
+#: ../src/backend/filters/spatialAnalysis.cpp:1157
+msgid "Match Tol."
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:191
-msgid "Sampling"
+#: ../src/backend/filters/spatialAnalysis.cpp:1160
+msgid "Tolerance to allow for matching"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:447
-msgid "By Count"
+#: ../src/backend/filters/spatialAnalysis.cpp:1176
+msgid "Replacment condition"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:450
-msgid "Sample up to a fixed number of ions"
+#: ../src/backend/filters/spatialAnalysis.cpp:1182
+msgid "Replace value"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:456
-msgid "Per Species"
+#: ../src/backend/filters/spatialAnalysis.cpp:1185
+msgid "Use value data from file when replacing ions"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:460
-msgid "Use species specific (from ranging) sampling values"
+#: ../src/backend/filters/spatialAnalysis.cpp:1190
+msgid "Replacement"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:489
-msgid "Sampling value for species"
+#: ../src/backend/filters/spatialAnalysis.cpp:1210
+msgid "Enable/disable all ions as source"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:497
-#: ../src/backend/filters/ionDownsample.cpp:521
-msgid "Sampling rates"
+#: ../src/backend/filters/spatialAnalysis.cpp:1236
+msgid "Ions to use as Numerator for conc. calculation"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:505
-msgid "Output Count"
+#: ../src/backend/filters/spatialAnalysis.cpp:1785
+msgid "Spatial analysis aborted by user"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:508
-msgid "Sample up to this value of points"
+#: ../src/backend/filters/spatialAnalysis.cpp:1786
+msgid "Insufficient memory to complete analysis"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:513
-msgid "Out Fraction"
+#: ../src/backend/filters/spatialAnalysis.cpp:1787
+msgid "Required range data not present"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:517
-msgid "Sample this fraction of points"
+#: ../src/backend/filters/spatialAnalysis.cpp:1788
+msgid "Insufficient memory for binomial. Reduce input size?"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:37
-msgid "Rectilinear"
+#: ../src/backend/filters/spatialAnalysis.cpp:1789
+msgid "Insufficient points to continue"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:38
-msgid "Convex hull"
+#: ../src/backend/filters/spatialAnalysis.cpp:1790
+msgid "Unable to load file"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:200
-msgid "No ions"
+#: ../src/backend/filters/spatialAnalysis.cpp:2437
+#: ../src/backend/filters/spatialAnalysis.cpp:2756
+#: ../src/backend/filters/spatialAnalysis.cpp:3046
+msgid "Analyse"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:226
-#: ../src/backend/filters/spectrumPlot.cpp:432
-msgid ""
-"Background fit failed - input data was considered ill formed (gauss-test)"
+#: ../src/backend/filters/spatialAnalysis.cpp:2516
+#: ../src/backend/filters/spatialAnalysis.cpp:2606
+#: ../src/backend/filters/spatialAnalysis.cpp:2672
+msgid "Radial Distance"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:227
-msgid "Following data has not been corrected"
+#: ../src/backend/filters/spatialAnalysis.cpp:2518
+#: ../src/backend/filters/spatialAnalysis.cpp:2611
+msgid "Count/Distance"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:279
-msgid "--Counts--"
+#: ../src/backend/filters/spatialAnalysis.cpp:2523
+#: ../src/backend/filters/spatialAnalysis.cpp:2616
+msgid "NN Freq."
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:289
-msgid "Total Ranged\t"
+#: ../src/backend/filters/spatialAnalysis.cpp:2663
+msgid "Warning, "
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:294
-msgid "Total (incl. unranged)\t"
+#: ../src/backend/filters/spatialAnalysis.cpp:2664
+msgid ""
+" points were unable to find neighbour points that exceeded the search "
+"radius, and thus terminated prematurely"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:307
-msgid "n/a"
+#: ../src/backend/filters/spatialAnalysis.cpp:2674
+msgid " RDF"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:317
-msgid "Unranged"
+#: ../src/backend/filters/spatialAnalysis.cpp:2952
+#: ../src/backend/filters/spatialAnalysis.cpp:3251
+msgid "Number Density (\\#/Vol^3)"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:330
-msgid "Number of points : "
+#: ../src/backend/filters/spatialAnalysis.cpp:2977
+#: ../src/backend/filters/spatialAnalysis.cpp:3271
+msgid "Warning,"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:359
-msgid "Rectilinear Bounds : "
+#: ../src/backend/filters/spatialAnalysis.cpp:2978
+#: ../src/backend/filters/spatialAnalysis.cpp:3272
+msgid " points were un-analysable. These have been dropped"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:364
-msgid "Volume (len^3): "
+#: ../src/backend/filters/spatialAnalysis.cpp:3000
+#: ../src/backend/filters/spatialAnalysis.cpp:3294
+msgid "And so on..."
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:381
-msgid "Convex Volume (len^3): "
+#: ../src/backend/filters/spatialAnalysis.cpp:3376
+msgid "Extract"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:384
-msgid "Unable to compute volume"
+#: ../src/backend/filters/spatialAnalysis.cpp:3449
+msgid "Reduce"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:413
-msgid "Ranged Density (pts/vol):"
+#: ../src/backend/filters/spatialAnalysis.cpp:3604
+msgid "Insufficient points to complete analysis"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:418
-msgid "Total Density (pts/vol):"
+#: ../src/backend/filters/spatialAnalysis.cpp:3627
+msgid "Axial Distance"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:445
-msgid "Compositions"
+#: ../src/backend/filters/spatialAnalysis.cpp:3629
+msgid " 1D Dist. Func."
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:446
-msgid "Display compositional data for points in console"
+#: ../src/backend/filters/spatialAnalysis.cpp:3698
+msgid "Binomial"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:450
-msgid "Counts"
+#: ../src/backend/filters/spatialAnalysis.cpp:3829
+#: ../src/backend/filters/spatialAnalysis.cpp:3888
+msgid "Rel. Frequency"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:451
-msgid "Display count data for points in console"
+#: ../src/backend/filters/spatialAnalysis.cpp:3966
+msgid "Build Numerator"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:458
-msgid "Ion data"
+#: ../src/backend/filters/spatialAnalysis.cpp:3980
+msgid "Build Denominator"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:466
-msgid "Normalise count data"
+#: ../src/backend/filters/ionColour.cpp:257
+msgid "Colour Map"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:530
-msgid "Volume"
+#: ../src/backend/filters/ionColour.cpp:265
+msgid "Reverse map"
+msgstr ""
+
+#: ../src/backend/filters/ionColour.cpp:266
+msgid "Reverse the colour scale"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:533
-msgid "Compute volume for point data"
+#: ../src/backend/filters/ionColour.cpp:279
+msgid "Opacity"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:549
-msgid "Select volume counting technique"
+#: ../src/backend/filters/ionColour.cpp:286
+msgid "Num Colours"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:562
-msgid "Volume data"
+#: ../src/backend/filters/ionColour.cpp:288
+msgid "Number of unique colours to use in colour map"
 msgstr ""
 
 #: ../src/backend/filters/dataLoad.cpp:61
@@ -4304,13 +4664,6 @@ msgid ""
 "Consider rescaling data before loading"
 msgstr ""
 
-#: ../src/backend/filters/dataLoad.cpp:484
-#: ../src/backend/filters/dataLoad.cpp:505
-#: ../src/backend/filters/rangeFile.cpp:558
-#: ../src/backend/filters/rangeFile.cpp:578
-msgid "File"
-msgstr ""
-
 #: ../src/backend/filters/dataLoad.cpp:485
 msgid "File from which to load data"
 msgstr ""
@@ -4452,328 +4805,142 @@ msgstr ""
 msgid "Mixed data"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:441
+#: ../src/backend/filters/spectrumPlot.cpp:445
 msgid "Background:"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:496
+#: ../src/backend/filters/spectrumPlot.cpp:504
 msgid "Relative "
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:499
+#: ../src/backend/filters/spectrumPlot.cpp:507
 msgid "Probability Density"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:576
+#: ../src/backend/filters/spectrumPlot.cpp:584
 msgid "Step size for spectrum"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:581
+#: ../src/backend/filters/spectrumPlot.cpp:589
 msgid "Auto Min/max"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:585
+#: ../src/backend/filters/spectrumPlot.cpp:593
 msgid "Automatically compute spectrum upper and lower bound"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:590
+#: ../src/backend/filters/spectrumPlot.cpp:598
 msgid "Min"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:593
+#: ../src/backend/filters/spectrumPlot.cpp:601
 msgid "Starting position for spectrum"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:598
+#: ../src/backend/filters/spectrumPlot.cpp:606
 msgid "Max"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:601
+#: ../src/backend/filters/spectrumPlot.cpp:609
 msgid "Ending position for spectrum"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:609
+#: ../src/backend/filters/spectrumPlot.cpp:617
 msgid "Logarithmic"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:612
+#: ../src/backend/filters/spectrumPlot.cpp:620
 msgid "Convert the plot to logarithmic mode"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:624
+#: ../src/backend/filters/spectrumPlot.cpp:632
 msgid "Normalisation"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:627
+#: ../src/backend/filters/spectrumPlot.cpp:635
 msgid "Rescale the plot height, to make inter-spectrum comparisons easier"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:634
+#: ../src/backend/filters/spectrumPlot.cpp:642
 msgid "Lower Bound"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:638
+#: ../src/backend/filters/spectrumPlot.cpp:646
 msgid "Do not use data below this x-value for normalisation"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:642
+#: ../src/backend/filters/spectrumPlot.cpp:650
 msgid "Upper Bound"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:646
+#: ../src/backend/filters/spectrumPlot.cpp:654
 msgid "Do not use data above this x-value for normalisation"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:664
+#: ../src/backend/filters/spectrumPlot.cpp:672
 msgid "Visual style of plot"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:671
+#: ../src/backend/filters/spectrumPlot.cpp:679
 msgid "Colour of plotted spectrum"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:153
-msgid "Pre-Allocate"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:288 ../src/backend/filter.cpp:54
-msgid "Range"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:561
-msgid "File to use for range data"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:571
-msgid "Drop unranged"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:573
-msgid "Remove unranged points when generating output"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:583
-msgid "Legend"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:585
-msgid "Display colour legend for enabled ions"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:589
-msgid "View"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:605
-msgid "All Ions"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:606
-msgid "Enable/disable all ions at once"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:614
-msgid "Species"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:621
-msgid "IonID "
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:622
-msgid "Enable/disable specified ion"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:632
-msgid "Active Ion "
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:634
-msgid "If true, ion is used in output"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:644
-msgid "Colour "
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:648
-msgid "Colour used to represent ion"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:671
-msgid "All Ranges"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:672
-msgid "Enable/disable all ranges"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:687
-msgid "Active Rng "
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:690
-msgid ""
-"Enable/disable specified range (ion must also be enabled to activiate range)"
+#: ../src/backend/filters/spectrumPlot.cpp:694
+msgid "Model"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:694
-msgid "Ion "
+#: ../src/backend/filters/spectrumPlot.cpp:697
+msgid "Fitting method to use"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:697
-msgid "Name of ion associate to this range"
+#: ../src/backend/filters/spectrumPlot.cpp:708
+msgid "Fit Start"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:706
-msgid "Start rng "
+#: ../src/backend/filters/spectrumPlot.cpp:709
+msgid "Start mass value for fitting background"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:709
-msgid "Start value for range"
+#: ../src/backend/filters/spectrumPlot.cpp:715
+msgid "Fit End"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:714
-msgid "End rng "
+#: ../src/backend/filters/spectrumPlot.cpp:716
+msgid "End mass value for fitting background"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.cpp:717
-msgid "Stopping value for range`"
+#: ../src/backend/filters/spectrumPlot.cpp:729
+msgid "Corr. Only"
 msgstr ""
 
-#: ../src/backend/state.cpp:151
-msgid ""
-"This file is a \"state\" file for the 3Depict program, and stores "
-"information about a particular analysis session. This file should be a valid "
-"\"XML\" file"
+#: ../src/backend/filters/spectrumPlot.cpp:730
+msgid "Only show corrected spectrum, not fit"
 msgstr ""
 
-#: ../src/backend/state.cpp:318
-msgid "Failed to allocate parser"
+#: ../src/backend/filters/spectrumPlot.cpp:738
+msgid "Background Mode"
 msgstr ""
 
-#: ../src/backend/state.cpp:353
-msgid ""
-"Unable to retrieve root node in input state file... Is this really a non-"
-"empty XML file?"
+#: ../src/backend/configFile.cpp:187
+msgid "Config file present, but is not valid (root node test)"
 msgstr ""
 
-#: ../src/backend/state.cpp:360
-msgid "Base state node missing. Is this really a state XML file??"
+#: ../src/backend/configFile.cpp:228
+msgid "Unable to interpret recent file entry"
 msgstr ""
 
-#: ../src/backend/state.cpp:389
-msgid "State was created by a newer version of this program.. "
+#: ../src/backend/configFile.cpp:268
+msgid "Unable to determine filter type in defaults listing."
 msgstr ""
 
-#: ../src/backend/state.cpp:390
-msgid "file reading will continue, but may fail."
+#: ../src/backend/configFile.cpp:605
+msgid "Online access for non win32/apple platforms is intentionally disabled, "
 msgstr ""
 
-#: ../src/backend/state.cpp:395
+#: ../src/backend/configFile.cpp:606
 msgid ""
-"Warning, unparseable version number in state file. File reading will "
-"continue, but may fail"
-msgstr ""
-
-#: ../src/backend/state.cpp:402
-msgid "Unable to find the \"writer\" node"
-msgstr ""
-
-#: ../src/backend/state.cpp:412
-msgid "Unable to find the \"backcolour\" node."
-msgstr ""
-
-#: ../src/backend/state.cpp:419
-msgid "\"backcolour\" node missing \"r\" value."
-msgstr ""
-
-#: ../src/backend/state.cpp:424
-msgid "Unable to interpret \"backColour\" node's \"r\" value."
-msgstr ""
-
-#: ../src/backend/state.cpp:432
-msgid "\"backcolour\" node missing \"g\" value."
-msgstr ""
-
-#: ../src/backend/state.cpp:438
-msgid "Unable to interpret \"backColour\" node's \"g\" value."
-msgstr ""
-
-#: ../src/backend/state.cpp:446
-msgid "\"backcolour\" node missing \"b\" value."
-msgstr ""
-
-#: ../src/backend/state.cpp:452
-msgid "Unable to interpret \"backColour\" node's \"b\" value."
-msgstr ""
-
-#: ../src/backend/state.cpp:459
-msgid "\"backcolour\"s rgb values must be in range [0,1]"
-msgstr ""
-
-#: ../src/backend/state.cpp:487
-msgid "Unable to find or interpret \"showaxis\" node"
-msgstr ""
-
-#: ../src/backend/state.cpp:531
-msgid "Unable to locate \"filtertree\" node."
-msgstr ""
-
-#: ../src/backend/state.cpp:547
-msgid "Cameras section missing \"active\" node."
-msgstr ""
-
-#: ../src/backend/state.cpp:555
-msgid "Unable to find property \"value\"  for \"cameras->active\" node."
-msgstr ""
-
-#: ../src/backend/state.cpp:561
-msgid "Unable to interpret property \"value\"  for \"cameras->active\" node."
-msgstr ""
-
-#: ../src/backend/state.cpp:580
-msgid "Failed to interpret camera state for camera : "
-msgstr ""
-
-#: ../src/backend/state.cpp:588
-msgid "Unable to interpret the camera type for camera : "
-msgstr ""
-
-#: ../src/backend/state.cpp:632
-msgid "Unable to locate stash name for stash "
-msgstr ""
-
-#: ../src/backend/state.cpp:639
-msgid "Empty stash name for stash "
-msgstr ""
-
-#: ../src/backend/state.cpp:648
-msgid "No filter tree for stash:"
-msgstr ""
-
-#: ../src/backend/state.cpp:654
-msgid "For stash "
-msgstr ""
-
-#: ../src/backend/state.cpp:686
-msgid "Unrecognised effect :"
-msgstr ""
-
-#: ../src/backend/state.cpp:696
-msgid "Duplicate effect found"
-msgstr ""
-
-#: ../src/backend/state.cpp:696
-msgid " cannot use."
-msgstr ""
-
-#: ../src/backend/state.cpp:706
-msgid "Error reading effect : "
-msgstr ""
-
-#: ../src/backend/state.cpp:898
-msgid "-merge"
+"regardless of the settings you use here. Use your package manager to keep up-"
+"to-date"
 msgstr ""
 
 #: ../src/backend/filtertreeAnalyse.cpp:223
@@ -4837,269 +5004,294 @@ msgid ""
 "Rangefile set to drop unranged data, however a child filter requires it."
 msgstr ""
 
-#: ../src/backend/filtertreeAnalyse.cpp:613
-msgid "Composition results possibly altered"
+#: ../src/backend/filtertreeAnalyse.cpp:613
+msgid "Composition results possibly altered"
+msgstr ""
+
+#: ../src/backend/filtertreeAnalyse.cpp:614
+msgid ""
+"Filters and settings selected that could bias reported composition. Check to "
+"see if species biasing may occcur in the filter tree - this warning is "
+"provisional only."
+msgstr ""
+
+#: ../src/backend/plot.cpp:29
+msgid "Moving avg."
+msgstr ""
+
+#: ../src/backend/plot.cpp:33
+msgid "Lines"
+msgstr ""
+
+#: ../src/backend/plot.cpp:34
+msgid "Bars"
+msgstr ""
+
+#: ../src/backend/plot.cpp:35
+msgid "Steps"
+msgstr ""
+
+#: ../src/backend/plot.cpp:36
+msgid "Stem"
+msgstr ""
+
+#: ../src/backend/plot.cpp:37
+msgid "Points"
+msgstr ""
+
+#: ../src/backend/plot.cpp:39
+msgid "Density"
+msgstr ""
+
+#: ../src/backend/plot.cpp:40
+msgid "Scatter"
+msgstr ""
+
+#: ../src/backend/plot.cpp:739 ../src/backend/plot.cpp:747
+msgid "Multiple data types"
+msgstr ""
+
+#: ../src/backend/plot.cpp:1581
+msgid "error"
+msgstr ""
+
+#: ../src/backend/plot.cpp:1821
+msgid "Amplitude"
+msgstr ""
+
+#: ../src/backend/filtertree.cpp:1151
+msgid "WARNING: Skipping node "
+msgstr ""
+
+#: ../src/backend/filtertree.cpp:1151
+msgid " as it was not recognised"
 msgstr ""
 
-#: ../src/backend/filtertreeAnalyse.cpp:614
-msgid ""
-"Filters and settings selected that could bias reported composition. Check to "
-"see if species biasing may occcur in the filter tree - this warning is "
-"provisional only."
+#: ../src/backend/filtertree.cpp:1189
+msgid "Error processing node: "
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:44 ../src/backend/APT/APTFileIO.cpp:79
-#: ../src/backend/APT/APTFileIO.cpp:103
-msgid "Error opening file"
+#: ../src/gl/cameras.cpp:596
+msgid "Lock"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:45
-msgid "Only found header, no data"
+#: ../src/gl/cameras.cpp:617
+msgid "Up Dir."
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:46
-msgid "Unable to reopen file after first scan"
+#: ../src/gl/cameras.cpp:625 ../src/gl/cameras.cpp:728
+msgid "Perspective"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:47
-msgid "Error whilst reading file contents"
+#: ../src/gl/cameras.cpp:631
+msgid "Projection"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:48 ../src/backend/APT/APTFileIO.cpp:49
-msgid "Unexpected file format"
+#: ../src/gl/cameras.cpp:640
+msgid "Field of View (deg)"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:50
-msgid "Insufficient memory to continue"
+#: ../src/gl/cameras.cpp:646
+msgid "View size"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:54
-msgid "Memory allocation failure on POS load"
+#: ../src/3Depict.cpp:397
+msgid "File : "
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:55
-msgid "Error opening pos file"
+#: ../src/3Depict.cpp:397
+msgid " does not exist. Skipping"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:56
-msgid "Pos file empty"
+#: ../src/common/constants.cpp:22
+msgid ""
+"Range Files (*.rng; *.env; *.rrng)|*.rng;*.env;*.rrng;*.RRNG;*.RNG;*.ENV|RNG "
+"File (*.rng)|*.rng;*.RNG|Environment File (*.env)|*.env;*.ENV|RRNG Files (*."
+"rrng)|*.rrng;*.RRNG|All Files (*)|*"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:57
-msgid "Pos file size appears to have non-integer number of entries"
+#: ../src/common/basics.cpp:183
+msgid "in the future?"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:58
-msgid "Error reading from pos file (after open)"
+#: ../src/common/basics.cpp:234
+msgid "a decade ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:59
-msgid "Error - Found NaN in pos file"
+#: ../src/common/basics.cpp:235
+msgid "a year ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:60
-msgid "Error - Found Inf in pos file"
+#: ../src/common/basics.cpp:236
+msgid "a month ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:61
-msgid "Pos load aborted by interrupt."
+#: ../src/common/basics.cpp:237
+msgid "a week ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:80
-msgid "No numerical data found"
+#: ../src/common/basics.cpp:238
+msgid "a day ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:81
-msgid "Error re-opening file, after first scan"
+#: ../src/common/basics.cpp:239
+msgid "an hour ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:82
-msgid "Unable to read file contents after open"
+#: ../src/common/basics.cpp:240
+msgid "45 minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:83
-msgid "Error interpreting field in file"
+#: ../src/common/basics.cpp:241
+msgid "30 minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:84
-msgid "Incorrect number of fields in file"
+#: ../src/common/basics.cpp:242
+msgid "20 minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:85 ../src/backend/APT/APTFileIO.cpp:107
-msgid "Unable to allocate memory to store data"
+#: ../src/common/basics.cpp:243
+msgid "15 minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:104
-msgid "File is empty"
+#: ../src/common/basics.cpp:244
+msgid "10 minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:105
-msgid "Filesize does not match expected format"
+#: ../src/common/basics.cpp:245
+msgid "5 minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:106
-msgid "File version number not <4, as expected"
+#: ../src/common/basics.cpp:246
+msgid "a minute ago"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:108
-msgid "Unable to detect endian-ness in file"
+#: ../src/common/basics.cpp:247
+msgid "30 seconds ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:48
-msgid "Error opening file, check name and permissions."
+#: ../src/common/basics.cpp:248
+msgid "10 seconds ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:49
-msgid ""
-"Error interpreting range file header, expecting ion count and range count, "
-"respectively."
+#: ../src/common/basics.cpp:249
+msgid "a second ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:50
-msgid ""
-"Range file appears to be empty, check file is a proper range file and is not "
-"empty."
+#: ../src/common/basics.cpp:254
+msgid "a few decades ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:51
-msgid "Error reading the long name for ion."
+#: ../src/common/basics.cpp:255
+msgid "a few years ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:52
-msgid "Error reading the short name for ion."
+#: ../src/common/basics.cpp:256
+msgid "a few months ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:53
-msgid ""
-"Error reading colour data in the file, expecting 3 decimal values, space "
-"separated."
+#: ../src/common/basics.cpp:257
+msgid "a few weeks ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:54
-msgid ""
-"Tried skipping to table separator line (line with dashes), but did not find "
-"it."
+#: ../src/common/basics.cpp:258
+msgid "a few days ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:55
-msgid ""
-"Number of ions in the table header did not match the number specified at the "
-"start of the file"
+#: ../src/common/basics.cpp:259
+msgid "a few hours ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:56
-msgid ""
-"Unexpected failure whilst trying to skip over range lead-in data (bit before "
-"range start value)"
+#: ../src/common/basics.cpp:266
+msgid "a few minutes ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:57
-msgid ""
-"Range table had an incorrect number of entries, should be 2 or 3 + number of "
-"ranges"
+#: ../src/common/basics.cpp:269
+msgid "a few seconds ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:58
-msgid "Unable to read range start and end values"
+#: ../src/common/basics.cpp:296
+msgid "moments ago"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:59
-msgid "Unable to read range table entry"
+#: ../src/common/colourmap.cpp:242
+msgid "Jet"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:60
-msgid ""
-"Error reading file, unexpected format, are you sure it is a proper range "
-"file?"
+#: ../src/common/colourmap.cpp:243
+msgid "Hot"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:61
-msgid ""
-"Too many ranges appeared to have range entries with no usable data (eg, all "
-"blank)"
+#: ../src/common/colourmap.cpp:244
+msgid "Cold"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:62
-msgid ""
-"Range file appears to contain malformed data, check things like start and "
-"ends of m/c are not equal or flipped."
+#: ../src/common/colourmap.cpp:245
+msgid "Grey"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:63
-msgid "Range file appears to be inconsistent (eg, overlapping ranges)"
+#: ../src/common/colourmap.cpp:246
+msgid "Cyclic"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:64
-msgid "No ion name mapping found  for multiple ion."
+#: ../src/common/colourmap.cpp:247
+msgid "General"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:65
-msgid "Polyatomic extension range matches multiple masses in first section"
+#: ../src/common/colourmap.cpp:248
+msgid "Blue"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:66
-msgid "Range file is exceedingly large. Refusing to open"
+#: ../src/common/colourmap.cpp:249
+msgid "Pseudo-Random"
 msgstr ""
 
-#: ../src/backend/APT/APTRanges.cpp:1404
-msgid ""
-"Range headings do not match order of the ions listed in the name "
-"specifications. The name specification ordering will be used when reading "
-"the range table, as the range heading section is declared as a comment in "
-"the file-format specifications, and is not to be intepreted by this program. "
-"Check range-species associations actually match what you expect."
+#: ../src/wx/wxcomponents.cpp:191
+msgid "Save Data..."
 msgstr ""
 
-#: ../src/backend/filter.cpp:52
-msgid "2D Plot"
+#: ../src/wx/wxcomponents.cpp:192
+msgid "Text File (*.txt)|*.txt|All Files (*)|*"
 msgstr ""
 
-#: ../src/backend/filter.cpp:53
-msgid "Draw"
+#: ../src/wx/wxcomponents.cpp:204
+msgid "Error saving file. Check output dir is writable."
 msgstr ""
 
-#: ../src/backend/filter.cpp:55
-msgid "Voxel"
+#: ../src/backend/filters/dataLoad.h:135
+msgid "Pos Data"
 msgstr ""
 
-#: ../src/wx/wxcomponents.h:82
-msgid "treeCtrl"
+#: ../src/backend/filters/ionInfo.h:103
+msgid "Ion info"
 msgstr ""
 
-#: ../src/backend/filters/transform.h:71
-msgid "Ion. Transform"
+#: ../src/backend/filters/externalProgram.h:69
+msgid "Ext. Program"
 msgstr ""
 
 #: ../src/backend/filters/ionColour.h:63
 msgid "Spectral Colour"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.h:72
-msgid "Bound box"
+#: ../src/backend/filters/profile.h:123
+msgid "Comp. Prof."
 msgstr ""
 
 #: ../src/backend/filters/ionDownsample.h:79
 msgid "Ion Sampler"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.h:103
-msgid "Ion info"
-msgstr ""
-
-#: ../src/backend/filters/dataLoad.h:135
-msgid "Pos Data"
-msgstr ""
-
-#: ../src/backend/filters/externalProgram.h:69
-msgid "Ext. Program"
+#: ../src/backend/filters/boundingBox.h:76
+msgid "Bound box"
 msgstr ""
 
-#: ../src/backend/filters/rangeFile.h:96
-msgid "Ranging"
+#: ../src/backend/filters/transform.h:71
+msgid "Ion. Transform"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.h:120
-msgid "Comp. Prof."
+#: ../src/wx/wxcomponents.h:82
+msgid "treeCtrl"
 msgstr ""
 
 #: ../data/startup-tips.txt:5
@@ -5154,7 +5346,9 @@ msgid ""
 msgstr ""
 
 #: ../data/startup-tips.txt:14
-msgid "You can abort most calculations by pressing Escape"
+msgid ""
+"You can abort most calculations either by pressing Escape (OSX/Linux), or by "
+"using the Abort button (Windows)"
 msgstr ""
 
 #: ../data/startup-tips.txt:15
@@ -5200,7 +5394,7 @@ msgstr ""
 #: ../data/startup-tips.txt:22
 msgid ""
 "You can ask questions about the program, or using it on your data on our "
-"forums (http://sourceforge.net/apps/phpbb/threedepict/)"
+"forums (https://sourceforge.net/p/threedepict/discussion/general/)"
 msgstr ""
 
 #: ../data/startup-tips.txt:23
@@ -5208,3 +5402,9 @@ msgid ""
 "By creating a camera, you can switch between orthographic and perspective "
 "views"
 msgstr ""
+
+#: ../data/startup-tips.txt:24
+msgid ""
+"You can open multiple files at once, and get a side-by-side view by "
+"translating (shifting) one of the datasets to one side"
+msgstr ""
diff --git a/translations/3Depict_de_DE.mo b/translations/3Depict_de_DE.mo
index c31b1ce..d746b34 100644
Binary files a/translations/3Depict_de_DE.mo and b/translations/3Depict_de_DE.mo differ
diff --git a/translations/3Depict_de_DE.po b/translations/3Depict_de_DE.po
index ca22634..ecaad27 100644
--- a/translations/3Depict_de_DE.po
+++ b/translations/3Depict_de_DE.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: 3Depict\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-04-26 23:23+0100\n"
+"POT-Creation-Date: 2016-05-31 11:15+1000\n"
 "PO-Revision-Date: 2012-07-09 08:21+0000\n"
 "Last-Translator: epix1234 <erich_s at gmx.de>\n"
 "Language-Team: German (Germany) (http://www.transifex.com/projects/p/3depict/"
@@ -21,246 +21,34 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 
-#: ../src/gl/cameras.cpp:596
-msgid "Lock"
-msgstr "Sperren"
-
-#: ../src/gl/cameras.cpp:603 ../src/backend/filters/ionClip.cpp:528
-#: ../src/backend/filters/ionClip.cpp:550
-#: ../src/backend/filters/ionClip.cpp:572
-#: ../src/backend/filters/ionClip.cpp:609
-#: ../src/backend/filters/compositionProfile.cpp:993
-#: ../src/backend/filters/compositionProfile.cpp:1031
-#: ../src/backend/filters/spatialAnalysis.cpp:846
-#: ../src/backend/filters/transform.cpp:1202
-#: ../src/backend/filters/transform.cpp:1229
-#: ../src/backend/filters/transform.cpp:1255
-#: ../src/backend/filters/annotation.cpp:568
-msgid "Origin"
-msgstr "Ursprung"
-
-#: ../src/gl/cameras.cpp:611 ../src/backend/filters/spatialAnalysis.cpp:769
-msgid "Target"
-msgstr "Ziel"
-
-#: ../src/gl/cameras.cpp:617
-msgid "Up Dir."
-msgstr "Up Dir."
-
-#: ../src/gl/cameras.cpp:625 ../src/gl/cameras.cpp:728
-msgid "Perspective"
-msgstr "Perspektivisch"
-
-#: ../src/gl/cameras.cpp:627 ../src/gl/cameras.cpp:730
-#: ../src/gui/mainFrame.cpp:5150
-msgid "Orthogonal"
-msgstr "Orthogonal"
-
-#: ../src/gl/cameras.cpp:631
-msgid "Projection"
-msgstr "Projektion"
-
-#: ../src/gl/cameras.cpp:640
-msgid "Field of View (deg)"
-msgstr "Bildausschnitt"
-
-#: ../src/gl/cameras.cpp:646
-msgid "View size"
-msgstr "Anzeigegröße"
-
-#: ../src/wx/wxcomponents.cpp:191
-msgid "Save Data..."
-msgstr "Datei speichern..."
-
-#: ../src/wx/wxcomponents.cpp:192
-msgid "Text File (*.txt)|*.txt|All Files (*)|*"
-msgstr "Text Datei (*.txt)|*.txt|Alle Dateien (*)|*"
-
-#: ../src/wx/wxcomponents.cpp:204
-msgid "Error saving file. Check output dir is writable."
-msgstr ""
-"Fehler beim Schreiben der Datei. Stellen Sie sicher, dass das "
-"Zielverzeichnis nicht schreibgeschüzt ist."
-
-#: ../src/wx/wxcomponents.cpp:204 ../src/gui/dialogs/ExportRngDialog.cpp:170
-#: ../src/gui/mainFrame.cpp:1448 ../src/gui/mainFrame.cpp:1573
-#: ../src/gui/mainFrame.cpp:1622 ../src/gui/mainFrame.cpp:1698
-#: ../src/gui/mainFrame.cpp:2245 ../src/gui/mainFrame.cpp:2311
-#: ../src/gui/mainFrame.cpp:2404 ../src/gui/mainFrame.cpp:2517
-msgid "Save error"
-msgstr "Fehler speichern"
-
-#: ../src/common/basics.cpp:183
-msgid "in the future?"
-msgstr "in Zukunft?"
-
-#: ../src/common/basics.cpp:234
-msgid "a decade ago"
-msgstr "vor zehn Jahren"
-
-#: ../src/common/basics.cpp:235
-msgid "a year ago"
-msgstr "vor einem Jahr"
-
-#: ../src/common/basics.cpp:236
-msgid "a month ago"
-msgstr "vor einem Monat"
-
-#: ../src/common/basics.cpp:237
-msgid "a week ago"
-msgstr "vor einer Woche"
-
-#: ../src/common/basics.cpp:238
-msgid "a day ago"
-msgstr "gestern"
-
-#: ../src/common/basics.cpp:239
-msgid "an hour ago"
-msgstr "vor einer Stunde"
-
-#: ../src/common/basics.cpp:240
-msgid "45 minutes ago"
-msgstr "vor 45 Minuten"
-
-#: ../src/common/basics.cpp:241
-msgid "30 minutes ago"
-msgstr "vor 30 Minuten"
-
-#: ../src/common/basics.cpp:242
-msgid "20 minutes ago"
-msgstr "vor 20 Minuten"
-
-#: ../src/common/basics.cpp:243
-msgid "15 minutes ago"
-msgstr "vor 15 Minuten"
-
-#: ../src/common/basics.cpp:244
-msgid "10 minutes ago"
-msgstr "vor 10 Minuten"
-
-#: ../src/common/basics.cpp:245
-msgid "5 minutes ago"
-msgstr "vor 5 Minuten"
-
-#: ../src/common/basics.cpp:246
-msgid "a minute ago"
-msgstr "vor einer Minute"
-
-#: ../src/common/basics.cpp:247
-msgid "30 seconds ago"
-msgstr "vor 30 Sekunden"
-
-#: ../src/common/basics.cpp:248
-msgid "10 seconds ago"
-msgstr "vor 10 Sekunden"
-
-#: ../src/common/basics.cpp:249
-msgid "a second ago"
-msgstr "vor einer Sekunde"
-
-#: ../src/common/basics.cpp:254
-msgid "a few decades ago"
-msgstr "vor einigen Dekaden"
-
-#: ../src/common/basics.cpp:255
-msgid "a few years ago"
-msgstr "vor einigen Jahren"
-
-#: ../src/common/basics.cpp:256
-msgid "a few months ago"
-msgstr "vor einigen Monaten"
-
-#: ../src/common/basics.cpp:257
-msgid "a few weeks ago"
-msgstr "vor einigen Wochen"
-
-#: ../src/common/basics.cpp:258
-msgid "a few days ago"
-msgstr "vor einigen Tagen"
-
-#: ../src/common/basics.cpp:259
-msgid "a few hours ago"
-msgstr "vor einigen Stunden"
-
-#: ../src/common/basics.cpp:266
-msgid "a few minutes ago"
-msgstr "vor einigen Minuten"
-
-#: ../src/common/basics.cpp:269
-msgid "a few seconds ago"
-msgstr "vor einigen Sekunden"
-
-#: ../src/common/basics.cpp:296
-msgid "moments ago"
-msgstr "kürzlich"
-
-#: ../src/common/colourmap.cpp:242
-msgid "Jet"
-msgstr "Jet"
-
-#: ../src/common/colourmap.cpp:243
-msgid "Hot"
-msgstr "Heiss"
-
-#: ../src/common/colourmap.cpp:244
-msgid "Cold"
-msgstr "Kalt"
-
-#: ../src/common/colourmap.cpp:245
-msgid "Grey"
-msgstr "Grau"
-
-#: ../src/common/colourmap.cpp:246
-msgid "Cyclic"
-msgstr "Cyclic"
-
-#: ../src/common/colourmap.cpp:247
-msgid "General"
-msgstr "Allgemein"
-
-#: ../src/common/colourmap.cpp:248
-msgid "Blue"
-msgstr "Blau"
-
-#: ../src/common/colourmap.cpp:249
-msgid "Pseudo-Random"
-msgstr "Pseudo-Random"
-
-#: ../src/common/constants.cpp:22
-msgid ""
-"Range Files (*.rng; *.env; *.rrng)|*.rng;*.env;*.rrng;*.RRNG;*.RNG;*.ENV|RNG "
-"File (*.rng)|*.rng;*.RNG|Environment File (*.env)|*.env;*.ENV|RRNG Files (*."
-"rrng)|*.rrng;*.RRNG|All Files (*)|*"
-msgstr ""
-
-#: ../src/gui/glPane.cpp:628
+#: ../src/gui/glPane.cpp:642
 msgid "Use shift/ctrl-space or double tap to alter reset axis"
 msgstr ""
-"Verwenden Sie Shift / ⌘-Leertaste oder doppeltippen, um Achsen "
+"Verwenden Sie Shift / Strng-Leertaste oder doppeltippen, um Achsen "
 "zurückzusetzen oder zu verändern"
 
-#: ../src/gui/glPane.cpp:901
+#: ../src/gui/glPane.cpp:938
 msgid "Image progress"
 msgstr "Bild Fortschritt"
 
-#: ../src/gui/glPane.cpp:902
+#: ../src/gui/glPane.cpp:939
 msgid "Rendering tiles..."
 msgstr "Rendering tiles..."
 
-#: ../src/gui/glPane.cpp:1091
+#: ../src/gui/glPane.cpp:1132
 msgid "Animation progress"
 msgstr "Animation-Fortschritt"
 
-#: ../src/gui/glPane.cpp:1092
+#: ../src/gui/glPane.cpp:1133
 msgid "Rendering sequence..."
 msgstr "Renderreihenfolge..."
 
-#: ../src/gui/glPane.cpp:1130
+#: ../src/gui/glPane.cpp:1171
 msgid "Saving Image "
 msgstr "Speichere Bild "
 
-#: ../src/gui/glPane.cpp:1130 ../src/gui/mainFrame.cpp:4329
-#: ../src/gui/mainFrame.cpp:4333 ../src/gui/mainFrame.cpp:4346
+#: ../src/gui/glPane.cpp:1171 ../src/gui/mainFrame.cpp:4401
+#: ../src/gui/mainFrame.cpp:4405 ../src/gui/mainFrame.cpp:4418
 #: ../src/backend/filters/dataLoad.cpp:321
 msgid " of "
 msgstr " von "
@@ -278,14 +66,14 @@ msgid "Source Filter"
 msgstr "Source Filter"
 
 #: ../src/gui/dialogs/ExportRngDialog.cpp:54
-#: ../src/backend/filters/rangeFile.cpp:654
+#: ../src/backend/filters/rangeFile.cpp:656
 msgid "Ions"
 msgstr "Ionen"
 
 #: ../src/gui/dialogs/ExportRngDialog.cpp:55
 #: ../src/gui/dialogs/rangeEditDialog.cpp:1587
 #: ../src/backend/filters/voxelise.cpp:834
-#: ../src/backend/filters/rangeFile.cpp:721
+#: ../src/backend/filters/rangeFile.cpp:723
 msgid "Ranges"
 msgstr "Ranges"
 
@@ -294,9 +82,9 @@ msgid "Param"
 msgstr "Param."
 
 #: ../src/gui/dialogs/ExportRngDialog.cpp:89
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1200
 #: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:105
 #: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:352
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1177
 #: ../src/backend/filters/dataLoad.cpp:581
 msgid "Value"
 msgstr "Wert"
@@ -314,7 +102,7 @@ msgid "Num Ranges"
 msgstr "Num Ranges"
 
 #: ../src/gui/dialogs/ExportRngDialog.cpp:116
-#: ../src/gui/dialogs/rangeEditDialog.cpp:696 ../src/backend/filter.cpp:50
+#: ../src/gui/dialogs/rangeEditDialog.cpp:696 ../src/backend/filter.cpp:53
 msgid "Ion"
 msgstr "Ion"
 
@@ -326,138 +114,273 @@ msgstr "Range Anfang"
 msgid "Range end"
 msgstr "Range Ende"
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:151 ../src/gui/mainFrame.cpp:2348
+#: ../src/gui/dialogs/ExportRngDialog.cpp:151 ../src/gui/mainFrame.cpp:2376
 msgid "Save pos..."
 msgstr "pos speichern..."
 
 #: ../src/gui/dialogs/ExportRngDialog.cpp:152
-msgid "ORNL format RNG (*.rng)|*.rng|All Files (*)|*"
-msgstr "ORNL Format RNG (*.rng)|*.rng|Alle Dateien (*)|*"
+msgid ""
+"Cameca/Ametek RRNG (*.rrng)|*.rrng|ORNL format RNG (*.rng)|*.rng|Cameca ENV "
+"(*.env)|*.env|All Files (*)|*"
+msgstr ""
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:167 ../src/gui/mainFrame.cpp:1448
-#: ../src/gui/mainFrame.cpp:1623 ../src/gui/mainFrame.cpp:1698
-#: ../src/gui/mainFrame.cpp:2246 ../src/gui/mainFrame.cpp:2405
-#: ../src/gui/mainFrame.cpp:2518
+#: ../src/gui/dialogs/ExportRngDialog.cpp:184 ../src/gui/mainFrame.cpp:1463
+#: ../src/gui/mainFrame.cpp:1638 ../src/gui/mainFrame.cpp:1713
+#: ../src/gui/mainFrame.cpp:2266 ../src/gui/mainFrame.cpp:2443
+#: ../src/gui/mainFrame.cpp:2556
 msgid "Unable to save. Check output destination can be written to."
 msgstr ""
 "Speichern nicht möglich. Bitte überprüfen Sie ob der Ausgabepfad "
 "schreibgeschützt ist."
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:236
+#: ../src/gui/dialogs/ExportRngDialog.cpp:187 ../src/gui/mainFrame.cpp:1463
+#: ../src/gui/mainFrame.cpp:1588 ../src/gui/mainFrame.cpp:1637
+#: ../src/gui/mainFrame.cpp:1713 ../src/gui/mainFrame.cpp:2265
+#: ../src/gui/mainFrame.cpp:2338 ../src/gui/mainFrame.cpp:2442
+#: ../src/gui/mainFrame.cpp:2555 ../src/wx/wxcomponents.cpp:204
+msgid "Save error"
+msgstr "Fehler speichern"
+
+#: ../src/gui/dialogs/ExportRngDialog.cpp:253
 msgid "Export Range"
 msgstr "Range exportieren"
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:241
+#: ../src/gui/dialogs/ExportRngDialog.cpp:258
 msgid "List of rangefiles in filter tree"
 msgstr "Liste der Rangedateien im Filterbaum"
 
-#: ../src/gui/dialogs/ExportRngDialog.cpp:243
+#: ../src/gui/dialogs/ExportRngDialog.cpp:260
 msgid "Detailed view of selected range"
 msgstr "Detailierte Ansicht des ausgewählten Range"
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:221
-msgid "Show Overlays"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:92
+msgid "Cameca/Ametek RRNG"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:246
-msgid "e.g. H2O"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:93
+msgid "Oak-Ridge RNG"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:561
-#: ../src/gui/dialogs/rangeEditDialog.cpp:695 ../src/gui/mainFrame.cpp:5801
-#: ../src/backend/filter.cpp:51
-msgid "Plot"
-msgstr "Plot"
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:562
-msgid "Short Name"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:94
+msgid "Cameca/Ametek ENV"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:563
-msgid "Long Name"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:156
+msgid "Key frames"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:564
-#: ../src/backend/filters/voxelise.cpp:975
-#: ../src/backend/filters/compositionProfile.cpp:1134
-#: ../src/backend/filters/annotation.cpp:901
-#: ../src/backend/filters/spectrumPlot.cpp:668
-msgid "Colour"
-msgstr "Farbe"
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:697
-#: ../src/backend/filters/annotation.cpp:605
-#: ../src/backend/filters/annotation.cpp:646
-#: ../src/backend/filters/annotation.cpp:815
-msgid "Start"
-msgstr "Anfang"
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:698
-#: ../src/backend/filters/annotation.cpp:613
-#: ../src/backend/filters/annotation.cpp:655
-#: ../src/backend/filters/annotation.cpp:823
-msgid "End"
-msgstr "Ende"
-
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1260
-msgid "Range or ion?"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:157
+msgid "Output Data"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1261
-msgid "Select type to add"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:158
+msgid "Filters and properties"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1542
-msgid "Range Editor"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:164
+msgid "Dir : "
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1546
-msgid "Enable or disable all overlays"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:167
+msgid "Output only when refresh required"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1547
-msgid "Entered overlays, use delete to remove"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:169
+msgid "Data Types:"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1548
-msgid "Available plots for ranging"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:170
+msgid "3D Images"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1549
-msgid "Enter species to display as overlay, e.g. SiO2"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:171
+msgid "File Prefix: "
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1550
-msgid "Editable ranges"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:173
+msgid "Size : "
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1551
-msgid "Editable ions"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:175
+msgid "..."
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:176
+msgid "Point data"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1586
 #: ../src/gui/dialogs/animateFilterDialog.cpp:177
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1586
 msgid "Plots"
 msgstr ""
 
-#: ../src/gui/dialogs/rangeEditDialog.cpp:1588
-msgid "Overlay"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:178
+msgid "Voxel data"
 msgstr ""
 
-#: ../src/gui/dialogs/autosaveDialog.cpp:39
-msgid "Remove &All"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:179
+msgid "Range files"
 msgstr ""
 
-#: ../src/gui/dialogs/autosaveDialog.cpp:123
-msgid "Restore state?"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:180
+msgid "Format"
 msgstr ""
 
-#: ../src/gui/dialogs/autosaveDialog.cpp:133
-msgid "Multiple autosave states were found; would you like to restore one?"
+#: ../src/gui/dialogs/animateFilterDialog.cpp:197
+#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:104
+#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:350
+msgid "Frame"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:702
+msgid "transition frame"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:702
+#: ../src/gui/mainFrame.cpp:1690
+msgid "Frame count"
+msgstr "Bildanzahl"
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:774
+msgid "Key frame : Colour"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:827
+msgid "File existed, but was unable to read or interpret file contents."
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:828
+msgid "String load failed"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:849
+msgid "Keyframe : decimal"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:858
+msgid "Keyframe : integer"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:867
+msgid "Keyframe : 3D Point"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:995
+msgid "Select or create new folder"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1175
+msgid "Export Animation"
+msgstr "Animation exportieren"
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1176
+msgid "Select filter"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1177
+msgid "Select property"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1179
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1198
+msgid "Filter"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1180
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1199
+msgid "Property"
+msgstr "Eigenschaft"
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1181
+#: ../src/backend/filters/annotation.cpp:545
+#: ../src/backend/filters/annotation.cpp:551
+#: ../src/backend/filters/transform.cpp:1150
+#: ../src/backend/filters/ionDownsample.cpp:465
+#: ../src/backend/filters/spatialAnalysis.cpp:1173
+msgid "Mode"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1182
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:68
+msgid "Start Frame"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1183
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:70
+msgid "End Frame"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1184
+msgid "Keyframe table"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1185
+msgid "Remove the selected keyframe from the table"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1186
+msgid "Enter where the animation frames will be exported to"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1187
+msgid "Browse to directory where the animation frames will be exported to"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1189
+msgid ""
+"Title for files, result will be saved as #-name.png, where # is image number."
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1190
+msgid "Target resolution (image size)"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1191
+msgid "Select frame for property display"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1192
+msgid "Enter frame number to change frame (eg 1/20)"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1193
+msgid "Save point data (POS files) in output folder?"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1194
+msgid "Save plots (as text files) in output folder?"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1195
+msgid "Save voxel data (raw files) in output folder?"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1196
+msgid "Save range files  in output folder?"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1201
+msgid "Animation parameters for current frame"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1202
+msgid "Abort animation"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1203
+msgid "Run Animation"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1274
+msgid "Filter view"
+msgstr ""
+
+#: ../src/gui/dialogs/animateFilterDialog.cpp:1275
+msgid "Frame view"
 msgstr ""
 
-#: ../src/gui/dialogs/filterErrorDialog.cpp:37 ../src/backend/filter.cpp:456
-#: ../src/backend/filter.cpp:459
+#: ../src/gui/dialogs/filterErrorDialog.cpp:37 ../src/backend/filter.cpp:476
+#: ../src/backend/filter.cpp:479
 msgid "Error"
 msgstr ""
 
@@ -510,6 +433,35 @@ msgstr "Einstellungen für den ausgewählten Stash"
 msgid "Available stashes"
 msgstr "Verfügbare Stash"
 
+#: ../src/gui/dialogs/resolutionDialog.cpp:45
+msgid "Width :"
+msgstr ""
+
+#: ../src/gui/dialogs/resolutionDialog.cpp:47
+msgid "Height :"
+msgstr ""
+
+#: ../src/gui/dialogs/resolutionDialog.cpp:50
+#: ../src/gui/dialogs/prefDialog.cpp:85
+msgid "Reset"
+msgstr "Zurücksetzen"
+
+#: ../src/gui/dialogs/resolutionDialog.cpp:336
+msgid "Resolution Selection"
+msgstr ""
+
+#: ../src/gui/dialogs/autosaveDialog.cpp:39
+msgid "Remove &All"
+msgstr ""
+
+#: ../src/gui/dialogs/autosaveDialog.cpp:123
+msgid "Restore state?"
+msgstr ""
+
+#: ../src/gui/dialogs/autosaveDialog.cpp:133
+msgid "Multiple autosave states were found; would you like to restore one?"
+msgstr ""
+
 #: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:45
 msgid "Start Frame: "
 msgstr ""
@@ -522,12 +474,6 @@ msgstr ""
 msgid "From Table"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:104
-#: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:350
-#: ../src/gui/dialogs/animateFilterDialog.cpp:196
-msgid "Frame"
-msgstr ""
-
 #: ../src/gui/dialogs/animateSubDialogs/stringKeyFrameDialog.cpp:240
 msgid "Select text file..."
 msgstr ""
@@ -576,375 +522,85 @@ msgstr ""
 msgid "Accept data values"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:56
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:60
 msgid "Keyframe Data"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:57
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:61
 msgid "Transition"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:60
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:64
 msgid "Step"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:61
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:65
 msgid "Ramp"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:64
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1158
-msgid "Start Frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:66
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1159
-msgid "End Frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:69
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:73
 msgid "Initial Value"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:70
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:74
 msgid "startColour"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:71
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:75
 msgid "Final Value"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:72
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:76
 msgid "endColour"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:235
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:250
 msgid "Key Frame : Colour"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:237
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:252
 msgid "Colour at the start of the transtition"
 msgstr ""
 
-#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:238
+#: ../src/gui/dialogs/animateSubDialogs/colourKeyFrameDialog.cpp:253
 msgid "Colour at end of transition"
 msgstr ""
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:92
-msgid "Oak-Ridge RNG"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:73
+msgid "Panel Display"
+msgstr "Panel Display"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:93
-msgid "Cameca/Ametek RRNG"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:75
+msgid "Online Updates"
+msgstr "Online Updates"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:94
-msgid "Cameca/Ametek ENV"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:77 ../src/gui/dialogs/prefDialog.cpp:560
+msgid "Startup"
+msgstr "Startup"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:156
-msgid "Key frames"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:78
+msgid "Camera Speed"
+msgstr "Kamerageschwindigkeit"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:157
-msgid "Output Data"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:79
+msgid "Available Filters"
+msgstr "Verfügbare Filter"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:158
-msgid "Filters and properties"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:84
+msgid "Reset All"
+msgstr "Alle zurücksetzen"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:164
-msgid "Dir : "
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:87
+msgid "Show all panels"
+msgstr "Zeige alle Fenster"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:167
-msgid "Output only when refresh required"
-msgstr ""
+#: ../src/gui/dialogs/prefDialog.cpp:88
+msgid "Remember last"
+msgstr "Zuletzt verwendet"
 
-#: ../src/gui/dialogs/animateFilterDialog.cpp:169
-msgid "Data Types:"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:170
-msgid "3D Images"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:171
-msgid "File Suffix: "
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:173
-msgid "Size : "
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:175
-msgid "..."
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:176
-msgid "Point data"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:178
-msgid "Voxel data"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:179
-msgid "Range files"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:180
-msgid "Format"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:681
-msgid "transition frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:681
-#: ../src/gui/mainFrame.cpp:1675
-msgid "Frame count"
-msgstr "Bildanzahl"
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:753
-msgid "Key frame : Colour"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:806
-msgid "File existed, but was unable to read or interpret file contents."
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:807
-msgid "String load failed"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:828
-msgid "Keyframe : decimal"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:837
-msgid "Keyframe : integer"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:846
-msgid "Keyframe : 3D Point"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:971
-msgid "Select or create new folder"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1151
-msgid "Export Animation"
-msgstr "Animation exportieren"
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1152
-msgid "Select filter"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1153
-msgid "Select property"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1155
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1175
-msgid "Filter"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1156
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1176
-msgid "Property"
-msgstr "Eigenschaft"
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1157
-#: ../src/backend/filters/voxelise.cpp:861
-#: ../src/backend/filters/spatialAnalysis.cpp:978
-#: ../src/backend/filters/transform.cpp:1119
-#: ../src/backend/filters/annotation.cpp:545
-#: ../src/backend/filters/annotation.cpp:551
-#: ../src/backend/filters/ionDownsample.cpp:465
-msgid "Mode"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1160
-msgid "Keyframe table"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1161
-msgid "Remove the selected keyframe from the table"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1162
-msgid "Enter where the animation frames will be exported to"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1163
-msgid "Browse to directory where the animation frames will be exported to"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1165
-msgid ""
-"Title for files, result will be saved as #-name.png, where # is image number."
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1166
-msgid "Target resolution (image size)"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1168
-msgid "Select frame for property display"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1169
-msgid "Enter frame number to change frame (eg 1/20)"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1170
-msgid "Save point data (POS files) in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1171
-msgid "Save plots (as text files) in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1172
-msgid "Save voxel data (raw files) in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1173
-msgid "Save range files  in output folder?"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1178
-msgid "Animation parameters for current frame"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1179
-msgid "Abort animation"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1180
-msgid "Run Animation"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1251
-msgid "Filter view"
-msgstr ""
-
-#: ../src/gui/dialogs/animateFilterDialog.cpp:1252
-msgid "Frame view"
-msgstr ""
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:45
-msgid "Width :"
-msgstr ""
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:47
-msgid "Height :"
-msgstr ""
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:50
-#: ../src/gui/dialogs/prefDialog.cpp:85
-msgid "Reset"
-msgstr "Zurücksetzen"
-
-#: ../src/gui/dialogs/resolutionDialog.cpp:336
-msgid "Resolution Selection"
-msgstr ""
-
-#: ../src/gui/dialogs/ExportPos.cpp:62
-msgid "Export:"
-msgstr "Exportieren:"
-
-#: ../src/gui/dialogs/ExportPos.cpp:63
-#: ../src/backend/filters/boundingBox.cpp:527
-msgid "Visible"
-msgstr "Sichtbar"
-
-#: ../src/gui/dialogs/ExportPos.cpp:64
-msgid "Selected Data"
-msgstr "Daten auswählen"
-
-#: ../src/gui/dialogs/ExportPos.cpp:66
-msgid "Available Data"
-msgstr "Verfügbare Daten"
-
-#: ../src/gui/dialogs/ExportPos.cpp:72
-msgid "Selection"
-msgstr "Auswahl"
-
-#: ../src/gui/dialogs/ExportPos.cpp:97 ../src/gui/dialogs/ExportPos.cpp:100
-msgid "Index"
-msgstr "Index"
-
-#: ../src/gui/dialogs/ExportPos.cpp:98 ../src/gui/dialogs/ExportPos.cpp:101
-#: ../src/backend/filters/compositionProfile.cpp:604
-#: ../src/backend/filters/spatialAnalysis.cpp:2282
-#: ../src/backend/filters/spatialAnalysis.cpp:2375
-#: ../src/backend/filters/spatialAnalysis.cpp:2435
-#: ../src/backend/filters/spatialAnalysis.cpp:3388
-#: ../src/backend/filters/spatialAnalysis.cpp:3591
-#: ../src/backend/filters/spatialAnalysis.cpp:3650
-#: ../src/backend/filters/spectrumPlot.cpp:65
-msgid "Count"
-msgstr "Anzahl"
-
-#: ../src/gui/dialogs/ExportPos.cpp:446
-msgid "Export Pos Data"
-msgstr "POS Daten exportieren"
-
-#: ../src/gui/dialogs/ExportPos.cpp:449
-msgid "Tree of filters, select leaves to show ion data."
-msgstr ""
-
-#: ../src/gui/dialogs/ExportPos.cpp:451
-msgid "Add all data from all filters"
-msgstr ""
-
-#: ../src/gui/dialogs/ExportPos.cpp:452
-msgid "Add all data from currently selected filter"
-msgstr ""
-
-#: ../src/gui/dialogs/ExportPos.cpp:453
-msgid "Add selected data from currently selected filter"
-msgstr ""
-
-#: ../src/gui/dialogs/prefDialog.cpp:73
-msgid "Panel Display"
-msgstr "Panel Display"
-
-#: ../src/gui/dialogs/prefDialog.cpp:75
-msgid "Online Updates"
-msgstr "Online Updates"
-
-#: ../src/gui/dialogs/prefDialog.cpp:77 ../src/gui/dialogs/prefDialog.cpp:560
-msgid "Startup"
-msgstr "Startup"
-
-#: ../src/gui/dialogs/prefDialog.cpp:78
-msgid "Camera Speed"
-msgstr "Kamerageschwindigkeit"
-
-#: ../src/gui/dialogs/prefDialog.cpp:79
-msgid "Available Filters"
-msgstr "Verfügbare Filter"
-
-#: ../src/gui/dialogs/prefDialog.cpp:84
-msgid "Reset All"
-msgstr "Alle zurücksetzen"
-
-#: ../src/gui/dialogs/prefDialog.cpp:87
-msgid "Show all panels"
-msgstr "Zeige alle Fenster"
-
-#: ../src/gui/dialogs/prefDialog.cpp:88
-msgid "Remember last"
-msgstr "Zuletzt verwendet"
-
-#: ../src/gui/dialogs/prefDialog.cpp:89
-msgid "Show Selected"
-msgstr "Zeige Auswahl"
+#: ../src/gui/dialogs/prefDialog.cpp:89
+msgid "Show Selected"
+msgstr "Zeige Auswahl"
 
 #: ../src/gui/dialogs/prefDialog.cpp:92
 msgid "Control Pane"
@@ -954,7 +610,7 @@ msgstr "Kontrollfenster"
 msgid "Raw Data Panel"
 msgstr "Rohdatenfenster"
 
-#: ../src/gui/dialogs/prefDialog.cpp:94 ../src/gui/mainFrame.cpp:676
+#: ../src/gui/dialogs/prefDialog.cpp:94 ../src/gui/mainFrame.cpp:691
 msgid "Plot List"
 msgstr "Plotliste"
 
@@ -1040,34 +696,175 @@ msgstr ""
 msgid "Camera"
 msgstr "Kamera"
 
-#: ../src/gui/mainFrame.cpp:119
-msgid "New camera name..."
-msgstr "Neuer Kameraname..."
+#: ../src/gui/dialogs/ExportPos.cpp:63
+msgid "Export:"
+msgstr "Exportieren:"
 
-#: ../src/gui/mainFrame.cpp:120
-msgid "New stash name..."
-msgstr ""
+#: ../src/gui/dialogs/ExportPos.cpp:64
+#: ../src/backend/filters/boundingBox.cpp:567
+msgid "Visible"
+msgstr "Sichtbar"
 
-#: ../src/gui/mainFrame.cpp:125
-msgid "New Filter..."
-msgstr ""
+#: ../src/gui/dialogs/ExportPos.cpp:65
+msgid "Selected Data"
+msgstr "Daten auswählen"
 
-#: ../src/gui/mainFrame.cpp:142 ../src/backend/filters/annotation.cpp:560
-#: ../src/backend/filters/annotation.cpp:664
-#: ../src/backend/filters/annotation.h:96
-msgid "Annotation"
-msgstr "Kommentar"
+#: ../src/gui/dialogs/ExportPos.cpp:67
+msgid "Available Data"
+msgstr "Verfügbare Daten"
 
-#: ../src/gui/mainFrame.cpp:143
-msgid "Bounding Box"
-msgstr "Begrenzungs-Box"
+#: ../src/gui/dialogs/ExportPos.cpp:73
+msgid "Selection"
+msgstr "Auswahl"
+
+#: ../src/gui/dialogs/ExportPos.cpp:98 ../src/gui/dialogs/ExportPos.cpp:101
+msgid "Index"
+msgstr "Index"
+
+#: ../src/gui/dialogs/ExportPos.cpp:99 ../src/gui/dialogs/ExportPos.cpp:102
+#: ../src/backend/filters/profile.cpp:604
+#: ../src/backend/filters/spatialAnalysis.cpp:2520
+#: ../src/backend/filters/spatialAnalysis.cpp:2613
+#: ../src/backend/filters/spatialAnalysis.cpp:2673
+#: ../src/backend/filters/spatialAnalysis.cpp:3628
+#: ../src/backend/filters/spatialAnalysis.cpp:3831
+#: ../src/backend/filters/spatialAnalysis.cpp:3890
+#: ../src/backend/filters/spectrumPlot.cpp:65
+msgid "Count"
+msgstr "Anzahl"
+
+#: ../src/gui/dialogs/ExportPos.cpp:451
+msgid "Export Pos Data"
+msgstr "POS Daten exportieren"
+
+#: ../src/gui/dialogs/ExportPos.cpp:454
+msgid "Tree of filters, select leaves to show ion data."
+msgstr ""
+
+#: ../src/gui/dialogs/ExportPos.cpp:456
+msgid "Add all data from all filters"
+msgstr ""
+
+#: ../src/gui/dialogs/ExportPos.cpp:457
+msgid "Add all data from currently selected filter"
+msgstr ""
+
+#: ../src/gui/dialogs/ExportPos.cpp:458
+msgid "Add selected data from currently selected filter"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:221
+msgid "Show Overlays"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:246
+msgid "e.g. H2O"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:561
+#: ../src/gui/dialogs/rangeEditDialog.cpp:695 ../src/gui/mainFrame.cpp:5966
+#: ../src/backend/filter.cpp:54
+msgid "Plot"
+msgstr "Plot"
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:562
+msgid "Short Name"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:563
+msgid "Long Name"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:564
+#: ../src/backend/filters/annotation.cpp:901
+#: ../src/backend/filters/voxelise.cpp:976
+#: ../src/backend/filters/profile.cpp:1155
+#: ../src/backend/filters/spectrumPlot.cpp:676
+msgid "Colour"
+msgstr "Farbe"
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:697
+#: ../src/backend/filters/annotation.cpp:605
+#: ../src/backend/filters/annotation.cpp:646
+#: ../src/backend/filters/annotation.cpp:815
+msgid "Start"
+msgstr "Anfang"
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:698
+#: ../src/backend/filters/annotation.cpp:613
+#: ../src/backend/filters/annotation.cpp:655
+#: ../src/backend/filters/annotation.cpp:823
+msgid "End"
+msgstr "Ende"
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1260
+msgid "Range or ion?"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1261
+msgid "Select type to add"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1542
+msgid "Range Editor"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1546
+msgid "Enable or disable all overlays"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1547
+msgid "Entered overlays, use delete to remove"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1548
+msgid "Available plots for ranging"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1549
+msgid "Enter species to display as overlay, e.g. SiO2"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1550
+msgid "Editable ranges"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1551
+msgid "Editable ions"
+msgstr ""
+
+#: ../src/gui/dialogs/rangeEditDialog.cpp:1588
+msgid "Overlay"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:119
+msgid "New camera name..."
+msgstr "Neuer Kameraname..."
+
+#: ../src/gui/mainFrame.cpp:120
+msgid "New stash name..."
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:125
+msgid "New Filter..."
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:142 ../src/backend/filters/annotation.cpp:560
+#: ../src/backend/filters/annotation.cpp:664
+#: ../src/backend/filters/annotation.h:96
+msgid "Annotation"
+msgstr "Kommentar"
+
+#: ../src/gui/mainFrame.cpp:143
+msgid "Bounding Box"
+msgstr "Begrenzungs-Box"
 
-#: ../src/gui/mainFrame.cpp:144 ../src/backend/filters/ionClip.cpp:628
+#: ../src/gui/mainFrame.cpp:144 ../src/backend/filters/ionClip.cpp:629
 #: ../src/backend/filters/ionClip.h:66
 msgid "Clipping"
 msgstr "Zuschneiden"
 
-#: ../src/gui/mainFrame.cpp:145 ../src/backend/filters/clusterAnalysis.h:150
+#: ../src/gui/mainFrame.cpp:145 ../src/backend/filters/clusterAnalysis.h:151
 msgid "Cluster Analysis"
 msgstr "Clusteranalyse"
 
@@ -1111,11 +908,11 @@ msgstr "Räumliche Analyse"
 msgid "Voxelisation"
 msgstr "Voxelisation"
 
-#: ../src/gui/mainFrame.cpp:442
+#: ../src/gui/mainFrame.cpp:451
 msgid "OpenGL Failed"
 msgstr "OpenGL fehlgeschlagen"
 
-#: ../src/gui/mainFrame.cpp:443 ../src/gui/mainFrame.cpp:445
+#: ../src/gui/mainFrame.cpp:452 ../src/gui/mainFrame.cpp:454
 msgid ""
 "Unable to initialise the openGL (3D) panel. Program cannot start. Please "
 "check your video drivers."
@@ -1123,431 +920,435 @@ msgstr ""
 "Kann das OpenGL (3D)-Panel nicht initialisieren. Das Programm kann nicht "
 "gestartet werden. Bitte überprüfen Sie Ihren Video-Treiber."
 
-#: ../src/gui/mainFrame.cpp:466
+#: ../src/gui/mainFrame.cpp:475
 msgid "&Open...\tCtrl+O"
 msgstr "&Öffnen...\tCtrl+O"
 
-#: ../src/gui/mainFrame.cpp:466
+#: ../src/gui/mainFrame.cpp:475
 msgid "Open state file"
 msgstr "Statusdatei öffnen"
 
-#: ../src/gui/mainFrame.cpp:467
+#: ../src/gui/mainFrame.cpp:476
 msgid "&Merge...\tCtrl+Shift+O"
 msgstr "&Zusammenführen...\tCtrl+Shift+O"
 
-#: ../src/gui/mainFrame.cpp:467
+#: ../src/gui/mainFrame.cpp:476
 msgid "Merge other file"
 msgstr "Merge other file"
 
-#: ../src/gui/mainFrame.cpp:471
+#: ../src/gui/mainFrame.cpp:480
 msgid "&Recent"
 msgstr "&Letzte"
 
-#: ../src/gui/mainFrame.cpp:472
+#: ../src/gui/mainFrame.cpp:481
 msgid "&Save\tCtrl+S"
 msgstr "&Speichern\tCtrl+S"
 
-#: ../src/gui/mainFrame.cpp:472
+#: ../src/gui/mainFrame.cpp:481
 msgid "Save state to file"
 msgstr "Status in Datei speichern"
 
-#: ../src/gui/mainFrame.cpp:474
+#: ../src/gui/mainFrame.cpp:483
 msgid "Save &As...\tCtrl+Shift+S"
 msgstr "Speichern &als...\tCtrl+Shift+S"
 
-#: ../src/gui/mainFrame.cpp:474
+#: ../src/gui/mainFrame.cpp:483
 msgid "Save current state to new file"
 msgstr "Aktuellen Status als neue Datei speichern"
 
-#: ../src/gui/mainFrame.cpp:477
+#: ../src/gui/mainFrame.cpp:486
 msgid "&Plot...\tCtrl+P"
 msgstr "&Plot...\tCtrl+P"
 
-#: ../src/gui/mainFrame.cpp:477
+#: ../src/gui/mainFrame.cpp:486
 msgid "Export Current Plot"
 msgstr "Aktuellen Plot exportieren"
 
-#: ../src/gui/mainFrame.cpp:478
+#: ../src/gui/mainFrame.cpp:487
 msgid "&Image...\tCtrl+I"
 msgstr "&Bild...\tCtrl+I"
 
-#: ../src/gui/mainFrame.cpp:478
+#: ../src/gui/mainFrame.cpp:487
 msgid "Export Current 3D View"
 msgstr "Aktuelle 3D Ansicht exportieren"
 
-#: ../src/gui/mainFrame.cpp:479
+#: ../src/gui/mainFrame.cpp:488
 msgid "Ion&s...\tCtrl+N"
 msgstr "Ion&en...\tCtrl+N"
 
-#: ../src/gui/mainFrame.cpp:479
+#: ../src/gui/mainFrame.cpp:488
 msgid "Export Ion Data"
 msgstr "Ionendaten exportieren"
 
-#: ../src/gui/mainFrame.cpp:480
+#: ../src/gui/mainFrame.cpp:489
 msgid "Ran&ges...\tCtrl+G"
 msgstr "Ran&ges...\tCtrl+G"
 
-#: ../src/gui/mainFrame.cpp:480
+#: ../src/gui/mainFrame.cpp:489
 msgid "Export Range Data"
 msgstr "Rangedaten exportieren"
 
-#: ../src/gui/mainFrame.cpp:481
+#: ../src/gui/mainFrame.cpp:490
 msgid "&Animate Filters...\tCtrl+T"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:481
+#: ../src/gui/mainFrame.cpp:490
 msgid "Export Animated Filter"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:482
+#: ../src/gui/mainFrame.cpp:491
 msgid "Ani&mate Camera...\tCtrl+M"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:482
+#: ../src/gui/mainFrame.cpp:491
 msgid "Export Animated Camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:483
+#: ../src/gui/mainFrame.cpp:492
 msgid "Pac&kage...\tCtrl+K"
 msgstr "Pa&ket...\tCtrl+K"
 
-#: ../src/gui/mainFrame.cpp:483
+#: ../src/gui/mainFrame.cpp:492
 msgid "Export analysis package"
 msgstr "Analysepaket exportieren"
 
-#: ../src/gui/mainFrame.cpp:485
+#: ../src/gui/mainFrame.cpp:494
 msgid "&Export"
 msgstr "&Exportieren"
 
-#: ../src/gui/mainFrame.cpp:488
+#: ../src/gui/mainFrame.cpp:497
 msgid "&Quit\tCtrl+Q"
 msgstr "&Beenden\tCtrl+Q"
 
-#: ../src/gui/mainFrame.cpp:488 ../src/gui/mainFrame.cpp:490
+#: ../src/gui/mainFrame.cpp:497 ../src/gui/mainFrame.cpp:499
 msgid "Exit Program"
 msgstr "Programm beenden"
 
-#: ../src/gui/mainFrame.cpp:490
+#: ../src/gui/mainFrame.cpp:499
 msgid "E&xit"
 msgstr "E&xit"
 
-#: ../src/gui/mainFrame.cpp:492
+#: ../src/gui/mainFrame.cpp:501
 msgid "&File"
 msgstr "&Datei"
 
-#: ../src/gui/mainFrame.cpp:496
+#: ../src/gui/mainFrame.cpp:505
 msgid "&Background Colour...\tCtrl+B"
 msgstr "&Hintergrundfarbe...\tCtrl+B"
 
-#: ../src/gui/mainFrame.cpp:496
+#: ../src/gui/mainFrame.cpp:505
 msgid "Change background colour"
 msgstr "Hintergrundfarbe ändern"
 
-#: ../src/gui/mainFrame.cpp:500
+#: ../src/gui/mainFrame.cpp:509
 msgid "&Control Pane\tF2"
 msgstr "&Kontrollfenster\tF2"
 
-#: ../src/gui/mainFrame.cpp:500 ../src/gui/mainFrame.cpp:503
+#: ../src/gui/mainFrame.cpp:509 ../src/gui/mainFrame.cpp:512
 msgid "Toggle left control pane"
 msgstr "Linkes Kontrollfenster ein/aus schalten"
 
-#: ../src/gui/mainFrame.cpp:503
+#: ../src/gui/mainFrame.cpp:512
 msgid "&Control Pane\tAlt+C"
 msgstr "&Kontrollfenster\tAlt+C"
 
-#: ../src/gui/mainFrame.cpp:509
+#: ../src/gui/mainFrame.cpp:518
 msgid "&Raw Data Pane\tF3"
 msgstr "&Rohdatenfenster\tF3"
 
-#: ../src/gui/mainFrame.cpp:509 ../src/gui/mainFrame.cpp:512
+#: ../src/gui/mainFrame.cpp:518 ../src/gui/mainFrame.cpp:521
 msgid "Toggle raw data  pane (bottom)"
 msgstr "Rohdatenfenster (unten)"
 
-#: ../src/gui/mainFrame.cpp:512
+#: ../src/gui/mainFrame.cpp:521
 msgid "&Raw Data Pane\tAlt+R"
 msgstr "&Rohdatenfenster\tAlt+R"
 
-#: ../src/gui/mainFrame.cpp:516
+#: ../src/gui/mainFrame.cpp:525
 msgid "&Plot List\tF4"
 msgstr "&Plot Liste\tF4"
 
-#: ../src/gui/mainFrame.cpp:516 ../src/gui/mainFrame.cpp:518
+#: ../src/gui/mainFrame.cpp:525 ../src/gui/mainFrame.cpp:527
 msgid "Toggle plot list"
 msgstr "Plotliste ein/aus schalten"
 
-#: ../src/gui/mainFrame.cpp:518
+#: ../src/gui/mainFrame.cpp:527
 msgid "&Plot List\tAlt+P"
 msgstr "&Plot Liste\tAlt+P"
 
-#: ../src/gui/mainFrame.cpp:524
+#: ../src/gui/mainFrame.cpp:533
 msgid "&Legend\tCtrl+L"
 msgstr "&Legende\tCtrl+L"
 
-#: ../src/gui/mainFrame.cpp:524
+#: ../src/gui/mainFrame.cpp:533
 msgid "Toggle Legend display"
 msgstr "Legende anzeigen ein/aus"
 
-#: ../src/gui/mainFrame.cpp:526
+#: ../src/gui/mainFrame.cpp:535
 msgid "P&lot..."
 msgstr "P&lot..."
 
-#: ../src/gui/mainFrame.cpp:527
+#: ../src/gui/mainFrame.cpp:536
 msgid "&Axis\tCtrl+Shift+I"
 msgstr "&Achsen\tCtrl+Shift+I"
 
-#: ../src/gui/mainFrame.cpp:527
+#: ../src/gui/mainFrame.cpp:536
 msgid "Toggle World Axis display"
 msgstr "Hauptachsen ein/aus schalten"
 
-#: ../src/gui/mainFrame.cpp:532
+#: ../src/gui/mainFrame.cpp:541
 msgid "&Fullscreen mode\tF11"
 msgstr "&Vollbildmodus\tF11"
 
-#: ../src/gui/mainFrame.cpp:532 ../src/gui/mainFrame.cpp:534
+#: ../src/gui/mainFrame.cpp:541 ../src/gui/mainFrame.cpp:543
 msgid "Next fullscreen mode: with toolbars"
 msgstr "Nächster Vollbildmodus: ohne Werkzeugleisten"
 
-#: ../src/gui/mainFrame.cpp:534
+#: ../src/gui/mainFrame.cpp:543
 msgid "&Fullscreen mode\tCtrl+Shift+F"
 msgstr "&Vollbildmodus\tCtrl+Shift+F"
 
-#: ../src/gui/mainFrame.cpp:539
+#: ../src/gui/mainFrame.cpp:548
 msgid "&Undo\tCtrl+Z"
 msgstr "&Zurück\tCtrl+Z"
 
-#: ../src/gui/mainFrame.cpp:541
+#: ../src/gui/mainFrame.cpp:550
 msgid "&Redo\tCtrl+Y"
 msgstr "&Wiederholen\tCtrl+Y"
 
-#: ../src/gui/mainFrame.cpp:544
+#: ../src/gui/mainFrame.cpp:553
 msgid "&Range"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:547
+#: ../src/gui/mainFrame.cpp:556
 msgid "&Preferences"
 msgstr "&Voreinstellungen"
 
-#: ../src/gui/mainFrame.cpp:549
+#: ../src/gui/mainFrame.cpp:558
 msgid "&Edit"
 msgstr "&Bearbeiten"
 
-#: ../src/gui/mainFrame.cpp:552
+#: ../src/gui/mainFrame.cpp:561
 msgid "&View"
 msgstr "&Ansicht"
 
-#: ../src/gui/mainFrame.cpp:554
+#: ../src/gui/mainFrame.cpp:563
 msgid "&Help...\tCtrl+H"
 msgstr "&Hilfe...\tCtrl+H"
 
-#: ../src/gui/mainFrame.cpp:554
+#: ../src/gui/mainFrame.cpp:563
 msgid "Show help files and documentation"
 msgstr "Hilfedateien und Dokumentation anzeigen"
 
-#: ../src/gui/mainFrame.cpp:555
+#: ../src/gui/mainFrame.cpp:564
 msgid "&Contact..."
 msgstr "&Kontakt..."
 
-#: ../src/gui/mainFrame.cpp:555
+#: ../src/gui/mainFrame.cpp:564
 msgid "Open contact page"
 msgstr "Kontaktseite öffnen"
 
-#: ../src/gui/mainFrame.cpp:557
+#: ../src/gui/mainFrame.cpp:566
 msgid "&About..."
 msgstr "Über 3Depict..."
 
-#: ../src/gui/mainFrame.cpp:557
+#: ../src/gui/mainFrame.cpp:566
 msgid "Information about this program"
 msgstr "Informationen zu diesem Programm"
 
-#: ../src/gui/mainFrame.cpp:558
+#: ../src/gui/mainFrame.cpp:567
 msgid "&Help"
 msgstr "&Hilfe"
 
-#: ../src/gui/mainFrame.cpp:560
+#: ../src/gui/mainFrame.cpp:569
 msgid "Stashed Filters"
 msgstr "Zwischengelagerte Filter"
 
-#: ../src/gui/mainFrame.cpp:565
+#: ../src/gui/mainFrame.cpp:574
 msgid "New Filters"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:595
+#: ../src/gui/mainFrame.cpp:604
 msgid "Auto Refresh"
 msgstr ""
 "Autom.\n"
 "aktualisieren"
 
-#: ../src/gui/mainFrame.cpp:601
+#: ../src/gui/mainFrame.cpp:610
 msgid "Filter settings"
 msgstr "Filtereinstellungen"
 
-#: ../src/gui/mainFrame.cpp:604
+#: ../src/gui/mainFrame.cpp:613
 msgid "Camera Name"
 msgstr "Kameraname"
 
-#: ../src/gui/mainFrame.cpp:611
+#: ../src/gui/mainFrame.cpp:625
+msgid "Resize to Fit"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:627
 msgid "3D Post-processing"
 msgstr "3D Nachbearbeitung"
 
-#: ../src/gui/mainFrame.cpp:613
+#: ../src/gui/mainFrame.cpp:629
 msgid "Enable Cropping"
 msgstr "Zuschneiden aktivieren"
 
-#: ../src/gui/mainFrame.cpp:615 ../src/gui/mainFrame.cpp:626
+#: ../src/gui/mainFrame.cpp:631 ../src/gui/mainFrame.cpp:642
 msgid "x-y"
 msgstr "x-y"
 
-#: ../src/gui/mainFrame.cpp:616 ../src/gui/mainFrame.cpp:627
+#: ../src/gui/mainFrame.cpp:632 ../src/gui/mainFrame.cpp:643
 msgid "x-z"
 msgstr "x-z"
 
-#: ../src/gui/mainFrame.cpp:617 ../src/gui/mainFrame.cpp:628
+#: ../src/gui/mainFrame.cpp:633 ../src/gui/mainFrame.cpp:644
 msgid "y-x"
 msgstr "y-x"
 
-#: ../src/gui/mainFrame.cpp:618 ../src/gui/mainFrame.cpp:629
+#: ../src/gui/mainFrame.cpp:634 ../src/gui/mainFrame.cpp:645
 msgid "y-z"
 msgstr "y-z"
 
-#: ../src/gui/mainFrame.cpp:619 ../src/gui/mainFrame.cpp:630
+#: ../src/gui/mainFrame.cpp:635 ../src/gui/mainFrame.cpp:646
 msgid "z-x"
 msgstr "z-x"
 
-#: ../src/gui/mainFrame.cpp:620 ../src/gui/mainFrame.cpp:631
+#: ../src/gui/mainFrame.cpp:636 ../src/gui/mainFrame.cpp:647
 msgid "z-y"
 msgstr "z-y"
 
-#: ../src/gui/mainFrame.cpp:635
+#: ../src/gui/mainFrame.cpp:651
 msgid "Use camera coordinates"
 msgstr "Verwende Kamerakoordinaten"
 
-#: ../src/gui/mainFrame.cpp:636
+#: ../src/gui/mainFrame.cpp:652
 msgid "dX"
 msgstr "dX"
 
-#: ../src/gui/mainFrame.cpp:638
+#: ../src/gui/mainFrame.cpp:654
 msgid "dY"
 msgstr "dY"
 
-#: ../src/gui/mainFrame.cpp:640
+#: ../src/gui/mainFrame.cpp:656
 msgid "dZ"
 msgstr "dZ"
 
-#: ../src/gui/mainFrame.cpp:642
+#: ../src/gui/mainFrame.cpp:658
 msgid "Enable Anaglyphic Stereo"
 msgstr "Anaglyphic Stereo aktivieren"
 
-#: ../src/gui/mainFrame.cpp:643
+#: ../src/gui/mainFrame.cpp:659
 msgid "Flip Channels"
 msgstr "Kanäle tauschen"
 
-#: ../src/gui/mainFrame.cpp:644
+#: ../src/gui/mainFrame.cpp:660
 msgid "Anaglyph Mode"
 msgstr "Anaglyphmodus"
 
-#: ../src/gui/mainFrame.cpp:646
+#: ../src/gui/mainFrame.cpp:662
 msgid "Red-Blue"
 msgstr "Rot-Blau"
 
-#: ../src/gui/mainFrame.cpp:647
+#: ../src/gui/mainFrame.cpp:663
 msgid "Red-Green"
 msgstr "Rot-Grün"
 
-#: ../src/gui/mainFrame.cpp:648
+#: ../src/gui/mainFrame.cpp:664
 msgid "Red-Cyan"
 msgstr "Rot-Zyan"
 
-#: ../src/gui/mainFrame.cpp:649
+#: ../src/gui/mainFrame.cpp:665
 msgid "Green-Magenta"
 msgstr "Grün-Magenta"
 
-#: ../src/gui/mainFrame.cpp:653
+#: ../src/gui/mainFrame.cpp:669
 msgid "Baseline Separation"
 msgstr "Basislinienabstand"
 
-#: ../src/gui/mainFrame.cpp:655 ../src/backend/filters/voxelise.cpp:937
-#: ../src/backend/filters/voxelise.cpp:1105
-#: ../src/backend/filters/compositionProfile.cpp:1143
-#: ../src/backend/filters/boundingBox.cpp:654
-#: ../src/backend/filters/annotation.cpp:906
+#: ../src/gui/mainFrame.cpp:671 ../src/backend/filters/annotation.cpp:906
+#: ../src/backend/filters/voxelise.cpp:938
+#: ../src/backend/filters/voxelise.cpp:1106
+#: ../src/backend/filters/profile.cpp:1164
+#: ../src/backend/filters/boundingBox.cpp:731
 #: ../src/backend/filters/dataLoad.cpp:666
-#: ../src/backend/filters/spectrumPlot.cpp:675
+#: ../src/backend/filters/spectrumPlot.cpp:683
 msgid "Appearance"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:656
+#: ../src/gui/mainFrame.cpp:672
 msgid "Smooth && translucent objects"
 msgstr "Glatte && durchsichtige Objekte"
 
-#: ../src/gui/mainFrame.cpp:658
+#: ../src/gui/mainFrame.cpp:674
 msgid "3D lighting"
 msgstr "3D Beleuchtung"
 
-#: ../src/gui/mainFrame.cpp:661
+#: ../src/gui/mainFrame.cpp:677
 msgid "Performance"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:662
+#: ../src/gui/mainFrame.cpp:678
 msgid "Fast and weak randomisation."
 msgstr "Schnelle aber schwache Randomisierung"
 
-#: ../src/gui/mainFrame.cpp:664
+#: ../src/gui/mainFrame.cpp:680
 msgid "Limit Output Pts"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:670
+#: ../src/gui/mainFrame.cpp:685
 msgid "Filter caching"
 msgstr "Filter zwischenspeichern"
 
-#: ../src/gui/mainFrame.cpp:672
+#: ../src/gui/mainFrame.cpp:687
 msgid "Max. Ram usage (%)"
 msgstr "Max. RAM-Nutzung (%)"
 
-#: ../src/gui/mainFrame.cpp:743
+#: ../src/gui/mainFrame.cpp:759
 msgid "Warning: Your configuration file appears to be invalid:\n"
 msgstr "Warnung: Ihre Konfigurationsdatei scheint ungültig zu sein.\n"
 
-#: ../src/gui/mainFrame.cpp:744
+#: ../src/gui/mainFrame.cpp:760
 msgid "\tConfig Load: "
 msgstr "\tConfig Load: "
 
-#: ../src/gui/mainFrame.cpp:1018
+#: ../src/gui/mainFrame.cpp:1054
 msgid "Current state has not been saved, would you like to save it now?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1019
+#: ../src/gui/mainFrame.cpp:1055
 msgid "State changed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1037
+#: ../src/gui/mainFrame.cpp:1073
 msgid "Readable files (*.xml, *.pos, *.txt,*.csv, *.ato)"
 msgstr "Lesbare Dateien (*.xml, *.pos, *.txt,*.csv,*.ato)"
 
-#: ../src/gui/mainFrame.cpp:1039
+#: ../src/gui/mainFrame.cpp:1075
 msgid "XML State File (*.xml)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1040
+#: ../src/gui/mainFrame.cpp:1076
 msgid "POS File (*.pos)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1041
+#: ../src/gui/mainFrame.cpp:1077
 msgid "LAWATAP ATO File (*.ato)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1042
+#: ../src/gui/mainFrame.cpp:1078
 msgid "Text File (*.txt, *.csv)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1043
+#: ../src/gui/mainFrame.cpp:1079
 msgid "All Files (*)"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1056 ../src/gui/mainFrame.cpp:1112
+#: ../src/gui/mainFrame.cpp:1092 ../src/gui/mainFrame.cpp:1141
 msgid "Select Data or State File..."
 msgstr "Daten oder Statusdatei auswählen..."
 
-#: ../src/gui/mainFrame.cpp:1113
+#: ../src/gui/mainFrame.cpp:1142
 msgid ""
 "3Depict file (*.xml, *.pos,*.txt)|*.xml;*.pos;*.txt|POS File (*.pos)|*.pos|"
 "XML State File (*.xml)|*.xml|All Files (*)|*"
@@ -1555,23 +1356,23 @@ msgstr ""
 "3Depictdateien (*.xml, *.pos,*.txt)|*.xml;*.pos;*.txt|POS Datei (*.pos)|*."
 "pos|XML Status Datei (*.xml)|*.xml|All Files (*)|*"
 
-#: ../src/gui/mainFrame.cpp:1124
+#: ../src/gui/mainFrame.cpp:1153
 msgid "Merged file."
 msgstr "Datei zusammengeführt."
 
-#: ../src/gui/mainFrame.cpp:1231
+#: ../src/gui/mainFrame.cpp:1256
 msgid "Tip: You can use ⌘ (command) to merge"
 msgstr "Tip: Sie können ⌘ (command) zum Zusammenführen verwenden"
 
-#: ../src/gui/mainFrame.cpp:1233
+#: ../src/gui/mainFrame.cpp:1258
 msgid "Tip: You can use ctrl to merge"
 msgstr "Tip: Sie können strg zum Zusammen führen verwenden"
 
-#: ../src/gui/mainFrame.cpp:1276
+#: ../src/gui/mainFrame.cpp:1292
 msgid "Load error"
 msgstr "Fehler beim Laden"
 
-#: ../src/gui/mainFrame.cpp:1277
+#: ../src/gui/mainFrame.cpp:1293
 msgid ""
 "Error loading state file.\n"
 "See console for more info."
@@ -1579,7 +1380,7 @@ msgstr ""
 "Fehler beim Laden der Statusdatei.\n"
 "Konsole für mehr Informationen."
 
-#: ../src/gui/mainFrame.cpp:1285
+#: ../src/gui/mainFrame.cpp:1301
 msgid ""
 "This state file contains filters that can be unsafe to run\n"
 "Do you wish to remove these before continuing?."
@@ -1587,24 +1388,24 @@ msgstr ""
 "Diese Statusdatei enthält Filter deren Anwendung möglicherweise unsicher "
 "ist. Wollen Sie diese entfernen."
 
-#: ../src/gui/mainFrame.cpp:1286
+#: ../src/gui/mainFrame.cpp:1302
 msgid "Security warning"
 msgstr "Sicherheitswarnung"
 
-#: ../src/gui/mainFrame.cpp:1469 ../src/gui/mainFrame.cpp:1565
-#: ../src/gui/mainFrame.cpp:1990
+#: ../src/gui/mainFrame.cpp:1484 ../src/gui/mainFrame.cpp:1580
+#: ../src/gui/mainFrame.cpp:2010
 msgid "Unable to save"
 msgstr "Speichern nicht möglich"
 
-#: ../src/gui/mainFrame.cpp:1470
+#: ../src/gui/mainFrame.cpp:1485
 msgid "No plot available. Please create a plot before exporting."
 msgstr "Kein Plot vefügbar. Plot muss vor dem Exportieren erzeugt werden."
 
-#: ../src/gui/mainFrame.cpp:1474
+#: ../src/gui/mainFrame.cpp:1489
 msgid "Save plot..."
 msgstr "Plot speichern..."
 
-#: ../src/gui/mainFrame.cpp:1475
+#: ../src/gui/mainFrame.cpp:1490
 msgid ""
 "By Extension (svg,png)|*.svg;*.png|Scalable Vector Graphics File (*.svg)|*."
 "svg|PNG File (*.png)|*.png|All Files (*)|*"
@@ -1612,53 +1413,53 @@ msgstr ""
 "Dateierweiterung (svg,png)|*.svg;*.png|Skalierbare Vektorgrafik (*.svg)|*."
 "svg|PNG Datei (*.png)|*.png|Alle Dateien (*)|*"
 
-#: ../src/gui/mainFrame.cpp:1529
+#: ../src/gui/mainFrame.cpp:1544
 msgid "Select type for save"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1530
+#: ../src/gui/mainFrame.cpp:1545
 msgid "Choose file type"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1550 ../src/gui/mainFrame.cpp:1607
-#: ../src/gui/mainFrame.cpp:1643
+#: ../src/gui/mainFrame.cpp:1565 ../src/gui/mainFrame.cpp:1622
+#: ../src/gui/mainFrame.cpp:1658
 msgid "Choose resolution"
 msgstr "Auflösung auswählen"
 
-#: ../src/gui/mainFrame.cpp:1566
+#: ../src/gui/mainFrame.cpp:1581
 msgid "Unknown file extension. Please use \"svg\" or \"png\""
 msgstr "Unbekannte Dateierweiterung. Bitte verwenden Sie \"svg\" oder \"png\""
 
-#: ../src/gui/mainFrame.cpp:1577
+#: ../src/gui/mainFrame.cpp:1592
 msgid "Saved plot: "
 msgstr "Gespeicherter Plot:"
 
-#: ../src/gui/mainFrame.cpp:1584 ../src/gui/mainFrame.cpp:1636
+#: ../src/gui/mainFrame.cpp:1599 ../src/gui/mainFrame.cpp:1651
 msgid "Save Image..."
 msgstr "Speichere Bild..."
 
-#: ../src/gui/mainFrame.cpp:1585 ../src/gui/mainFrame.cpp:1637
+#: ../src/gui/mainFrame.cpp:1600 ../src/gui/mainFrame.cpp:1652
 msgid "PNG File (*.png)|*.png|All Files (*)|*"
 msgstr "PNG Datei (*.png)|*.png|Alle Dateien (*)|*"
 
-#: ../src/gui/mainFrame.cpp:1599
+#: ../src/gui/mainFrame.cpp:1614
 msgid "File already exists. Overwrite?"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1600 ../src/gui/mainFrame.cpp:2378
-#: ../src/gui/mainFrame.cpp:2475 ../src/gui/mainFrame.cpp:2498
+#: ../src/gui/mainFrame.cpp:1615 ../src/gui/mainFrame.cpp:2407
+#: ../src/gui/mainFrame.cpp:2513 ../src/gui/mainFrame.cpp:2536
 msgid "Overwrite?"
 msgstr "Überschreiben?"
 
-#: ../src/gui/mainFrame.cpp:1627 ../src/gui/mainFrame.cpp:1703
+#: ../src/gui/mainFrame.cpp:1642 ../src/gui/mainFrame.cpp:1718
 msgid "Saved 3D View :"
 msgstr "Gespeicherte 3D Ansicht"
 
-#: ../src/gui/mainFrame.cpp:1657
+#: ../src/gui/mainFrame.cpp:1672
 msgid "Program limitation"
 msgstr "Programmeinschränkung"
 
-#: ../src/gui/mainFrame.cpp:1658
+#: ../src/gui/mainFrame.cpp:1673
 msgid ""
 "Limitation on the screenshot dimension; please ensure that both width and "
 "height exceed the initial values,\n"
@@ -1670,96 +1471,104 @@ msgstr ""
 "kleiner als die ursprünglichen Werte sind. Sollte Sie dies stören, melden "
 "Sie bitte einen Bug."
 
-#: ../src/gui/mainFrame.cpp:1675
+#: ../src/gui/mainFrame.cpp:1690
 msgid "Number of frames"
 msgstr "Bilderanzahl"
 
-#: ../src/gui/mainFrame.cpp:1835
+#: ../src/gui/mainFrame.cpp:1744
+msgid "Abo&rt"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:1746
+msgid "&Refresh"
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:1855
 msgid "Cannot animate with no filters."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1913
+#: ../src/gui/mainFrame.cpp:1933
 msgid "Animating"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1914
+#: ../src/gui/mainFrame.cpp:1934
 msgid "Performing refresh"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1940
+#: ../src/gui/mainFrame.cpp:1960
 msgid "Filter property change failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1962
+#: ../src/gui/mainFrame.cpp:1982
 msgid "Refresh failed on frame :"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:1991
+#: ../src/gui/mainFrame.cpp:2011
 msgid "Image save failed for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2016
+#: ../src/gui/mainFrame.cpp:2036
 msgid "Ion save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2017
+#: ../src/gui/mainFrame.cpp:2037
 msgid "Unable to save ions for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2048
+#: ../src/gui/mainFrame.cpp:2068
 msgid "Plot save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2049
+#: ../src/gui/mainFrame.cpp:2069
 msgid "Unable to save plot or frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2090
+#: ../src/gui/mainFrame.cpp:2110
 msgid "Range save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2091
+#: ../src/gui/mainFrame.cpp:2111
 msgid "Unable to save range for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2120
+#: ../src/gui/mainFrame.cpp:2140
 msgid "Voxel save failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2121
+#: ../src/gui/mainFrame.cpp:2141
 msgid "Unable to save voxels for frame "
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2150
+#: ../src/gui/mainFrame.cpp:2170
 msgid "Animate failed"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2174 ../src/gui/mainFrame.cpp:2333
-#: ../src/gui/mainFrame.cpp:2430
+#: ../src/gui/mainFrame.cpp:2194 ../src/gui/mainFrame.cpp:2360
+#: ../src/gui/mainFrame.cpp:2468
 msgid "No filters means no data to export"
 msgstr "Keine Filter bedeutet keine Daten zum Exportieren"
 
-#: ../src/gui/mainFrame.cpp:2188
+#: ../src/gui/mainFrame.cpp:2208
 msgid "Package name"
 msgstr "Paketname"
 
-#: ../src/gui/mainFrame.cpp:2189
+#: ../src/gui/mainFrame.cpp:2209
 msgid "Package directory name"
 msgstr "Paketverzeichnis"
 
-#: ../src/gui/mainFrame.cpp:2191
+#: ../src/gui/mainFrame.cpp:2211
 msgid "AnalysisPackage"
 msgstr "Analysepaket"
 
-#: ../src/gui/mainFrame.cpp:2204
+#: ../src/gui/mainFrame.cpp:2224
 msgid "Package folder already exists, won't overwrite."
 msgstr "Paketverzeichnis existiert bereits. Werde es nicht überschreiben."
 
-#: ../src/gui/mainFrame.cpp:2205
+#: ../src/gui/mainFrame.cpp:2225
 msgid "Not available"
 msgstr "Nicht verfügbar"
 
-#: ../src/gui/mainFrame.cpp:2230
+#: ../src/gui/mainFrame.cpp:2250
 msgid ""
 "Package folder creation failed\n"
 "check writing to this location is possible."
@@ -1767,215 +1576,221 @@ msgstr ""
 "Anlegen des Paketverzeichnisses fehlgeschlagen\n"
 "Überprüfen Sie ob der angegenbene Ort schreibgeschützt ist."
 
-#: ../src/gui/mainFrame.cpp:2231
+#: ../src/gui/mainFrame.cpp:2251
 msgid "Folder creation failed"
 msgstr "Anlegen des Ordners ist fehlgeschlagen"
 
-#: ../src/gui/mainFrame.cpp:2251
+#: ../src/gui/mainFrame.cpp:2271
 msgid "Copying"
 msgstr "kopiere"
 
-#: ../src/gui/mainFrame.cpp:2252
+#: ../src/gui/mainFrame.cpp:2272
 msgid "Copying referenced files"
 msgstr "Copying referenced files"
 
-#: ../src/gui/mainFrame.cpp:2311
+#: ../src/gui/mainFrame.cpp:2338
 msgid "Error copying file"
 msgstr "Fehler beim Kopieren der Datei"
 
-#: ../src/gui/mainFrame.cpp:2320
+#: ../src/gui/mainFrame.cpp:2347
 msgid "Saved package: "
 msgstr "Gespeicherte Pakete: "
 
-#: ../src/gui/mainFrame.cpp:2344
+#: ../src/gui/mainFrame.cpp:2371
 msgid "Export"
 msgstr "Exportieren"
 
-#: ../src/gui/mainFrame.cpp:2349
-msgid "POS Data (*.pos)|*.pos|All Files (*)|*"
-msgstr "POS-Daten (*.pos)|*.pos|All Files (*)|*"
+#: ../src/gui/mainFrame.cpp:2377
+msgid ""
+"POS Data (*.pos)|*.pos|Text File (*.txt)|*.txt|VTK Legacy (*.vtk)|*.vtk|All "
+"Files (*)|*"
+msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2377 ../src/gui/mainFrame.cpp:2474
+#: ../src/gui/mainFrame.cpp:2406 ../src/gui/mainFrame.cpp:2512
 msgid "File already exists, overwrite?"
 msgstr "Datei existiert bereits. Überschreiben?"
 
-#: ../src/gui/mainFrame.cpp:2409
+#: ../src/gui/mainFrame.cpp:2447
 msgid "Saved ions: "
 msgstr "Gespeicherte Ionen:"
 
-#: ../src/gui/mainFrame.cpp:2434
+#: ../src/gui/mainFrame.cpp:2472
 msgid "Export Ranges"
 msgstr "Range exportieren"
 
-#: ../src/gui/mainFrame.cpp:2456
+#: ../src/gui/mainFrame.cpp:2494
 msgid "Save state..."
 msgstr "Speichere Status..."
 
-#: ../src/gui/mainFrame.cpp:2457
+#: ../src/gui/mainFrame.cpp:2495
 msgid "XML state file (*.xml)|*.xml|All Files (*)|*"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2497
+#: ../src/gui/mainFrame.cpp:2535
 msgid "Files have been referred to using relative paths. Keep relative paths?"
 msgstr ""
 "Auf Dateien wurde mit relativen Pfaden verwiesen. Relative Pfade beibehalten?"
 
-#: ../src/gui/mainFrame.cpp:2530
+#: ../src/gui/mainFrame.cpp:2568
 msgid "Saved state: "
 msgstr "Gespeicherter Status: "
 
-#: ../src/gui/mainFrame.cpp:2606
+#: ../src/gui/mainFrame.cpp:2644
 msgid "Range editor"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:2863
+#: ../src/gui/mainFrame.cpp:2901
 msgid "Manual not found locally. Launching web browser"
 msgstr "Anleitung konnte lokal nicht gefunden werden. Starte Webbrowser"
 
-#: ../src/gui/mainFrame.cpp:2872
+#: ../src/gui/mainFrame.cpp:2910
 msgid "Opening contact page in external web browser"
 msgstr "Öffne Kontaktseite in externem Browser"
 
-#: ../src/gui/mainFrame.cpp:2880
+#: ../src/gui/mainFrame.cpp:2918
 msgid "No filter stashes to edit."
 msgstr "Keine Filterstashes zum Bearbeiten."
 
-#: ../src/gui/mainFrame.cpp:2884
+#: ../src/gui/mainFrame.cpp:2922
 msgid "Filter Stashes"
 msgstr "Filter Stashes"
 
-#: ../src/gui/mainFrame.cpp:2901
+#: ../src/gui/mainFrame.cpp:2939
 msgid "Quick and dirty analysis for point data."
 msgstr "\"Quick and dirty\" Analyse von Punktdaten."
 
-#: ../src/gui/mainFrame.cpp:2911
+#: ../src/gui/mainFrame.cpp:2949
 msgid "Compiled with wx Version: "
 msgstr "Kompiliert mit wx Version: "
 
-#: ../src/gui/mainFrame.cpp:2932
+#: ../src/gui/mainFrame.cpp:2970
 msgid "Press enter to store new stash"
 msgstr "Eingabe drücken um neuen Filterstash zu speichern"
 
-#: ../src/gui/mainFrame.cpp:2938
+#: ../src/gui/mainFrame.cpp:2976
 msgid "Press enter to restore stash"
 msgstr "Eingabe drücken um Stash wiederherzustellen"
 
-#: ../src/gui/mainFrame.cpp:2971
+#: ../src/gui/mainFrame.cpp:3009
 msgid "Unable to create stash, selection invalid"
 msgstr "Stash kann nicht erstellt werden, Auswahl ungültig"
 
-#: ../src/gui/mainFrame.cpp:2978
+#: ../src/gui/mainFrame.cpp:3016
 msgid "Created new filter tree stash"
 msgstr "Neuer Filterstash wurde erzeugt"
 
-#: ../src/gui/mainFrame.cpp:3083
+#: ../src/gui/mainFrame.cpp:3123
 msgid "Filter type not a data source - can't be at tree base"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3223
+#: ../src/gui/mainFrame.cpp:3263
 msgid "Moving - Hold ⌘ (command) to copy"
 msgstr "Verschieben - Halte ⌘ (command) um zu kopieren"
 
-#: ../src/gui/mainFrame.cpp:3225
+#: ../src/gui/mainFrame.cpp:3265
 msgid "Moving - Hold control to copy"
 msgstr "Verschieben - Halte Strg zum kopieren"
 
-#: ../src/gui/mainFrame.cpp:3545
+#: ../src/gui/mainFrame.cpp:3604
 msgid "Press enter to store new camera"
 msgstr "Eingabe drücken um neue Kamera zu speichern"
 
-#: ../src/gui/mainFrame.cpp:3547
+#: ../src/gui/mainFrame.cpp:3606
 msgid "Press enter to restore camera"
 msgstr "Eingabe drücken um Kamera wiederherzustellen"
 
-#: ../src/gui/mainFrame.cpp:3572 ../src/gui/mainFrame.cpp:3613
+#: ../src/gui/mainFrame.cpp:3631 ../src/gui/mainFrame.cpp:3672
 msgid "Restored camera: "
 msgstr "Wiederhergestellte Kamera: "
 
-#: ../src/gui/mainFrame.cpp:3590
+#: ../src/gui/mainFrame.cpp:3649
 msgid "Stored camera: "
 msgstr "Gespeicherte Kamera: "
 
-#: ../src/gui/mainFrame.cpp:3676
+#: ../src/gui/mainFrame.cpp:3735
 msgid "Select an item from the filter tree before choosing a new filter"
 msgstr ""
 "Aktivieren Sie zuerst ein Punkt aus dem Filterverlauf bevor Sie einen neuen "
 "Filter auswählen"
 
-#: ../src/gui/mainFrame.cpp:3678
+#: ../src/gui/mainFrame.cpp:3737
 msgid "Load data source (file->open) before choosing a new filter"
 msgstr "Lade Datenquelle (Datei->öffnen) vor dem Auswählen eines neuen Filters"
 
-#: ../src/gui/mainFrame.cpp:3704
+#: ../src/gui/mainFrame.cpp:3763
 msgid "Select RNG File..."
 msgstr "RNG Datei auswählen..."
 
-#: ../src/gui/mainFrame.cpp:3725
+#: ../src/gui/mainFrame.cpp:3784
 msgid "Failed reading range file."
 msgstr "Fehler beim Lesen der Rangedatei."
 
-#: ../src/gui/mainFrame.cpp:3729
+#: ../src/gui/mainFrame.cpp:3788
 msgid "Error loading file"
 msgstr "Fehler beim Laden der Datei"
 
-#: ../src/gui/mainFrame.cpp:3788 ../src/gui/mainFrame.cpp:3882
-#: ../src/gui/mainFrame.cpp:5284 ../src/gui/mainFrame.cpp:5803
+#: ../src/gui/mainFrame.cpp:3849 ../src/gui/mainFrame.cpp:3944
+#: ../src/gui/mainFrame.cpp:5449 ../src/gui/mainFrame.cpp:5968
 msgid "Cons."
 msgstr "Kons."
 
-#: ../src/gui/mainFrame.cpp:3844
+#: ../src/gui/mainFrame.cpp:3907
 msgid "Refresh Aborted."
 msgstr "Aktualisieren abgebrochen"
 
-#: ../src/gui/mainFrame.cpp:3886
+#: ../src/gui/mainFrame.cpp:3948
 msgid "*Cons."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:3888
+#: ../src/gui/mainFrame.cpp:3950
 msgid "§Cons."
 msgstr "§Kons."
 
-#: ../src/gui/mainFrame.cpp:3945
+#: ../src/gui/mainFrame.cpp:4007
 msgid "Complete"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4030
+#: ../src/gui/mainFrame.cpp:4105
 msgid "msgs"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4071
+#: ../src/gui/mainFrame.cpp:4146
 msgid "Autosave complete."
 msgstr "Autosave beendet."
 
-#: ../src/gui/mainFrame.cpp:4281
+#: ../src/gui/mainFrame.cpp:4350
 msgid "Aborting...."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:4344
+#: ../src/gui/mainFrame.cpp:4416
 msgid "Updated."
 msgstr "Updated."
 
-#: ../src/gui/mainFrame.cpp:4352
+#: ../src/gui/mainFrame.cpp:4425
+msgid "Calculating..."
+msgstr ""
+
+#: ../src/gui/mainFrame.cpp:4428
 msgid "\\% Done (Esc aborts)"
 msgstr "\\% fertig (Esc abbrechen)"
 
-#: ../src/gui/mainFrame.cpp:4354
+#: ../src/gui/mainFrame.cpp:4430
 msgid "\\% Done"
 msgstr "\\% fertig"
 
-#: ../src/gui/mainFrame.cpp:4624
+#: ../src/gui/mainFrame.cpp:4704
 msgid "Tip: You can shift-click to force full refresh, if required"
 msgstr "Tipp: Verwende shift-click um komplettes Aktualisieren zu erzwingen"
 
-#: ../src/gui/mainFrame.cpp:4686
+#: ../src/gui/mainFrame.cpp:4766
 msgid "No data to save"
 msgstr "Keine Daten zum Sichern"
 
-#: ../src/gui/mainFrame.cpp:4860
+#: ../src/gui/mainFrame.cpp:4950
 msgid "Aborting..."
 msgstr "Abbrechen..."
 
-#: ../src/gui/mainFrame.cpp:4866
+#: ../src/gui/mainFrame.cpp:4956
 msgid ""
 "Waiting for refresh to abort. Exiting could lead to the program "
 "backgrounding. Exit anyway? "
@@ -1983,63 +1798,68 @@ msgstr ""
 "Waiting for refresh to abort. Exiting could lead to the program "
 "backgrounding. Exit anyway? "
 
-#: ../src/gui/mainFrame.cpp:4867 ../src/gui/mainFrame.cpp:4887
+#: ../src/gui/mainFrame.cpp:4957 ../src/gui/mainFrame.cpp:4977
 msgid "Confirmation request"
 msgstr "Bestätigungsabfrage"
 
-#: ../src/gui/mainFrame.cpp:4886
+#: ../src/gui/mainFrame.cpp:4976
 msgid "Are you sure you wish to exit 3Depict?"
 msgstr "Sind Sie sicher, dass Sie 3Depict beenden wollen?"
 
-#: ../src/gui/mainFrame.cpp:5312
+#: ../src/gui/mainFrame.cpp:5314 ../src/gl/cameras.cpp:627
+#: ../src/gl/cameras.cpp:730
+msgid "Orthogonal"
+msgstr "Orthogonal"
+
+#: ../src/gui/mainFrame.cpp:5477
 msgid "Update Notice: New version "
 msgstr "Updatenotiz: Neue Version "
 
-#: ../src/gui/mainFrame.cpp:5312
+#: ../src/gui/mainFrame.cpp:5477
 msgid " found online."
 msgstr " online gefunden."
 
-#: ../src/gui/mainFrame.cpp:5316
+#: ../src/gui/mainFrame.cpp:5481
 msgid "Online Check: "
 msgstr "Überprüfe online:"
 
-#: ../src/gui/mainFrame.cpp:5316
+#: ../src/gui/mainFrame.cpp:5481
 msgid " is up-to-date."
 msgstr "ist up-to-date."
 
-#: ../src/gui/mainFrame.cpp:5406
+#: ../src/gui/mainFrame.cpp:5571
 msgid "An auto-save state was found, would you like to restore it?."
 msgstr "Ein auto-save Status wurde gefunden. Wollen Sie ihn wiederherstellen?"
 
-#: ../src/gui/mainFrame.cpp:5407
+#: ../src/gui/mainFrame.cpp:5572
 msgid "Autosave"
 msgstr "Automatisch speichern"
 
-#: ../src/gui/mainFrame.cpp:5414
+#: ../src/gui/mainFrame.cpp:5579
 msgid "Unable to load autosave file.."
 msgstr "Kann Autosavedatei nicht laden.."
 
-#: ../src/gui/mainFrame.cpp:5605
+#: ../src/gui/mainFrame.cpp:5770
 msgid "List of available filters"
 msgstr "Liste der verfügbaren Filter"
 
-#: ../src/gui/mainFrame.cpp:5607
+#: ../src/gui/mainFrame.cpp:5772
 msgid "Tree - drag to move items, hold ⌘ for copy. Tap delete to remove items"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5609
+#: ../src/gui/mainFrame.cpp:5774
 msgid ""
 "Tree - drag to move items, hold Ctrl for copy. Tap delete to remove items."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5611
+#: ../src/gui/mainFrame.cpp:5776
 msgid ""
 "Enable/Disable automatic updates of data when filter change takes effect"
 msgstr ""
 "Ein/Ausschalten vom automatischen Aktualisieren der Daten wenn Änderungen am "
 "Filter wirksam werden"
 
-#: ../src/gui/mainFrame.cpp:5614
+#: ../src/gui/mainFrame.cpp:5779
 msgid ""
 "Enable/Disable \"Alpha blending\" (transparency) in rendering system. "
 "Blending is used to smooth objects (avoids artefacts known as \"jaggies\") "
@@ -2051,7 +1871,7 @@ msgstr ""
 "und transparente Oberflächen zu generieren. Ausschalten erlaubt schnelleres "
 "Renden führt jedoch zu blockigerer Darstellung."
 
-#: ../src/gui/mainFrame.cpp:5615
+#: ../src/gui/mainFrame.cpp:5780
 msgid ""
 "Enable/Disable lighting calculations in rendering, for objects that request "
 "this. Lighting provides important depth cues for objects comprised of 3D "
@@ -2062,7 +1882,7 @@ msgstr ""
 "umrandete Objekte. Deaktivieren erlaubt u.U. schnelleres Rendern bei "
 "komplizierten Szenen."
 
-#: ../src/gui/mainFrame.cpp:5616
+#: ../src/gui/mainFrame.cpp:5781
 msgid ""
 "Enable/Disable weak randomisation (Galois linear feedback shift register). "
 "Strong randomisation uses a much slower random selection method, but "
@@ -2074,14 +1894,14 @@ msgstr ""
 "Auswahlmethode bietet dafür aber einen besseren Schutz gegen unbeabsichtigte "
 "Korrelationen und wird für die endgültige Analyse empfohlen."
 
-#: ../src/gui/mainFrame.cpp:5618
+#: ../src/gui/mainFrame.cpp:5783
 msgid ""
 "Limit the number of points that can be displayed in the 3D  scene. Does not "
 "affect filter tree calculations. Disabling this can severely reduce "
 "performance, due to large numbers of points being visible at once."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5619
+#: ../src/gui/mainFrame.cpp:5784
 msgid ""
 "Enable/Disable caching of intermediate results during filter updates. "
 "Disabling caching will use less system RAM, though changes to any filter "
@@ -2093,30 +1913,30 @@ msgstr ""
 "bei Änderungen der Filterparameter der ganze Filterbaum neu berechnet wird. "
 "Dies erhöht den Rechenaufwand deutlich."
 
-#: ../src/gui/mainFrame.cpp:5621
+#: ../src/gui/mainFrame.cpp:5786
 msgid "Camera data information"
 msgstr "Kamerainformation"
 
-#: ../src/gui/mainFrame.cpp:5625
+#: ../src/gui/mainFrame.cpp:5790
 msgid "Enable/disable visual effects on final 3D output"
 msgstr "Ein/Ausschalten von visuellen Effekten in der finalen 3D Ausgabe."
 
-#: ../src/gui/mainFrame.cpp:5627
+#: ../src/gui/mainFrame.cpp:5792
 msgid "Enable cropping post-process effect"
 msgstr "Cropping post-Prozess Effect einschalten"
 
-#: ../src/gui/mainFrame.cpp:5630
+#: ../src/gui/mainFrame.cpp:5795
 msgid ""
 "Colour based 3D effect enable/disable - requires appropriate colour filter "
 "3D glasses."
 msgstr ""
 "Farbbasierte 3D-Effekte ein/ausschalten - erfordert geeignete 3D-Brillen"
 
-#: ../src/gui/mainFrame.cpp:5631
+#: ../src/gui/mainFrame.cpp:5796
 msgid "Glasses colour mode"
 msgstr "Brillenfarbmodus"
 
-#: ../src/gui/mainFrame.cpp:5633
+#: ../src/gui/mainFrame.cpp:5798
 msgid ""
 "Level of separation between left and right images, which sets 3D depth to "
 "visual distortion tradeoff"
@@ -2124,95 +1944,99 @@ msgstr ""
 "Level of separation between left and right images, which sets 3D depth to "
 "visual distortion tradeoff"
 
-#: ../src/gui/mainFrame.cpp:5637
+#: ../src/gui/mainFrame.cpp:5802
 msgid "X"
 msgstr "X"
 
-#: ../src/gui/mainFrame.cpp:5638
+#: ../src/gui/mainFrame.cpp:5803
 msgid "Y"
 msgstr "Y"
 
-#: ../src/gui/mainFrame.cpp:5639
+#: ../src/gui/mainFrame.cpp:5804
 msgid "Save raw data to file"
 msgstr "Speichere Rohdaten in Datei"
 
-#: ../src/gui/mainFrame.cpp:5640
+#: ../src/gui/mainFrame.cpp:5805
 msgid "Copy raw data to clipboard"
 msgstr "Kopiere Rohdaten in die Zwischenablage"
 
-#: ../src/gui/mainFrame.cpp:5641
+#: ../src/gui/mainFrame.cpp:5806
 msgid "Manage \"stashed\" data."
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5642
+#: ../src/gui/mainFrame.cpp:5807
 msgid "Program text output"
 msgstr "Programm Textausgabe"
 
-#: ../src/gui/mainFrame.cpp:5643
+#: ../src/gui/mainFrame.cpp:5808
 msgid "Select active camera, or type to create new named camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5644
+#: ../src/gui/mainFrame.cpp:5809
 msgid "Remove the selected camera"
 msgstr "Ausgewählte Kamera entfernen"
 
-#: ../src/gui/mainFrame.cpp:5645
+#: ../src/gui/mainFrame.cpp:5810
 msgid "Perform cropping from coordinate frame of camera"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5646
+#: ../src/gui/mainFrame.cpp:5811
 msgid ""
 "Set the maximum amount of RAM to use in order to speed repeat computations"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5647
+#: ../src/gui/mainFrame.cpp:5812
 msgid "Collapse the filter tree"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5648
+#: ../src/gui/mainFrame.cpp:5813
 msgid "Expand the filter tree"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5649
+#: ../src/gui/mainFrame.cpp:5814
 msgid "Process the filter tree, hold shift to purge cached filter data"
 msgstr ""
 
-#: ../src/gui/mainFrame.cpp:5763
+#: ../src/gui/mainFrame.cpp:5928
 msgid "Crop"
 msgstr "Zuschneiden"
 
-#: ../src/gui/mainFrame.cpp:5764
+#: ../src/gui/mainFrame.cpp:5929
 msgid "Stereo"
 msgstr "Stereo"
 
-#: ../src/gui/mainFrame.cpp:5781
+#: ../src/gui/mainFrame.cpp:5946
 #: ../src/backend/filters/externalProgram.cpp:596
-#: ../src/backend/filters/ionColour.cpp:316
-#: ../src/backend/filters/spectrumPlot.cpp:604
+#: ../src/backend/filters/ionColour.cpp:308
+#: ../src/backend/filters/spectrumPlot.cpp:612
 msgid "Data"
 msgstr "Daten"
 
-#: ../src/gui/mainFrame.cpp:5782
+#: ../src/gui/mainFrame.cpp:5947
 msgid "Cam"
 msgstr "Cam"
 
-#: ../src/gui/mainFrame.cpp:5783
+#: ../src/gui/mainFrame.cpp:5948
 msgid "Post"
 msgstr "Post"
 
-#: ../src/gui/mainFrame.cpp:5784
+#: ../src/gui/mainFrame.cpp:5949
 msgid "Tools"
 msgstr "Werkz."
 
-#: ../src/gui/mainFrame.cpp:5802
+#: ../src/gui/mainFrame.cpp:5967
 msgid "Raw"
 msgstr "Roh"
 
+#: ../src/gui/mainFrame.cpp:6010
+msgid "Align Camera"
+msgstr ""
+
 #: ../src/gui/mathglPane.cpp:259
 msgid "No plots selected."
 msgstr "Kein Plot ausgewählt."
 
-#: ../src/gui/mathglPane.cpp:1198
+#: ../src/gui/mathglPane.cpp:1201
 msgid ""
 "Unable to allocate requested memory.\n"
 " Try a lower resolution, or save as vector (SVG)."
@@ -2220,185 +2044,632 @@ msgstr ""
 "Kann den notwendigen Speicher nicht zuordnen. Versuche eine geringer "
 "Auflösung oder speichere als Vektografik (svg)."
 
-#: ../src/gui/mathglPane.cpp:1200
+#: ../src/gui/mathglPane.cpp:1203
 msgid "Plotting functions returned an error:\n"
 msgstr "Plot-Funktion meldete einen Fehler:\n"
 
-#: ../src/gui/mathglPane.cpp:1202
+#: ../src/gui/mathglPane.cpp:1205
 msgid "File readback check failed"
 msgstr "File readback check failed"
 
-#: ../src/gui/mathglPane.cpp:1204
+#: ../src/gui/mathglPane.cpp:1207
 msgid "Filesize during readback appears to be zero."
 msgstr "Filesize during readback appears to be zero."
 
-#: ../src/3Depict.cpp:375
-msgid "File : "
-msgstr "Datei : "
+#: ../src/backend/filter.cpp:55
+msgid "2D Plot"
+msgstr ""
 
-#: ../src/3Depict.cpp:375
-msgid " does not exist. Skipping"
-msgstr " existiert nicht. Überspringe"
+#: ../src/backend/filter.cpp:56
+msgid "Draw"
+msgstr "Zeichnen"
 
-#: ../src/backend/configFile.cpp:187
-msgid "Config file present, but is not valid (root node test)"
-msgstr "Konfigurationsdatei vorhanden, aber nicht gültig (root node test)"
+#: ../src/backend/filter.cpp:57
+msgid "Range"
+msgstr "Range"
 
-#: ../src/backend/configFile.cpp:228
-msgid "Unable to interpret recent file entry"
-msgstr "Kann den letzten Dateieintrag nicht interpretieren"
+#: ../src/backend/filter.cpp:58
+msgid "Voxel"
+msgstr "Voxel"
 
-#: ../src/backend/configFile.cpp:268
-msgid "Unable to determine filter type in defaults listing."
-msgstr "Kann den Filtertyp im Defaultslisting nicht bestimmen."
+#: ../src/backend/filter.cpp:192 ../src/backend/filters/ionColour.cpp:411
+msgid "Aborted"
+msgstr "Abgebrochen"
 
-#: ../src/backend/configFile.cpp:605
-msgid "Online access for non win32/apple platforms is intentionally disabled, "
+#: ../src/backend/state.cpp:151
+msgid ""
+"This file is a \"state\" file for the 3Depict program, and stores "
+"information about a particular analysis session. This file should be a valid "
+"\"XML\" file"
 msgstr ""
-"Onlinezugang für nicht Win32/apple systeme wurde absichtlich deaktiviert."
+"Diese Datei ist ein \"Status\" Datei für das Programm 3Depict. Sie speichert "
+"Informationen über die jeweiligen Analysesitzung. Dies sollte ein gültige "
+"\"XML\" Datei sein."
 
-#: ../src/backend/configFile.cpp:606
+#: ../src/backend/state.cpp:319
+msgid "Failed to allocate parser"
+msgstr "Kann Parser nicht zuordnen"
+
+#: ../src/backend/state.cpp:354
 msgid ""
-"regardless of the settings you use here. Use your package manager to keep up-"
-"to-date"
+"Unable to retrieve root node in input state file... Is this really a non-"
+"empty XML file?"
 msgstr ""
-"Nutzen Sie Ihren Paketmanager um up-to-date zu sein unabhängig von den "
-"Einstellungen die Sie hier verwenden"
-
-#: ../src/backend/plot.cpp:28 ../src/backend/filters/algorithms/mass.cpp:25
-#: ../src/backend/filters/voxelise.cpp:124
-#: ../src/backend/filters/voxelise.cpp:130
-#: ../src/backend/filters/spectrumPlot.cpp:76
-msgid "None"
-msgstr "Keiner"
 
-#: ../src/backend/plot.cpp:29
-msgid "Moving avg."
-msgstr "Gleit.Durchschn."
+#: ../src/backend/state.cpp:361
+msgid "Base state node missing. Is this really a state XML file??"
+msgstr ""
 
-#: ../src/backend/plot.cpp:33
-msgid "Lines"
-msgstr "Linien"
+#: ../src/backend/state.cpp:390
+msgid "State was created by a newer version of this program.. "
+msgstr "Status wurde von einer neueren Version dieses Programmes erstellt.. "
+
+#: ../src/backend/state.cpp:391
+msgid "file reading will continue, but may fail."
+msgstr "Datei wird weiter eingelesen kann aber unter Umständen fehlschlagen."
+
+#: ../src/backend/state.cpp:396
+msgid ""
+"Warning, unparseable version number in state file. File reading will "
+"continue, but may fail"
+msgstr ""
+"Warnung: Nicht lesbare Versionsnummer in Statusdatei. Datei wird weiter "
+"eingelesen kann aber unter Umständen fehlschlagen."
+
+#: ../src/backend/state.cpp:403
+msgid "Unable to find the \"writer\" node"
+msgstr "Kann \"writer\" node nicht finden"
+
+#: ../src/backend/state.cpp:413
+msgid "Unable to find the \"backcolour\" node."
+msgstr "Unable to find the \"backcolour\" node."
+
+#: ../src/backend/state.cpp:420
+msgid "\"backcolour\" node missing \"r\" value."
+msgstr "\"backcolour\" node fehlt \"r\" Wert."
+
+#: ../src/backend/state.cpp:425
+msgid "Unable to interpret \"backColour\" node's \"r\" value."
+msgstr "Kann \"backColour\" node's \"r\" Wert nicht interpretieren."
+
+#: ../src/backend/state.cpp:433
+msgid "\"backcolour\" node missing \"g\" value."
+msgstr "\"backcolour\" node fehlt \"g\" Wert."
+
+#: ../src/backend/state.cpp:439
+msgid "Unable to interpret \"backColour\" node's \"g\" value."
+msgstr "Kann \"backColour\" node's \"g\" Wert nicht interpretieren."
+
+#: ../src/backend/state.cpp:447
+msgid "\"backcolour\" node missing \"b\" value."
+msgstr "\"backcolour\" node fehlt \"b\" Wert."
+
+#: ../src/backend/state.cpp:453
+msgid "Unable to interpret \"backColour\" node's \"b\" value."
+msgstr "Kann \"backColour\" node's \"b\" Wert nicht interpretieren."
+
+#: ../src/backend/state.cpp:460
+msgid "\"backcolour\"s rgb values must be in range [0,1]"
+msgstr "\"backcolour\"s rgb Wert muss im Bereich [0,1] liegen"
+
+#: ../src/backend/state.cpp:488
+msgid "Unable to find or interpret \"showaxis\" node"
+msgstr "Kann \"showaxis\" node nicht interpretieren"
+
+#: ../src/backend/state.cpp:532
+msgid "Unable to locate \"filtertree\" node."
+msgstr "Kann \"filtertree\" node nicht finden."
+
+#: ../src/backend/state.cpp:548
+msgid "Cameras section missing \"active\" node."
+msgstr "Cameras section fehlt \"active\" node."
+
+#: ../src/backend/state.cpp:556
+msgid "Unable to find property \"value\"  for \"cameras->active\" node."
+msgstr "Kann \"Eigenschaftswert\"  für \"Kamera->aktiv\" Node nicht finden."
+
+#: ../src/backend/state.cpp:562
+msgid "Unable to interpret property \"value\"  for \"cameras->active\" node."
+msgstr ""
+"Kann \"Eigenschaftswert\"  für \"Kamera->aktiv\" Node nicht interpretieren."
+
+#: ../src/backend/state.cpp:582
+msgid "Failed to interpret camera state for camera : "
+msgstr ""
+
+#: ../src/backend/state.cpp:590
+msgid "Unable to interpret the camera type for camera : "
+msgstr "Kann den Kameratype nicht interpretieren für :"
+
+#: ../src/backend/state.cpp:648
+msgid "Unable to locate stash name for stash "
+msgstr "Kann den Stashnamen für Stash  nicht finden"
+
+#: ../src/backend/state.cpp:655
+msgid "Empty stash name for stash "
+msgstr "Leerer Stashname für Stash"
+
+#: ../src/backend/state.cpp:664
+msgid "No filter tree for stash:"
+msgstr ""
+
+#: ../src/backend/state.cpp:670
+msgid "For stash "
+msgstr "Für Stash "
+
+#: ../src/backend/state.cpp:702
+msgid "Unrecognised effect :"
+msgstr "Nichterkannter Effekt :"
+
+#: ../src/backend/state.cpp:712
+msgid "Duplicate effect found"
+msgstr "Doppelter Effekt gefunden"
+
+#: ../src/backend/state.cpp:712
+msgid " cannot use."
+msgstr "kann nicht   verwenden."
+
+#: ../src/backend/state.cpp:722
+msgid "Error reading effect : "
+msgstr "Fehler beim Lesen:"
+
+#: ../src/backend/state.cpp:927
+msgid "-merge"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:44 ../src/backend/APT/APTFileIO.cpp:79
+#: ../src/backend/APT/APTFileIO.cpp:103
+msgid "Error opening file"
+msgstr "Fehler beim Öffnen der Datei"
+
+#: ../src/backend/APT/APTFileIO.cpp:45
+msgid "Only found header, no data"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:46
+msgid "Unable to reopen file after first scan"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:47
+msgid "Error whilst reading file contents"
+msgstr "Fehler beim Lesen des Dateiinhaltes"
+
+#: ../src/backend/APT/APTFileIO.cpp:48 ../src/backend/APT/APTFileIO.cpp:49
+msgid "Unexpected file format"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:50
+msgid "Insufficient memory to continue"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:54
+msgid "Memory allocation failure on POS load"
+msgstr "Speicherzuweisungsfeher beim Laden der pos-Datei"
+
+#: ../src/backend/APT/APTFileIO.cpp:55
+msgid "Error opening pos file"
+msgstr "Fehler beim Öffnen der pos-Datei"
+
+#: ../src/backend/APT/APTFileIO.cpp:56
+msgid "Pos file empty"
+msgstr "Pos-Datei ist leer"
+
+#: ../src/backend/APT/APTFileIO.cpp:57
+msgid "Pos file size appears to have non-integer number of entries"
+msgstr ""
+"Pos-Dateigröße scheint eine nicht ganzzahlige Anzahl an Einträgen zu haben"
+
+#: ../src/backend/APT/APTFileIO.cpp:58
+msgid "Error reading from pos file (after open)"
+msgstr "Fehler beim Lesen aus pos-Datei (nach dem öffnen)"
+
+#: ../src/backend/APT/APTFileIO.cpp:59
+msgid "Error - Found NaN in pos file"
+msgstr "Fehler - Fand NaN in pos-Datei"
+
+#: ../src/backend/APT/APTFileIO.cpp:60
+msgid "Error - Found Inf in pos file"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:61
+msgid "Pos load aborted by interrupt."
+msgstr "Pos laden durch Interrupt abgebrochen."
+
+#: ../src/backend/APT/APTFileIO.cpp:80
+msgid "No numerical data found"
+msgstr "Keine numerischen Daten gefunden"
+
+#: ../src/backend/APT/APTFileIO.cpp:81
+msgid "Error re-opening file, after first scan"
+msgstr "Fehler beim nochmaligen Öffnen der Datei nach dem ersten Scan"
+
+#: ../src/backend/APT/APTFileIO.cpp:82
+msgid "Unable to read file contents after open"
+msgstr "Kann den Dateiinhalt nach dem Öffnen nich lesen"
+
+#: ../src/backend/APT/APTFileIO.cpp:83
+msgid "Error interpreting field in file"
+msgstr "Fehler beim Interpretieren eine Feldes in der Datei"
+
+#: ../src/backend/APT/APTFileIO.cpp:84
+msgid "Incorrect number of fields in file"
+msgstr "Die Datei enthält eine falsche Anzahl von Feldern"
+
+#: ../src/backend/APT/APTFileIO.cpp:85 ../src/backend/APT/APTFileIO.cpp:107
+msgid "Unable to allocate memory to store data"
+msgstr "Kann Speicher nicht zuordnen"
+
+#: ../src/backend/APT/APTFileIO.cpp:104
+msgid "File is empty"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:105
+msgid "Filesize does not match expected format"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:106
+msgid "File version number not <4, as expected"
+msgstr ""
+
+#: ../src/backend/APT/APTFileIO.cpp:108
+msgid "Unable to detect endian-ness in file"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:48
+msgid "Error opening file, check name and permissions."
+msgstr "Fehler beim Öffnen der Datei, überprüfe Namen und Berechtigungen."
+
+#: ../src/backend/APT/APTRanges.cpp:49
+msgid ""
+"Error interpreting range file header, expecting ion count and range count, "
+"respectively."
+msgstr ""
+"Fehler beim Rangedatei interpretieren, erwarte Ionenanzahl bzw. Rangeanzahl."
+
+#: ../src/backend/APT/APTRanges.cpp:50
+msgid ""
+"Range file appears to be empty, check file is a proper range file and is not "
+"empty."
+msgstr ""
+"Rangedatei scheint leer zu sein. Prüfe ob die Datei wirklich ein Rangedatei "
+"und nicht leer ist."
+
+#: ../src/backend/APT/APTRanges.cpp:51
+msgid "Error reading the long name for ion."
+msgstr "Fehler beim Lesen des langen Namens für Ion."
+
+#: ../src/backend/APT/APTRanges.cpp:52
+msgid "Error reading the short name for ion."
+msgstr "Fehler beim Lesen des kurzen Namens für Ion."
+
+#: ../src/backend/APT/APTRanges.cpp:53
+msgid ""
+"Error reading colour data in the file, expecting 3 decimal values, space "
+"separated."
+msgstr ""
+"Fehler beim Lesen der Farbinformationen in der Datei. Erwarte 3, durch "
+"Leerzeichen getrennte, Dezimalwerte."
+
+#: ../src/backend/APT/APTRanges.cpp:54
+msgid ""
+"Tried skipping to table separator line (line with dashes), but did not find "
+"it."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:55
+msgid ""
+"Number of ions in the table header did not match the number specified at the "
+"start of the file"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:56
+msgid ""
+"Unexpected failure whilst trying to skip over range lead-in data (bit before "
+"range start value)"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:57
+msgid ""
+"Range table had an incorrect number of entries, should be 2 or 3 + number of "
+"ranges"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:58
+msgid "Unable to read range start and end values"
+msgstr "Kann Anfangs und Endwert des Range nicht lesen"
+
+#: ../src/backend/APT/APTRanges.cpp:59
+msgid "Unable to read range table entry"
+msgstr "Kann Rangetabelleneintrag nich lesen"
+
+#: ../src/backend/APT/APTRanges.cpp:60
+msgid ""
+"Error reading file, unexpected format, are you sure it is a proper range "
+"file?"
+msgstr ""
+"Fehler beim Lesen der Datei: Unerwartetes Format, sind Sie sicher, dass dies "
+"eine korrekte Rangedatei ist?"
+
+#: ../src/backend/APT/APTRanges.cpp:61
+msgid ""
+"Too many ranges appeared to have range entries with no usable data (eg, all "
+"blank)"
+msgstr "Zu viele Ranges scheinen  ungültige Einträge zu haben (z.B. alle leer)"
+
+#: ../src/backend/APT/APTRanges.cpp:62
+msgid ""
+"Range file appears to contain malformed data, check things like start and "
+"ends of m/c are not equal or flipped."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:63
+msgid "Range file appears to be inconsistent (eg, overlapping ranges)"
+msgstr "Rangedatei schein inkonsistent zu sein (z.B. überlappende Ranges)"
+
+#: ../src/backend/APT/APTRanges.cpp:64
+msgid "No ion name mapping found  for multiple ion."
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:65
+msgid "Polyatomic extension range matches multiple masses in first section"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:66
+msgid "Range file is exceedingly large. Refusing to open"
+msgstr ""
+
+#: ../src/backend/APT/APTRanges.cpp:1404
+msgid ""
+"Range headings do not match order of the ions listed in the name "
+"specifications. The name specification ordering will be used when reading "
+"the range table, as the range heading section is declared as a comment in "
+"the file-format specifications, and is not to be intepreted by this program. "
+"Check range-species associations actually match what you expect."
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:73
+msgid "Arrow"
+msgstr "Pfeil"
+
+#: ../src/backend/filters/annotation.cpp:74
+msgid "Text"
+msgstr "Text"
+
+#: ../src/backend/filters/annotation.cpp:75
+msgid "Arrow+Text"
+msgstr "Pfeil+Text"
+
+#: ../src/backend/filters/annotation.cpp:76
+msgid "Angle"
+msgstr "Winkel"
+
+#: ../src/backend/filters/annotation.cpp:77
+msgid "Ruler"
+msgstr "Lineal"
+
+#: ../src/backend/filters/annotation.cpp:524
+msgid "Enable"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:527
+msgid "Enable/disable annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:548
+msgid "Type or style of annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:564
+#: ../src/backend/filters/annotation.cpp:668
+msgid "Text of annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:568
+#: ../src/backend/filters/ionClip.cpp:529
+#: ../src/backend/filters/ionClip.cpp:551
+#: ../src/backend/filters/ionClip.cpp:573
+#: ../src/backend/filters/ionClip.cpp:610
+#: ../src/backend/filters/transform.cpp:1233
+#: ../src/backend/filters/transform.cpp:1260
+#: ../src/backend/filters/transform.cpp:1286
+#: ../src/backend/filters/profile.cpp:1013
+#: ../src/backend/filters/profile.cpp:1051
+#: ../src/backend/filters/spatialAnalysis.cpp:1041 ../src/gl/cameras.cpp:603
+msgid "Origin"
+msgstr "Ursprung"
+
+#: ../src/backend/filters/annotation.cpp:572
+msgid "Position of annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:576
+#: ../src/backend/filters/annotation.cpp:683
+#: ../src/backend/filters/annotation.cpp:742
+#: ../src/backend/filters/annotation.cpp:831
+msgid "Up dir"
+msgstr "Up dir"
+
+#: ../src/backend/filters/annotation.cpp:580
+#: ../src/backend/filters/annotation.cpp:835
+msgid "Vector for up direction of annotation text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:584
+#: ../src/backend/filters/annotation.cpp:690
+#: ../src/backend/filters/annotation.cpp:734
+#: ../src/backend/filters/annotation.cpp:839
+msgid "Across dir"
+msgstr "Across dir"
+
+#: ../src/backend/filters/annotation.cpp:588
+#: ../src/backend/filters/annotation.cpp:843
+msgid "Reading direction for annotation"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:593
+#: ../src/backend/filters/annotation.cpp:675
+#: ../src/backend/filters/annotation.cpp:769
+msgid "Text size"
+msgstr "Textgröße"
+
+#: ../src/backend/filters/annotation.cpp:597
+#: ../src/backend/filters/annotation.cpp:679
+#: ../src/backend/filters/annotation.cpp:851
+msgid "Relative size of annotation text"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:609
+#: ../src/backend/filters/annotation.cpp:650
+msgid "3D position for tail of arrow"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:617
+#: ../src/backend/filters/annotation.cpp:659
+msgid "3D Position to which arrow points"
+msgstr ""
+
+#: ../src/backend/filters/annotation.cpp:620
+#: ../src/backend/filters/annotation.cpp:730
+msgid "Positioning"
+msgstr ""
 
-#: ../src/backend/plot.cpp:34
-msgid "Bars"
-msgstr "Block"
+#: ../src/backend/filters/annotation.cpp:625
+#: ../src/backend/filters/annotation.cpp:697
+msgid "Tip radius"
+msgstr ""
 
-#: ../src/backend/plot.cpp:35
-msgid "Steps"
-msgstr "Stufen"
+#: ../src/backend/filters/annotation.cpp:629
+msgid "Size of the arrow head"
+msgstr ""
 
-#: ../src/backend/plot.cpp:36
-msgid "Stem"
-msgstr "Stem"
+#: ../src/backend/filters/annotation.cpp:633
+msgid "Line size"
+msgstr ""
 
-#: ../src/backend/plot.cpp:37
-msgid "Points"
-msgstr "Punkte"
+#: ../src/backend/filters/annotation.cpp:637
+msgid "Thickness of line used to draw arrow stem"
+msgstr ""
 
-#: ../src/backend/plot.cpp:39
-msgid "Density"
+#: ../src/backend/filters/annotation.cpp:671
+msgid "Options"
 msgstr ""
 
-#: ../src/backend/plot.cpp:40
-msgid "Scatter"
+#: ../src/backend/filters/annotation.cpp:707
+msgid "Position A"
+msgstr "Position A"
+
+#: ../src/backend/filters/annotation.cpp:711
+msgid "Location of first non-central vertex"
 msgstr ""
 
-#: ../src/backend/plot.cpp:739 ../src/backend/plot.cpp:747
-msgid "Multiple data types"
+#: ../src/backend/filters/annotation.cpp:715
+msgid "Origin "
+msgstr "Ursprung "
+
+#: ../src/backend/filters/annotation.cpp:719
+msgid "Location of central vertex"
 msgstr ""
 
-#: ../src/backend/plot.cpp:1581
-msgid "error"
-msgstr "Fehler"
+#: ../src/backend/filters/annotation.cpp:723
+msgid "Position B"
+msgstr "Position B"
 
-#: ../src/backend/plot.cpp:1821
-msgid "Amplitude"
+#: ../src/backend/filters/annotation.cpp:727
+msgid "Location of second non-central vertex"
 msgstr ""
 
-#: ../src/backend/filtertree.cpp:1146
-msgid "WARNING: Skipping node "
-msgstr "WARNUNG: Skipping node "
+#: ../src/backend/filters/annotation.cpp:738
+msgid "Reading direction for angle text"
+msgstr ""
 
-#: ../src/backend/filtertree.cpp:1146
-msgid " as it was not recognised"
-msgstr " wurde nicht erkannt."
+#: ../src/backend/filters/annotation.cpp:743
+msgid "Vector for up direction of angle text"
+msgstr ""
 
-#: ../src/backend/filtertree.cpp:1184
-msgid "Error processing node: "
-msgstr "Fehler beim Verarbeiten von Node: "
+#: ../src/backend/filters/annotation.cpp:751
+msgid "Reflexive"
+msgstr "Reflexive"
 
-#: ../src/backend/filters/externalProgram.cpp:259
-msgid "Collate Input"
+#: ../src/backend/filters/annotation.cpp:754
+msgid "Measure interor (enabled) or exterior angle (disabled)"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:348
-msgid "Execute"
+#: ../src/backend/filters/annotation.cpp:759
+msgid "Show Angle"
+msgstr "Zeige Winkel"
+
+#: ../src/backend/filters/annotation.cpp:763
+msgid "Display angle text (when enabled)"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:389
-msgid "Collate output"
+#: ../src/backend/filters/annotation.cpp:773
+msgid "Size of angle text"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:564
-#: ../src/backend/filters/externalProgram.cpp:578
-msgid "Command"
-msgstr "Befehl"
+#: ../src/backend/filters/annotation.cpp:791
+msgid "Digit format"
+msgstr "Zahlenformat"
 
-#: ../src/backend/filters/externalProgram.cpp:567
+#: ../src/backend/filters/annotation.cpp:795
 msgid ""
-"Full command to send to operating system. See manual for escape sequence "
-"meanings"
+"Format of angle text; # for numeral position, '.' for separator, eg ##.## "
+"gives 12.34"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:571
-msgid "Work Dir"
-msgstr "Arbeitsverzeichnis"
+#: ../src/backend/filters/annotation.cpp:801
+#: ../src/backend/filters/annotation.cpp:886
+msgid "Sphere size"
+msgstr "Kugelgröße"
 
-#: ../src/backend/filters/externalProgram.cpp:574
-msgid "Directory to run the command in"
+#: ../src/backend/filters/annotation.cpp:805
+#: ../src/backend/filters/annotation.cpp:890
+msgid "Marker sphere size for manipulating tool"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:581
-msgid "Cleanup input"
-msgstr "Bereinige Eingabe"
+#: ../src/backend/filters/annotation.cpp:819
+msgid "Ruler beginning 3D location"
+msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:584
-msgid "Erase input files when command completed"
+#: ../src/backend/filters/annotation.cpp:827
+msgid "Ruler finish 3D location"
 msgstr ""
 
-#: ../src/backend/filters/externalProgram.cpp:589
-msgid "Cache"
-msgstr "Zwischenspeicher"
+#: ../src/backend/filters/annotation.cpp:848
+#: ../src/backend/filters/boundingBox.cpp:715
+msgid "Font Size"
+msgstr "Schriftgröße"
 
-#: ../src/backend/filters/externalProgram.cpp:592
+#: ../src/backend/filters/annotation.cpp:857
+msgid "Fixed ticks"
+msgstr "Fixe Marker"
+
+#: ../src/backend/filters/annotation.cpp:860
 msgid ""
-"Assume program does not alter its output, unless inputs from 3Depict are "
-"altered"
+"Use fixed (enabled) number of text markers, or one every fixed distance "
+"(disabled)"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:26
-msgid "Flat TOF"
-msgstr ""
+#: ../src/backend/filters/annotation.cpp:867
+msgid "Num Ticks"
+msgstr "Anzahl Marker"
 
-#: ../src/backend/filters/algorithms/mass.cpp:33
-msgid "INsufficient bins to perform fit"
+#: ../src/backend/filters/annotation.cpp:870
+msgid "Number of tick marks along ruler"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:34
-msgid "Insufficient counts to perform fit"
-msgstr ""
+#: ../src/backend/filters/annotation.cpp:877
+msgid "Tick Spacing"
+msgstr "Markerabstand"
 
-#: ../src/backend/filters/algorithms/mass.cpp:35
-msgid "Insufficient data to perform fit"
+#: ../src/backend/filters/annotation.cpp:880
+msgid "Distance between tick marks along ruler"
 msgstr ""
 
-#: ../src/backend/filters/algorithms/mass.cpp:36
-msgid "Data did not appear to be random noise - cannot fit noise level"
+#: ../src/backend/filters/annotation.cpp:904
+msgid "Colour for ruler and ticks"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:65
-#: ../src/backend/filters/compositionProfile.cpp:53
+#: ../src/backend/filters/ionClip.cpp:65 ../src/backend/filters/profile.cpp:53
 msgid "Sphere"
 msgstr "Kugel"
 
@@ -2414,1898 +2685,1996 @@ msgstr "Zylinder"
 msgid "Aligned box"
 msgstr "Ausgerichtete Box"
 
-#: ../src/backend/filters/ionClip.cpp:497
-#: ../src/backend/filters/compositionProfile.cpp:971
-msgid "Primitive"
-msgstr "Primitiv"
+#: ../src/backend/filters/ionClip.cpp:498
+#: ../src/backend/filters/profile.cpp:991
+msgid "Primitive"
+msgstr "Primitiv"
+
+#: ../src/backend/filters/ionClip.cpp:501
+msgid "Shape of clipping object"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:507
+#: ../src/backend/filters/profile.cpp:997
+msgid "Show Primitive"
+msgstr "Zeige Primitiv"
+
+#: ../src/backend/filters/ionClip.cpp:510
+msgid "Display the 3D interaction object"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:515
+msgid "Invert Clip"
+msgstr "Invertiere Clip"
+
+#: ../src/backend/filters/ionClip.cpp:518
+msgid ""
+"Switch between retaining points inside (false) and outside (true) of "
+"primitive"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:532
+#: ../src/backend/filters/profile.cpp:1054
+msgid "Position for centre of sphere"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:537
+#: ../src/backend/filters/ionClip.cpp:597
+#: ../src/backend/filters/profile.cpp:1037
+#: ../src/backend/filters/profile.cpp:1059
+#: ../src/backend/filters/spatialAnalysis.cpp:134
+#: ../src/backend/filters/spatialAnalysis.cpp:1058
+msgid "Radius"
+msgstr "Radius"
+
+#: ../src/backend/filters/ionClip.cpp:540
+#: ../src/backend/filters/profile.cpp:1062
+msgid "Radius of sphere"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:554
+msgid "Position that plane passes through"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:559
+msgid "Plane Normal"
+msgstr "Plane Normal"
+
+#: ../src/backend/filters/ionClip.cpp:562
+msgid "Perpendicular direction for plane"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:576
+msgid "Centre of cylinder"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:581
+#: ../src/backend/filters/transform.cpp:1294
+#: ../src/backend/filters/profile.cpp:1021
+#: ../src/backend/filters/spatialAnalysis.cpp:1049
+msgid "Axis"
+msgstr "Achse"
+
+#: ../src/backend/filters/ionClip.cpp:584
+msgid "Positive vector for cylinder"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:589
+#: ../src/backend/filters/profile.cpp:1029
+msgid "Lock Axis Mag."
+msgstr "Achsen Vergr. sperren"
+
+#: ../src/backend/filters/ionClip.cpp:592
+msgid "Prevent changing length of cylinder during 3D interaction"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:600
+#: ../src/backend/filters/profile.cpp:1040
+#: ../src/backend/filters/spatialAnalysis.cpp:1061
+msgid "Radius of cylinder"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:613
+msgid "Centre of axis aligned box"
+msgstr ""
+
+#: ../src/backend/filters/ionClip.cpp:618
+msgid "Corner offset"
+msgstr "Corner offset"
+
+#: ../src/backend/filters/ionClip.cpp:621
+msgid "Vector to corner of box"
+msgstr ""
+
+#: ../src/backend/filters/voxelise.cpp:111
+msgid "None (Raw count)"
+msgstr "Keine (Roh count)"
+
+#: ../src/backend/filters/voxelise.cpp:112
+msgid "Volume (Density)"
+msgstr "Volumen (Dichte)"
+
+#: ../src/backend/filters/voxelise.cpp:113
+msgid "All Ions (conc)"
+msgstr "Alle Ionen (Konz)"
+
+#: ../src/backend/filters/voxelise.cpp:114
+msgid "Ratio (Num/Denom)"
+msgstr "Verhältnis (Zähler/Nenner)"
+
+#: ../src/backend/filters/voxelise.cpp:118
+msgid "Point Cloud"
+msgstr "Punktwolke"
+
+#: ../src/backend/filters/voxelise.cpp:119
+msgid "Isosurface"
+msgstr "Isosurface"
+
+#: ../src/backend/filters/voxelise.cpp:120
+msgid "Axial slice"
+msgstr ""
+
+#: ../src/backend/filters/voxelise.cpp:124
+#: ../src/backend/filters/voxelise.cpp:130
+#: ../src/backend/filters/algorithms/mass.cpp:25
+#: ../src/backend/filters/spectrumPlot.cpp:76 ../src/backend/plot.cpp:28
+msgid "None"
+msgstr "Keiner"
 
-#: ../src/backend/filters/ionClip.cpp:500
-msgid "Shape of clipping object"
+#: ../src/backend/filters/voxelise.cpp:125
+msgid "Gaussian (blur)"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:506
-#: ../src/backend/filters/compositionProfile.cpp:977
-msgid "Show Primitive"
-msgstr "Zeige Primitiv"
+#: ../src/backend/filters/voxelise.cpp:126
+msgid "Lapl. of Gauss. (edges)"
+msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:509
-msgid "Display the 3D interaction object"
+#: ../src/backend/filters/voxelise.cpp:131
+msgid "Linear"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:514
-msgid "Invert Clip"
-msgstr "Invertiere Clip"
+#: ../src/backend/filters/voxelise.cpp:564
+msgid "Voxel Limits (min,max): ("
+msgstr "Voxel Grenzen (min,max): ("
 
-#: ../src/backend/filters/ionClip.cpp:517
-msgid ""
-"Switch between retaining points inside (false) and outside (true) of "
-"primitive"
-msgstr ""
+#: ../src/backend/filters/voxelise.cpp:709
+msgid "Fixed width"
+msgstr "Fixe Breite"
 
-#: ../src/backend/filters/ionClip.cpp:531
-#: ../src/backend/filters/compositionProfile.cpp:1034
-msgid "Position for centre of sphere"
+#: ../src/backend/filters/voxelise.cpp:713
+msgid "If true, use fixed size voxels, otherwise use fixed count"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:536
-#: ../src/backend/filters/ionClip.cpp:596
-#: ../src/backend/filters/compositionProfile.cpp:1017
-#: ../src/backend/filters/compositionProfile.cpp:1039
-#: ../src/backend/filters/spatialAnalysis.cpp:121
-#: ../src/backend/filters/spatialAnalysis.cpp:863
-msgid "Radius"
-msgstr "Radius"
+#: ../src/backend/filters/voxelise.cpp:719
+msgid "Bin width x"
+msgstr "Bin-Breite x"
 
-#: ../src/backend/filters/ionClip.cpp:539
-#: ../src/backend/filters/compositionProfile.cpp:1042
-msgid "Radius of sphere"
+#: ../src/backend/filters/voxelise.cpp:723
+msgid "Voxel size in X direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:553
-msgid "Position that plane passes through"
+#: ../src/backend/filters/voxelise.cpp:727
+msgid "Bin width y"
+msgstr "Bin-Breite y"
+
+#: ../src/backend/filters/voxelise.cpp:730
+msgid "Voxel size in Y direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:558
-msgid "Plane Normal"
-msgstr "Plane Normal"
+#: ../src/backend/filters/voxelise.cpp:736
+msgid "Bin width z"
+msgstr "Bin-Breite Z"
 
-#: ../src/backend/filters/ionClip.cpp:561
-msgid "Perpendicular direction for plane"
+#: ../src/backend/filters/voxelise.cpp:739
+msgid "Voxel size in Z direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:575
-msgid "Centre of cylinder"
+#: ../src/backend/filters/voxelise.cpp:746
+msgid "Num bins x"
+msgstr "Anzahl Bins x"
+
+#: ../src/backend/filters/voxelise.cpp:750
+msgid "Number of voxels to use in X direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:580
-#: ../src/backend/filters/compositionProfile.cpp:1001
-#: ../src/backend/filters/spatialAnalysis.cpp:854
-#: ../src/backend/filters/transform.cpp:1263
-msgid "Axis"
-msgstr "Achse"
+#: ../src/backend/filters/voxelise.cpp:755
+msgid "Num bins y"
+msgstr "Anzahl Bins y"
 
-#: ../src/backend/filters/ionClip.cpp:583
-msgid "Positive vector for cylinder"
+#: ../src/backend/filters/voxelise.cpp:758
+msgid "Number of voxels to use in Y direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:588
-#: ../src/backend/filters/compositionProfile.cpp:1009
-msgid "Lock Axis Mag."
-msgstr "Achsen Vergr. sperren"
+#: ../src/backend/filters/voxelise.cpp:764
+msgid "Num bins z"
+msgstr "Anzahl Bins z"
 
-#: ../src/backend/filters/ionClip.cpp:591
-msgid "Prevent changing length of cylinder during 3D interaction"
+#: ../src/backend/filters/voxelise.cpp:766
+msgid "Number of voxels to use in Z direction"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:599
-#: ../src/backend/filters/compositionProfile.cpp:1020
-#: ../src/backend/filters/spatialAnalysis.cpp:866
-msgid "Radius of cylinder"
+#: ../src/backend/filters/voxelise.cpp:796
+msgid "Normalise by"
+msgstr "Normalisieren mit"
+
+#: ../src/backend/filters/voxelise.cpp:799
+msgid "Method to use to normalise scalar value in each voxel"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:612
-msgid "Centre of axis aligned box"
+#: ../src/backend/filters/voxelise.cpp:802
+msgid "Computation"
 msgstr ""
 
-#: ../src/backend/filters/ionClip.cpp:617
-msgid "Corner offset"
-msgstr "Corner offset"
+#: ../src/backend/filters/voxelise.cpp:809
+#: ../src/backend/filters/spatialAnalysis.cpp:1233
+#: ../src/backend/filters/spatialAnalysis.cpp:1254
+msgid "Numerator"
+msgstr "Zähler"
 
-#: ../src/backend/filters/ionClip.cpp:620
-msgid "Vector to corner of box"
+#: ../src/backend/filters/voxelise.cpp:812
+msgid "Parmeter \"a\" used in fraction (a/b) to get voxel value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:82
-#: ../src/backend/filters/clusterAnalysis.cpp:1040
-msgid "Size Distribution"
-msgstr "Größenverteilung"
-
-#: ../src/backend/filters/clusterAnalysis.cpp:83
-msgid "Chemistry Distribution"
-msgstr "Chemische Verteilung"
+#: ../src/backend/filters/voxelise.cpp:829
+msgid "Enable this ion for numerator"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:493
-msgid "No range data. Can't cluster."
-msgstr "Keine Rangedaten. Clusteranalyse nicht möglich."
+#: ../src/backend/filters/voxelise.cpp:841
+#: ../src/backend/filters/voxelise.cpp:862
+#: ../src/backend/filters/spatialAnalysis.cpp:1261
+#: ../src/backend/filters/spatialAnalysis.cpp:1280
+msgid "Denominator"
+msgstr "Nenner"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:504
-msgid ""
-"No ranges selected for cluster \"core\". Cannot continue with clustering."
+#: ../src/backend/filters/voxelise.cpp:844
+msgid "Parameter \"b\" used in fraction (a/b) to get voxel value"
 msgstr ""
-"Kein Range für cluster \"core\" ausgewählt. Kann mit Clusteranalyse nicht "
-"weitermachen."
 
-#: ../src/backend/filters/clusterAnalysis.cpp:513
-msgid ""
-"No ranges selected for cluster \"bulk\". Cannot continue with clustering."
+#: ../src/backend/filters/voxelise.cpp:858
+msgid "Enable this ion for denominator contribution"
 msgstr ""
-"Kein Range für \"bulk\" ausgewählt. Kann mit Clusteranalyse nicht "
-"weitermachen."
 
-#: ../src/backend/filters/clusterAnalysis.cpp:679
-msgid "Morphology Plot"
-msgstr ""
+#: ../src/backend/filters/voxelise.cpp:880
+#: ../src/backend/filters/voxelise.cpp:911
+msgid "Filtering"
+msgstr "Filtern"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:680
-msgid "\\lambda_1:\\lambda_2 ratio"
+#: ../src/backend/filters/voxelise.cpp:884
+msgid "Smoothing method to use on voxels"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:681
-msgid "\\lambda_2:\\lambda_3 ratio"
+#: ../src/backend/filters/voxelise.cpp:887
+msgid "Processing"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:726
-msgid "No clusters had sufficient dimensionality to compute singular values"
+#: ../src/backend/filters/voxelise.cpp:893
+msgid "Standard Dev"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:784
-msgid "Found :"
-msgstr "Gefunden:"
-
-#: ../src/backend/filters/clusterAnalysis.cpp:786
-msgid " clusters"
-msgstr " Cluster"
+#: ../src/backend/filters/voxelise.cpp:897
+msgid "Filtering Scale"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:868
-msgid "Compositions (fractional, core+bulk)"
-msgstr "Zusammensetzungen (fractional, core+bulk)"
+#: ../src/backend/filters/voxelise.cpp:903
+msgid "Kernel Size"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:870
-msgid "Compositions (fractional, core only)"
-msgstr "Zusammensetzungen (fractional, core only)"
+#: ../src/backend/filters/voxelise.cpp:907
+msgid ""
+"Filter radius, in multiples of std. dev. Larger -> slower, more accurate"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:888
-msgid "Frequencies (core+bulk)"
-msgstr "Häufigkeiten (core+bulk)"
+#: ../src/backend/filters/voxelise.cpp:927
+msgid "Representation"
+msgstr "Representation"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:919
-msgid "Core Link + Erode"
-msgstr "Core Link + Erode"
+#: ../src/backend/filters/voxelise.cpp:930
+msgid "3D display method"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:923
-#: ../src/backend/filters/clusterAnalysis.cpp:931
-#: ../src/backend/filters/spatialAnalysis.cpp:605
-#: ../src/backend/filters/spatialAnalysis.cpp:613
-#: ../src/backend/filters/transform.cpp:1126
-#: ../src/backend/filters/ionInfo.cpp:546
-msgid "Algorithm"
-msgstr "Algorithmus"
+#: ../src/backend/filters/voxelise.cpp:941
+msgid "Spot size"
+msgstr "Spot size"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:927
-msgid "Cluster algorithm mode"
+#: ../src/backend/filters/voxelise.cpp:944
+msgid "Size of the spots to use for display"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:938
-msgid "Core Classify"
-msgstr ""
+#: ../src/backend/filters/voxelise.cpp:949
+#: ../src/backend/filters/voxelise.cpp:984
+#: ../src/backend/filters/voxelise.cpp:1056
+msgid "Transparency"
+msgstr "Transparenz"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:941
-msgid ""
-"Enable core-classifcation pre-step in clustering (Stephenson et al, 2007)"
+#: ../src/backend/filters/voxelise.cpp:952
+msgid "How \"see through\" each point is (0 - opaque, 1 - invisible)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:947
-msgid "Core Classify Dist"
-msgstr "Core Classify Dist"
-
-#: ../src/backend/filters/clusterAnalysis.cpp:950
-msgid "Restrict only atoms by distance to be cluster sources"
+#: ../src/backend/filters/voxelise.cpp:961
+msgid "Surf. param."
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:955
-msgid "Classify Knn Max"
-msgstr "Classify Knn Max"
+#: ../src/backend/filters/voxelise.cpp:964
+msgid "Isovalue"
+msgstr "Isovalue"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:958
-msgid ""
-"Require that the kth NN (this number) is within the classify distance, to be "
-"a cluster source"
+#: ../src/backend/filters/voxelise.cpp:967
+msgid "Scalar value to show as isosurface"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:964
-msgid "Core Link Dist"
-msgstr "Core Link Dist"
+#: ../src/backend/filters/voxelise.cpp:972
+#: ../src/backend/filters/voxelise.cpp:1037
+#: ../src/backend/filters/spatialAnalysis.cpp:2344
+#: ../src/backend/filters/spatialAnalysis.cpp:2397
+msgid "Surface"
+msgstr "Oberfläche"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:967
-msgid "Distance between clusters to allow linking"
+#: ../src/backend/filters/voxelise.cpp:979
+msgid "Colour of isosurface"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:972
-msgid "Bulk Link"
+#: ../src/backend/filters/voxelise.cpp:987
+#: ../src/backend/filters/voxelise.cpp:1059
+msgid "How \"see through\" each facet is (0 - opaque, 1 - invisible)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:975
-#: ../src/backend/filters/clusterAnalysis.cpp:993
-msgid "Enable  linking of non-cluster species - eg for composition analysis "
+#: ../src/backend/filters/voxelise.cpp:998
+msgid "Slice param."
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:982
-msgid "Bulk Link (Envelope) Dist"
-msgstr "Bulk Link (Envelope) Dist"
-
-#: ../src/backend/filters/clusterAnalysis.cpp:985
-msgid ""
-"Distance from core points that form cluster that is used to grab surrounding "
-"bulk points"
+#: ../src/backend/filters/voxelise.cpp:1006
+msgid "Slice Axis"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:990
-msgid "Erosion"
+#: ../src/backend/filters/voxelise.cpp:1009
+msgid "Normal for the planar slice"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:999
-msgid "Erode Dist"
-msgstr "Erode Dist"
-
-#: ../src/backend/filters/clusterAnalysis.cpp:1002
-msgid ""
-"Distance from unclustered material in which bulk points are eroded from "
-"cluster"
+#: ../src/backend/filters/voxelise.cpp:1016
+msgid "Slice Coord"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1008
-msgid "Clustering Params"
-msgstr "Cluster Parameter"
+#: ../src/backend/filters/voxelise.cpp:1019
+msgid "Fractional coordinate that slice plane passes through"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1013
-msgid "Size Cropping"
-msgstr "Größeneinschrankungen"
+#: ../src/backend/filters/voxelise.cpp:1024
+msgid "Interp. Mode"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1016
-msgid "Remove clusters based upon size distribution"
+#: ../src/backend/filters/voxelise.cpp:1032
+msgid "Interpolation mode for direction normal to slice"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1023
-msgid "Min Size"
-msgstr "Min Größe"
+#: ../src/backend/filters/voxelise.cpp:1048
+msgid "Colour mode"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1026
-msgid "Remove clusters below this size"
+#: ../src/backend/filters/voxelise.cpp:1051
+#: ../src/backend/filters/ionColour.cpp:261
+msgid "Colour scheme used to assign points colours by value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1031
-msgid "Max Size"
-msgstr "Max Größe"
+#: ../src/backend/filters/voxelise.cpp:1064
+#: ../src/backend/filters/ionColour.cpp:273
+msgid "Show Bar"
+msgstr "Zeige Balken"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1034
-msgid "Remove clusters above this size"
+#: ../src/backend/filters/voxelise.cpp:1071
+msgid "Auto Bounds"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1043
-msgid "Show number of clusters as a function of cluster size"
+#: ../src/backend/filters/voxelise.cpp:1072
+msgid "Auto-compute min/max values in map"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1049
-msgid "Log Scale"
-msgstr "Log. Skala"
+#: ../src/backend/filters/voxelise.cpp:1082
+#: ../src/backend/filters/ionColour.cpp:294
+msgid "Map start"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1052
-msgid "Use logarithmic scale for size distribution"
+#: ../src/backend/filters/voxelise.cpp:1083
+#: ../src/backend/filters/ionColour.cpp:295
+msgid "Assign points with this value to the first colour in map"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1059
-msgid "Morphology Dist."
+#: ../src/backend/filters/voxelise.cpp:1090
+#: ../src/backend/filters/ionColour.cpp:302
+msgid "Map end"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1062
-msgid "Create a plot showing cluster aspect ratio"
+#: ../src/backend/filters/voxelise.cpp:1091
+#: ../src/backend/filters/ionColour.cpp:303
+msgid "Assign points with this value to the last colour in map"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1068
-msgid "Cluster Id"
-msgstr ""
+#: ../src/backend/filters/transform.cpp:84
+msgid "Translate"
+msgstr "Translate"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1071
-msgid "Assign cluster output a unique per-cluster value (id)."
+#: ../src/backend/filters/transform.cpp:85
+msgid "Scale (isotropic)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1078
-msgid "Chemistry Dist."
-msgstr "Chemistry Dist."
-
-#: ../src/backend/filters/clusterAnalysis.cpp:1081
-msgid "Create a plot showing chemistry for each cluster size"
+#: ../src/backend/filters/transform.cpp:86
+msgid "Scale (anisotropic)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1088
-#: ../src/backend/filters/compositionProfile.cpp:1087
-#: ../src/backend/filters/spatialAnalysis.cpp:921
-#: ../src/backend/filters/ionInfo.cpp:462
-msgid "Normalise"
-msgstr "Normalisieren"
+#: ../src/backend/filters/transform.cpp:87
+msgid "Rotate"
+msgstr "Rotieren"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1091
-msgid "Convert cluster counts to composition"
+#: ../src/backend/filters/transform.cpp:88
+msgid "Value Shuffle"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1097
-msgid "Postprocess"
-msgstr "Postprozess"
-
-#: ../src/backend/filters/clusterAnalysis.cpp:1116
-msgid "If selected, use as \"core\" ion type (can make clusters)"
+#: ../src/backend/filters/transform.cpp:89
+msgid "Spatial Noise"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1121
-msgid "Core Ranges"
-msgstr "Core Ranges"
+#: ../src/backend/filters/transform.cpp:90
+msgid "Translate Value"
+msgstr "Translate Wert"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1135
-msgid ""
-"If selected, use as \"bulk\" ion type (can be included in existing clusters)"
+#: ../src/backend/filters/transform.cpp:91
+msgid "Crop Value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1140
-msgid "Bulk Ranges"
-msgstr "Bulk Ranges"
+#: ../src/backend/filters/transform.cpp:95
+msgid "Specify"
+msgstr "Angeben"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1156
-msgid "Max. Sep + Erode"
-msgstr "Max. Sep + Erode"
+#: ../src/backend/filters/transform.cpp:96
+msgid "Boundbox Centre"
+msgstr "Boundbox Zentrum"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1894
-msgid " --------------------------- Parameter selection notice ------------- "
-msgstr " --------------------------- Parameterauswahl Notiz ------------- "
+#: ../src/backend/filters/transform.cpp:97
+msgid "Mass Centre"
+msgstr "Massen-Zentrum"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1895
-msgid "You have specified a bulk distance larger than half your link distance."
+#: ../src/backend/filters/transform.cpp:1008
+#: ../src/backend/filters/clusterAnalysis.cpp:1956
+#: ../src/backend/filters/spatialAnalysis.cpp:635
+#: ../src/backend/filters/spatialAnalysis.cpp:2298
+#: ../src/backend/filters/spatialAnalysis.cpp:2727
+#: ../src/backend/filters/spatialAnalysis.cpp:3016
+#: ../src/backend/filters/spatialAnalysis.cpp:3689
+#: ../src/backend/filters/spatialAnalysis.cpp:3952
+#: ../src/backend/filters/spatialAnalysis.cpp:4165
+msgid "Collate"
+msgstr "Abgleichen"
+
+#: ../src/backend/filters/transform.cpp:1027
+msgid "Mass-to-Charge (Da/e)"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1896
-msgid ""
-"You can do this; thats OK, but the output is no longer independent of the "
-"computational process;"
+#: ../src/backend/filters/transform.cpp:1081
+msgid "Shuffle"
 msgstr ""
-"Sie könne das machen, das ist in Ordnung, aber die Ausgabe ist nicht länger "
-"unabhängig vom Berechnungsprozess"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1897
-msgid ""
-"This will be a problem in the case where two or more clusters can equally "
-"lay claim to a \"bulk\" ion. "
+#: ../src/backend/filters/transform.cpp:1105
+msgid "Splice"
 msgstr ""
-"Dies ist ein Problem wenn zwei oder mehrere Cluster auf dasselbe \"bulk\" "
-"Ion Anspruch erheben. "
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1898
-msgid ""
-" If your inter-cluster distance is sufficiently large (larger than your bulk "
-"linking distance), then you can get away with this."
+#: ../src/backend/filters/transform.cpp:1153
+msgid "Algorithm to use to transform point data"
 msgstr ""
-" If your inter-cluster distance is sufficiently large (larger than your bulk "
-"linking distance), then you can get away with this."
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1899
-msgid ""
-" In theory it is possible to \"join\" the clusters, but this has not been "
-"implemented for speed reasons."
+#: ../src/backend/filters/transform.cpp:1157
+#: ../src/backend/filters/ionInfo.cpp:546
+#: ../src/backend/filters/clusterAnalysis.cpp:943
+#: ../src/backend/filters/clusterAnalysis.cpp:951
+#: ../src/backend/filters/spatialAnalysis.cpp:800
+#: ../src/backend/filters/spatialAnalysis.cpp:808
+msgid "Algorithm"
+msgstr "Algorithmus"
+
+#: ../src/backend/filters/transform.cpp:1170
+msgid "Origin mode"
 msgstr ""
-"Theoretisch ist es möglich die Cluster zu 'verbinden', dies wurde jedoch aus "
-"Gescheindigkeitsgründen nicht implementiert."
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1900
-msgid ""
-"If you want this, please contact the author, or just use the source to add "
-"this in yourself."
+#: ../src/backend/filters/transform.cpp:1173
+msgid "Select how transform origin is computed"
 msgstr ""
-"Sollten Sie dies wollen, kontaktieren Sie den Autor oder verwenden Sie den "
-"Sourcecode um es selbst hinzuzufügen."
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1901
-msgid "---------------------------------------------------------------------- "
-msgstr "---------------------------------------------------------------------- "
+#: ../src/backend/filters/transform.cpp:1178
+msgid "Show marker"
+msgstr "Zeige Markierung"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1911
-#: ../src/backend/filters/spatialAnalysis.cpp:2060
-#: ../src/backend/filters/spatialAnalysis.cpp:2489
-#: ../src/backend/filters/spatialAnalysis.cpp:2775
-#: ../src/backend/filters/spatialAnalysis.cpp:3449
-#: ../src/backend/filters/transform.cpp:977
-msgid "Collate"
-msgstr "Abgleichen"
+#: ../src/backend/filters/transform.cpp:1182
+msgid "Display an interactive object to set transform origin"
+msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1930
-msgid "Build Core"
+#: ../src/backend/filters/transform.cpp:1184
+msgid "Display a small marker to denote transform origin"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:1958
-msgid "Core"
-msgstr "Kern"
+#: ../src/backend/filters/transform.cpp:1200
+msgid "Translation"
+msgstr "Translation"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2097
-msgid "Bulk"
+#: ../src/backend/filters/transform.cpp:1203
+msgid "Translation vector for transform"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2227
-msgid "Erode"
+#: ../src/backend/filters/transform.cpp:1215
+msgid "Offset"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2301
-msgid "Re-Collate"
+#: ../src/backend/filters/transform.cpp:1219
+msgid "Scalar to use to offset each point's associated value"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2358
-msgid "Classify Core"
+#: ../src/backend/filters/transform.cpp:1236
+#: ../src/backend/filters/transform.cpp:1263
+msgid "Origin of scale trasnform"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2449
-msgid "Build Bulk"
-msgstr ""
+#: ../src/backend/filters/transform.cpp:1243
+#: ../src/backend/filters/transform.cpp:1270
+msgid "Scale Fact."
+msgstr "Skalierungsfaktor"
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2694
-#: ../src/backend/filters/clusterAnalysis.cpp:2893
-msgid "Cluster Size"
+#: ../src/backend/filters/transform.cpp:1246
+#: ../src/backend/filters/transform.cpp:1273
+msgid "Enlargement factor for scaling around origin"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2695
-#: ../src/backend/filters/clusterAnalysis.cpp:2897
-msgid "Frequency"
+#: ../src/backend/filters/transform.cpp:1289
+msgid "Origin of rotation"
 msgstr ""
 
-#: ../src/backend/filters/clusterAnalysis.cpp:2895
-msgid "Composition"
+#: ../src/backend/filters/transform.cpp:1297
+msgid "Axis around which to revolve"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:111
-msgid "None (Raw count)"
-msgstr "Keine (Roh count)"
+#: ../src/backend/filters/transform.cpp:1302
+msgid "Angle (deg)"
+msgstr "Winkel (deg)"
 
-#: ../src/backend/filters/voxelise.cpp:112
-msgid "Volume (Density)"
-msgstr "Volumen (Dichte)"
+#: ../src/backend/filters/transform.cpp:1305
+msgid "Angle to perform rotation (ACW, as viewed from axis towards origin)"
+msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:113
-msgid "All Ions (conc)"
-msgstr "Alle Ionen (Konz)"
+#: ../src/backend/filters/transform.cpp:1322
+msgid "Noise Type"
+msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:114
-msgid "Ratio (Num/Denom)"
-msgstr "Verhältnis (Zähler/Nenner)"
+#: ../src/backend/filters/transform.cpp:1325
+msgid "Method to use to degrade point data"
+msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:118
-msgid "Point Cloud"
-msgstr "Punktwolke"
+#: ../src/backend/filters/transform.cpp:1332
+msgid "Noise level"
+msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:119
-msgid "Isosurface"
-msgstr "Isosurface"
+#: ../src/backend/filters/transform.cpp:1334
+msgid "Standard dev."
+msgstr "Standardabweichung"
 
-#: ../src/backend/filters/voxelise.cpp:120
-msgid "Axial slice"
+#: ../src/backend/filters/transform.cpp:1342
+msgid "Amplitude of noise"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:125
-msgid "Gaussian (blur)"
+#: ../src/backend/filters/transform.cpp:1356
+msgid "Min Value"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:126
-msgid "Lapl. of Gauss. (edges)"
+#: ../src/backend/filters/transform.cpp:1360
+msgid "Minimum value to use for crop"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:131
-msgid "Linear"
+#: ../src/backend/filters/transform.cpp:1364
+msgid "Max Value"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:564
-msgid "Voxel Limits (min,max): ("
-msgstr "Voxel Grenzen (min,max): ("
-
-#: ../src/backend/filters/voxelise.cpp:709
-msgid "Fixed width"
-msgstr "Fixe Breite"
-
-#: ../src/backend/filters/voxelise.cpp:713
-msgid "If true, use fixed size voxels, otherwise use fixed count"
+#: ../src/backend/filters/transform.cpp:1368
+msgid "Maximum value to use for crop"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:719
-msgid "Bin width x"
-msgstr "Bin-Breite x"
+#: ../src/backend/filters/transform.cpp:1377
+msgid "Transform Params"
+msgstr "Transformationsparameter"
 
-#: ../src/backend/filters/voxelise.cpp:723
-msgid "Voxel size in X direction"
+#: ../src/backend/filters/transform.cpp:1738
+msgid "White"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:727
-msgid "Bin width y"
-msgstr "Bin-Breite y"
+#: ../src/backend/filters/transform.cpp:1740
+msgid "Gaussian"
+msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:730
-msgid "Voxel size in Y direction"
+#: ../src/backend/filters/externalProgram.cpp:259
+msgid "Collate Input"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:736
-msgid "Bin width z"
-msgstr "Bin-Breite Z"
+#: ../src/backend/filters/externalProgram.cpp:348
+msgid "Execute"
+msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:739
-msgid "Voxel size in Z direction"
+#: ../src/backend/filters/externalProgram.cpp:389
+msgid "Collate output"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:746
-msgid "Num bins x"
-msgstr "Anzahl Bins x"
+#: ../src/backend/filters/externalProgram.cpp:564
+#: ../src/backend/filters/externalProgram.cpp:578
+msgid "Command"
+msgstr "Befehl"
 
-#: ../src/backend/filters/voxelise.cpp:750
-msgid "Number of voxels to use in X direction"
+#: ../src/backend/filters/externalProgram.cpp:567
+msgid ""
+"Full command to send to operating system. See manual for escape sequence "
+"meanings"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:755
-msgid "Num bins y"
-msgstr "Anzahl Bins y"
+#: ../src/backend/filters/externalProgram.cpp:571
+msgid "Work Dir"
+msgstr "Arbeitsverzeichnis"
 
-#: ../src/backend/filters/voxelise.cpp:758
-msgid "Number of voxels to use in Y direction"
+#: ../src/backend/filters/externalProgram.cpp:574
+msgid "Directory to run the command in"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:764
-msgid "Num bins z"
-msgstr "Anzahl Bins z"
+#: ../src/backend/filters/externalProgram.cpp:581
+msgid "Cleanup input"
+msgstr "Bereinige Eingabe"
 
-#: ../src/backend/filters/voxelise.cpp:766
-msgid "Number of voxels to use in Z direction"
+#: ../src/backend/filters/externalProgram.cpp:584
+msgid "Erase input files when command completed"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:796
-msgid "Normalise by"
-msgstr "Normalisieren mit"
+#: ../src/backend/filters/externalProgram.cpp:589
+msgid "Cache"
+msgstr "Zwischenspeicher"
 
-#: ../src/backend/filters/voxelise.cpp:799
-msgid "Method to use to normalise scalar value in each voxel"
+#: ../src/backend/filters/externalProgram.cpp:592
+msgid ""
+"Assume program does not alter its output, unless inputs from 3Depict are "
+"altered"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:802
-msgid "Computation"
+#: ../src/backend/filters/algorithms/mass.cpp:26
+msgid "Flat TOF"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:809
-msgid "Numerator"
-msgstr "Zähler"
-
-#: ../src/backend/filters/voxelise.cpp:812
-msgid "Parmeter \"a\" used in fraction (a/b) to get voxel value"
+#: ../src/backend/filters/algorithms/mass.cpp:33
+msgid "INsufficient bins to perform fit"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:829
-msgid "Enable this ion for numerator"
+#: ../src/backend/filters/algorithms/mass.cpp:34
+msgid "Insufficient counts to perform fit"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:841
-msgid "Denominator"
-msgstr "Nenner"
-
-#: ../src/backend/filters/voxelise.cpp:844
-msgid "Parameter \"b\" used in fraction (a/b) to get voxel value"
+#: ../src/backend/filters/algorithms/mass.cpp:35
+msgid "Insufficient data to perform fit"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:857
-msgid "Enable this ion for denominator contribution"
+#: ../src/backend/filters/algorithms/mass.cpp:36
+msgid "Data did not appear to be random noise - cannot fit noise level"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:879
-#: ../src/backend/filters/voxelise.cpp:910
-msgid "Filtering"
-msgstr "Filtern"
+#: ../src/backend/filters/ionInfo.cpp:37
+msgid "Rectilinear"
+msgstr "Geradlinig"
 
-#: ../src/backend/filters/voxelise.cpp:883
-msgid "Smoothing method to use on voxels"
-msgstr ""
+#: ../src/backend/filters/ionInfo.cpp:38
+msgid "Convex hull"
+msgstr "Konvexe Hülle"
 
-#: ../src/backend/filters/voxelise.cpp:886
-msgid "Processing"
+#: ../src/backend/filters/ionInfo.cpp:200
+msgid "No ions"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:892
-msgid "Standard Dev"
+#: ../src/backend/filters/ionInfo.cpp:226
+#: ../src/backend/filters/spectrumPlot.cpp:432
+msgid ""
+"Background fit failed - input data was considered ill formed (gauss-test)"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:896
-msgid "Filtering Scale"
+#: ../src/backend/filters/ionInfo.cpp:227
+msgid "Following data has not been corrected"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:902
-msgid "Kernel Size"
-msgstr ""
+#: ../src/backend/filters/ionInfo.cpp:279
+msgid "--Counts--"
+msgstr "- Anzahl -"
 
-#: ../src/backend/filters/voxelise.cpp:906
-msgid ""
-"Filter radius, in multiples of std. dev. Larger -> slower, more accurate"
-msgstr ""
+#: ../src/backend/filters/ionInfo.cpp:289
+msgid "Total Ranged\t"
+msgstr "Gesamt ranged\t"
 
-#: ../src/backend/filters/voxelise.cpp:926
-msgid "Representation"
-msgstr "Representation"
+#: ../src/backend/filters/ionInfo.cpp:294
+msgid "Total (incl. unranged)\t"
+msgstr "Total (inkl. nicht geranged)"
 
-#: ../src/backend/filters/voxelise.cpp:929
-msgid "3D display method"
+#: ../src/backend/filters/ionInfo.cpp:307
+msgid "n/a"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:940
-msgid "Spot size"
-msgstr "Spot size"
+#: ../src/backend/filters/ionInfo.cpp:317
+#: ../src/backend/filters/ionDownsample.cpp:496
+msgid "Unranged"
+msgstr "Nicht Geranged"
 
-#: ../src/backend/filters/voxelise.cpp:943
-msgid "Size of the spots to use for display"
-msgstr ""
+#: ../src/backend/filters/ionInfo.cpp:330
+msgid "Number of points : "
+msgstr "Anzahl der Punkte: "
 
-#: ../src/backend/filters/voxelise.cpp:948
-#: ../src/backend/filters/voxelise.cpp:983
-#: ../src/backend/filters/voxelise.cpp:1055
-msgid "Transparency"
-msgstr "Transparenz"
+#: ../src/backend/filters/ionInfo.cpp:359
+msgid "Rectilinear Bounds : "
+msgstr "Geradlinige Grenzen:"
 
-#: ../src/backend/filters/voxelise.cpp:951
-msgid "How \"see through\" each point is (0 - opaque, 1 - invisible)"
-msgstr ""
+#: ../src/backend/filters/ionInfo.cpp:364
+msgid "Volume (len^3): "
+msgstr "Volumen (Läng.^3)"
 
-#: ../src/backend/filters/voxelise.cpp:960
-msgid "Surf. param."
-msgstr ""
+#: ../src/backend/filters/ionInfo.cpp:381
+msgid "Convex Volume (len^3): "
+msgstr "Konvexes Volumen (Läng.^3)"
 
-#: ../src/backend/filters/voxelise.cpp:963
-msgid "Isovalue"
-msgstr "Isovalue"
+#: ../src/backend/filters/ionInfo.cpp:384
+msgid "Unable to compute volume"
+msgstr "Kann Volumen nicht berechnen"
 
-#: ../src/backend/filters/voxelise.cpp:966
-msgid "Scalar value to show as isosurface"
+#: ../src/backend/filters/ionInfo.cpp:413
+msgid "Ranged Density (pts/vol):"
+msgstr "Ranged Dichte (pts / vol):"
+
+#: ../src/backend/filters/ionInfo.cpp:418
+msgid "Total Density (pts/vol):"
+msgstr "Gesamtdichte (pts / vol):"
+
+#: ../src/backend/filters/ionInfo.cpp:445
+msgid "Compositions"
+msgstr "Zusammensetzungen"
+
+#: ../src/backend/filters/ionInfo.cpp:446
+msgid "Display compositional data for points in console"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:971
-#: ../src/backend/filters/voxelise.cpp:1036
-#: ../src/backend/filters/spatialAnalysis.cpp:2106
-#: ../src/backend/filters/spatialAnalysis.cpp:2159
-msgid "Surface"
-msgstr "Oberfläche"
+#: ../src/backend/filters/ionInfo.cpp:450
+msgid "Counts"
+msgstr "Anzahl"
 
-#: ../src/backend/filters/voxelise.cpp:978
-msgid "Colour of isosurface"
+#: ../src/backend/filters/ionInfo.cpp:451
+msgid "Display count data for points in console"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:986
-#: ../src/backend/filters/voxelise.cpp:1058
-msgid "How \"see through\" each facet is (0 - opaque, 1 - invisible)"
+#: ../src/backend/filters/ionInfo.cpp:458
+msgid "Ion data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:997
-msgid "Slice param."
+#: ../src/backend/filters/ionInfo.cpp:462
+#: ../src/backend/filters/profile.cpp:1107
+#: ../src/backend/filters/clusterAnalysis.cpp:1108
+#: ../src/backend/filters/spatialAnalysis.cpp:1116
+msgid "Normalise"
+msgstr "Normalisieren"
+
+#: ../src/backend/filters/ionInfo.cpp:466
+msgid "Normalise count data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1005
-msgid "Slice Axis"
+#: ../src/backend/filters/ionInfo.cpp:530
+msgid "Volume"
+msgstr "Volumen"
+
+#: ../src/backend/filters/ionInfo.cpp:533
+msgid "Compute volume for point data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1008
-msgid "Normal for the planar slice"
+#: ../src/backend/filters/ionInfo.cpp:549
+msgid "Select volume counting technique"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1015
-msgid "Slice Coord"
+#: ../src/backend/filters/ionInfo.cpp:562
+msgid "Volume data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1018
-msgid "Fractional coordinate that slice plane passes through"
+#: ../src/backend/filters/rangeFile.cpp:120
+#: ../src/backend/filters/rangeFile.h:96
+msgid "Ranging"
+msgstr "Ranging"
+
+#: ../src/backend/filters/rangeFile.cpp:560
+#: ../src/backend/filters/rangeFile.cpp:580
+#: ../src/backend/filters/dataLoad.cpp:484
+#: ../src/backend/filters/dataLoad.cpp:505
+msgid "File"
+msgstr "Datei"
+
+#: ../src/backend/filters/rangeFile.cpp:563
+msgid "File to use for range data"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1023
-msgid "Interp. Mode"
+#: ../src/backend/filters/rangeFile.cpp:573
+msgid "Drop unranged"
+msgstr "Nicht gerangete ausschalten"
+
+#: ../src/backend/filters/rangeFile.cpp:575
+msgid "Remove unranged points when generating output"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1031
-msgid "Interpolation mode for direction normal to slice"
+#: ../src/backend/filters/rangeFile.cpp:585
+msgid "Legend"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1047
-msgid "Colour mode"
+#: ../src/backend/filters/rangeFile.cpp:587
+msgid "Display colour legend for enabled ions"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1050
-#: ../src/backend/filters/ionColour.cpp:269
-msgid "Colour scheme used to assign points colours by value"
+#: ../src/backend/filters/rangeFile.cpp:591
+msgid "View"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1063
-#: ../src/backend/filters/ionColour.cpp:281
-msgid "Show Bar"
-msgstr "Zeige Balken"
+#: ../src/backend/filters/rangeFile.cpp:607
+msgid "All Ions"
+msgstr "Alle Ionen"
 
-#: ../src/backend/filters/voxelise.cpp:1070
-msgid "Auto Bounds"
+#: ../src/backend/filters/rangeFile.cpp:608
+msgid "Enable/disable all ions at once"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1071
-msgid "Auto-compute min/max values in map"
+#: ../src/backend/filters/rangeFile.cpp:616
+msgid "Species"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1081
-#: ../src/backend/filters/ionColour.cpp:302
-msgid "Map start"
-msgstr ""
+#: ../src/backend/filters/rangeFile.cpp:623
+msgid "IonID "
+msgstr "IonID "
 
-#: ../src/backend/filters/voxelise.cpp:1082
-#: ../src/backend/filters/ionColour.cpp:303
-msgid "Assign points with this value to the first colour in map"
+#: ../src/backend/filters/rangeFile.cpp:624
+msgid "Enable/disable specified ion"
 msgstr ""
 
-#: ../src/backend/filters/voxelise.cpp:1089
-#: ../src/backend/filters/ionColour.cpp:310
-msgid "Map end"
-msgstr ""
+#: ../src/backend/filters/rangeFile.cpp:634
+msgid "Active Ion "
+msgstr "Actives Ion "
 
-#: ../src/backend/filters/voxelise.cpp:1090
-#: ../src/backend/filters/ionColour.cpp:311
-msgid "Assign points with this value to the last colour in map"
+#: ../src/backend/filters/rangeFile.cpp:636
+msgid "If true, ion is used in output"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:265
-msgid "Colour Map"
-msgstr "Farbtabelle"
+#: ../src/backend/filters/rangeFile.cpp:646
+msgid "Colour "
+msgstr "Farbe"
 
-#: ../src/backend/filters/ionColour.cpp:273
-msgid "Reverse map"
+#: ../src/backend/filters/rangeFile.cpp:650
+msgid "Colour used to represent ion"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:274
-msgid "Reverse the colour scale"
+#: ../src/backend/filters/rangeFile.cpp:673
+msgid "All Ranges"
+msgstr "Alle Range"
+
+#: ../src/backend/filters/rangeFile.cpp:674
+msgid "Enable/disable all ranges"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:287
-msgid "Opacity"
+#: ../src/backend/filters/rangeFile.cpp:689
+msgid "Active Rng "
+msgstr "Activer Rng "
+
+#: ../src/backend/filters/rangeFile.cpp:692
+msgid ""
+"Enable/disable specified range (ion must also be enabled to activiate range)"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:294
-msgid "Num Colours"
+#: ../src/backend/filters/rangeFile.cpp:696
+msgid "Ion "
+msgstr "Ion "
+
+#: ../src/backend/filters/rangeFile.cpp:699
+msgid "Name of ion associate to this range"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:296
-msgid "Number of unique colours to use in colour map"
+#: ../src/backend/filters/rangeFile.cpp:708
+msgid "Start rng "
+msgstr "Start rng "
+
+#: ../src/backend/filters/rangeFile.cpp:711
+msgid "Start value for range"
 msgstr ""
 
-#: ../src/backend/filters/ionColour.cpp:417 ../src/backend/filter.cpp:172
-msgid "Aborted"
-msgstr "Abgebrochen"
+#: ../src/backend/filters/rangeFile.cpp:716
+msgid "End rng "
+msgstr "End rng "
 
-#: ../src/backend/filters/compositionProfile.cpp:51
+#: ../src/backend/filters/rangeFile.cpp:719
+msgid "Stopping value for range`"
+msgstr ""
+
+#: ../src/backend/filters/profile.cpp:51
 msgid "Cylinder (axial)"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:52
+#: ../src/backend/filters/profile.cpp:52
 msgid "Cylinder (radial)"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:591
+#: ../src/backend/filters/profile.cpp:591
 msgid "Distance"
 msgstr "Abstand"
 
-#: ../src/backend/filters/compositionProfile.cpp:599
+#: ../src/backend/filters/profile.cpp:599
 msgid "Fraction"
 msgstr "Anteil"
 
-#: ../src/backend/filters/compositionProfile.cpp:601
+#: ../src/backend/filters/profile.cpp:601
 msgid "Density (\\frac{\\#}{len^3})"
 msgstr "Dichte (\\frac{\\#}{len^3})"
 
-#: ../src/backend/filters/compositionProfile.cpp:628
+#: ../src/backend/filters/profile.cpp:628
 msgid "Freq. Profile"
 msgstr "Häufigkeitsprofil"
 
-#: ../src/backend/filters/compositionProfile.cpp:680
+#: ../src/backend/filters/profile.cpp:680
 msgid "No data remained in profile - cannot display result"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:965
+#: ../src/backend/filters/profile.cpp:967
+msgid "Total Density"
+msgstr ""
+
+#: ../src/backend/filters/profile.cpp:971
+msgid "Do not do per-species analysis, perform density computation only"
+msgstr ""
+
+#: ../src/backend/filters/profile.cpp:985
 msgid "Primitive type"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:969
+#: ../src/backend/filters/profile.cpp:989
 msgid "Basic shape to use for profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:981
+#: ../src/backend/filters/profile.cpp:1001
 msgid "Display the 3D composition profile interaction object"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:996
-#: ../src/backend/filters/spatialAnalysis.cpp:849
+#: ../src/backend/filters/profile.cpp:1016
+#: ../src/backend/filters/spatialAnalysis.cpp:1044
 msgid "Position for centre of cylinder"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1004
+#: ../src/backend/filters/profile.cpp:1024
 msgid "Vector between ends of cylinder"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1012
+#: ../src/backend/filters/profile.cpp:1032
 msgid "Prevent length of cylinder changing during interaction"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1055
+#: ../src/backend/filters/profile.cpp:1075
 msgid "Fixed Bin Num"
 msgstr "Fix. Bin-Anz."
 
-#: ../src/backend/filters/compositionProfile.cpp:1058
+#: ../src/backend/filters/profile.cpp:1078
 msgid ""
 "If true, use a fixed number of bins for profile, otherwise use fixed step "
 "size"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1065
-#: ../src/backend/filters/spatialAnalysis.cpp:690
-#: ../src/backend/filters/spatialAnalysis.cpp:826
+#: ../src/backend/filters/profile.cpp:1085
+#: ../src/backend/filters/spatialAnalysis.cpp:887
+#: ../src/backend/filters/spatialAnalysis.cpp:1021
 msgid "Num Bins"
 msgstr "Bin-Anz."
 
-#: ../src/backend/filters/compositionProfile.cpp:1070
+#: ../src/backend/filters/profile.cpp:1090
 msgid "Number of bins to use for profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1076
-#: ../src/backend/filters/spectrumPlot.cpp:572
+#: ../src/backend/filters/profile.cpp:1096
+#: ../src/backend/filters/spectrumPlot.cpp:580
 msgid "Bin width"
 msgstr "Bin-Breite"
 
-#: ../src/backend/filters/compositionProfile.cpp:1082
+#: ../src/backend/filters/profile.cpp:1102
 msgid "Size of each bin in profile"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1091
+#: ../src/backend/filters/profile.cpp:1111
 msgid "Convert bin counts into relative frequencies in each bin"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1095
+#: ../src/backend/filters/profile.cpp:1115
 msgid "Min. events"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1099
+#: ../src/backend/filters/profile.cpp:1119
 msgid "Drop data that does not have this many events"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1102
+#: ../src/backend/filters/profile.cpp:1122
 msgid "Settings"
 msgstr ""
 
-#: ../src/backend/filters/compositionProfile.cpp:1124
-#: ../src/backend/filters/spectrumPlot.cpp:661
+#: ../src/backend/filters/profile.cpp:1144
+#: ../src/backend/filters/spectrumPlot.cpp:669
 msgid "Plot Type"
 msgstr "Plot Type"
 
-#: ../src/backend/filters/compositionProfile.cpp:1127
-msgid "Visual style for plot"
-msgstr ""
-
-#: ../src/backend/filters/compositionProfile.cpp:1137
-msgid "Colour of plot"
-msgstr ""
-
-#: ../src/backend/filters/compositionProfile.cpp:1153
-msgid "Err. Estimator"
-msgstr "Fehlerschätzer"
-
-#: ../src/backend/filters/compositionProfile.cpp:1156
-msgid "Method of estimating error associated with each bin"
-msgstr ""
-
-#: ../src/backend/filters/compositionProfile.cpp:1163
-msgid "Avg. Window"
-msgstr ""
-
-#: ../src/backend/filters/compositionProfile.cpp:1166
-msgid "Number of bins to include in moving average filter"
-msgstr ""
-
-#: ../src/backend/filters/compositionProfile.cpp:1170
-msgid "Error analysis"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:111
-msgid "Local Density"
-msgstr "Lokale Dichte"
-
-#: ../src/backend/filters/spatialAnalysis.cpp:112
-msgid "Density Filtering"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:113
-msgid "Radial Distribution"
-msgstr "Radial Distribution"
-
-#: ../src/backend/filters/spatialAnalysis.cpp:114
-msgid "Axial Distribution"
-msgstr ""
-
-#: ../src/backend/filters/spatialAnalysis.cpp:115
-msgid "Binomial Distribution"
+#: ../src/backend/filters/profile.cpp:1147
+msgid "Visual style for plot"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:116
-msgid "Point Em/Replacement"
+#: ../src/backend/filters/profile.cpp:1158
+msgid "Colour of plot"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:120
-msgid "Neighbour Count"
-msgstr ""
+#: ../src/backend/filters/profile.cpp:1174
+msgid "Err. Estimator"
+msgstr "Fehlerschätzer"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:608
-msgid "Spatial analysis algorithm to use"
+#: ../src/backend/filters/profile.cpp:1177
+msgid "Method of estimating error associated with each bin"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:631
-msgid "Stop Mode"
+#: ../src/backend/filters/profile.cpp:1184
+msgid "Avg. Window"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:634
-msgid "Method to use to terminate algorithm when examining each point"
+#: ../src/backend/filters/profile.cpp:1187
+msgid "Number of bins to include in moving average filter"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:641
-msgid "NN Max"
-msgstr "NN Max"
-
-#: ../src/backend/filters/spatialAnalysis.cpp:644
-msgid "Maximum number of neighbours to examine"
+#: ../src/backend/filters/profile.cpp:1191
+msgid "Error analysis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:651
-msgid "Normalise bins"
+#: ../src/backend/filters/boundingBox.cpp:64
+msgid "Box only"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:654
-msgid ""
-"Normalise counts by binwidth. Needed when comparing NN histograms against "
-"one another"
+#: ../src/backend/filters/boundingBox.cpp:65
+msgid "Tick"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:660
-msgid "Show Random"
+#: ../src/backend/filters/boundingBox.cpp:66
+msgid "Dimension"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:663
-msgid "Show a fitted (density matched) theoretical distribution"
+#: ../src/backend/filters/boundingBox.cpp:571
+msgid "If true, show box, otherwise hide box"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:674
-msgid "Dist Max"
-msgstr "Abst. Max."
-
-#: ../src/backend/filters/spatialAnalysis.cpp:677
-msgid "Maximum distance from each point for search"
+#: ../src/backend/filters/boundingBox.cpp:584
+msgid "Style"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:693
-#: ../src/backend/filters/spatialAnalysis.cpp:829
-msgid "Number of bins for output 1D RDF plot"
+#: ../src/backend/filters/boundingBox.cpp:587
+msgid "Box display mode"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:699
-msgid "Surface Remove"
+#: ../src/backend/filters/boundingBox.cpp:590
+msgid "Display mode"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:702
+#: ../src/backend/filters/boundingBox.cpp:599
+msgid "Fixed Tick Num"
+msgstr "Fixed Tick Num"
+
+#: ../src/backend/filters/boundingBox.cpp:603
 msgid ""
-"Exclude surface as part of source to minimise bias in RDF (at cost of "
-"increased noise)"
+"If true, evenly use specified number of ticks. Otherwise, use distance to "
+"determine tick count"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:709
-msgid "Remove Dist"
-msgstr ""
+#: ../src/backend/filters/boundingBox.cpp:611
+msgid "Num X"
+msgstr "Num X"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:712
-msgid "Minimum distance to remove from surface"
+#: ../src/backend/filters/boundingBox.cpp:614
+msgid "Tick count in X direction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:720
-#: ../src/backend/filters/spatialAnalysis.cpp:834
-msgid "Plot colour "
-msgstr "Plotfarbe "
+#: ../src/backend/filters/boundingBox.cpp:619
+msgid "Num Y"
+msgstr "Num Y"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:723
-#: ../src/backend/filters/spatialAnalysis.cpp:837
-msgid "Colour of output plot"
+#: ../src/backend/filters/boundingBox.cpp:622
+msgid "Tick count in Y direction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:727
-#: ../src/backend/filters/spatialAnalysis.cpp:815
-#: ../src/backend/filters/spatialAnalysis.cpp:820
-#: ../src/backend/filters/spatialAnalysis.cpp:869
-#: ../src/backend/filters/spatialAnalysis.cpp:908
-msgid "Alg. Params."
+#: ../src/backend/filters/boundingBox.cpp:627
+msgid "Num Z"
+msgstr "Num Z"
+
+#: ../src/backend/filters/boundingBox.cpp:630
+msgid "Tick count in Z direction"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:740
-msgid "Source"
-msgstr "Quelle"
+#: ../src/backend/filters/boundingBox.cpp:636
+msgid "Spacing X"
+msgstr "X-Abstand"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:743
-msgid "Ions to use for initiating RDF search"
+#: ../src/backend/filters/boundingBox.cpp:640
+msgid "Distance between ticks on X axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:756
-msgid "Enable/disable ion as source"
-msgstr ""
+#: ../src/backend/filters/boundingBox.cpp:644
+msgid "Spacing Y"
+msgstr "Y-Abstand"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:762
-msgid "Source Ion"
+#: ../src/backend/filters/boundingBox.cpp:648
+msgid "Distance between ticks on Y axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:772
-msgid "Enable/disable all ions as target"
-msgstr ""
+#: ../src/backend/filters/boundingBox.cpp:652
+msgid "Spacing Z"
+msgstr "Z-Abstand"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:784
-msgid "Enable/disable this ion as target"
+#: ../src/backend/filters/boundingBox.cpp:656
+msgid "Distance between ticks on Z axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:789
-msgid "Target Ion"
+#: ../src/backend/filters/boundingBox.cpp:664
+msgid "Ticks X"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:799
-msgid "Cutoff"
+#: ../src/backend/filters/boundingBox.cpp:668
+msgid "Display tick marks on X axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:802
-msgid "Remove points with local density above/below this value"
+#: ../src/backend/filters/boundingBox.cpp:672
+msgid "Ticks Y"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:808
-msgid "Retain Upper"
+#: ../src/backend/filters/boundingBox.cpp:676
+msgid "Display tick marks on Y axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:811
-msgid "Retain either points with density above (enabled) or below cutoff"
+#: ../src/backend/filters/boundingBox.cpp:680
+msgid "Ticks Z"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:857
-msgid "Vector between centre and end of cylinder"
+#: ../src/backend/filters/boundingBox.cpp:684
+msgid "Display tick marks on Z axis"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:876
-#: ../src/backend/filters/spatialAnalysis.cpp:3587
-#: ../src/backend/filters/spatialAnalysis.cpp:3646
-msgid "Block size"
+#: ../src/backend/filters/boundingBox.cpp:687
+msgid "Tick marks"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:879
-msgid "Number of ions to use per block"
-msgstr ""
+#: ../src/backend/filters/boundingBox.cpp:694
+msgid "Box Colour"
+msgstr "Box Farbe"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:886
-msgid "Max Block Aspect"
+#: ../src/backend/filters/boundingBox.cpp:698
+msgid "Colour of the bounding box"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:889
-msgid ""
-"Maximum allowable block aspect ratio. Blocks above this aspect are "
-"discarded. Setting too high decreases correlation strength. Too low causes "
-"loss of statistical power."
+#: ../src/backend/filters/boundingBox.cpp:703
+msgid "Line thickness"
+msgstr "Linienbreite"
+
+#: ../src/backend/filters/boundingBox.cpp:707
+msgid "Thickness of the lines used to draw the box"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:900
-msgid "Extrusion Direction"
+#: ../src/backend/filters/boundingBox.cpp:718
+msgid "Relative size for text"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:903
-msgid "Direction in which blocks are extended during construction."
+#: ../src/backend/filters/boundingBox.cpp:723
+msgid "Abs. Coords"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:912
-msgid "Plot Counts"
+#: ../src/backend/filters/boundingBox.cpp:726
+msgid "Show labels using aboslute coo-ordinates"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:915
-msgid "Show the counts in the binomial histogram"
+#: ../src/backend/filters/ionDownsample.cpp:191
+msgid "Sampling"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:924
-msgid ""
-"Normalise the counts in the binomial histogram to a probability density "
-"function"
+#: ../src/backend/filters/ionDownsample.cpp:447
+msgid "By Count"
+msgstr "Nach Anzahl"
+
+#: ../src/backend/filters/ionDownsample.cpp:450
+msgid "Sample up to a fixed number of ions"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:938
-msgid "Display Grid"
+#: ../src/backend/filters/ionDownsample.cpp:456
+msgid "Per Species"
+msgstr "Nach Spezies"
+
+#: ../src/backend/filters/ionDownsample.cpp:460
+msgid "Use species specific (from ranging) sampling values"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:947
-msgid "View Options"
+#: ../src/backend/filters/ionDownsample.cpp:489
+msgid "Sampling value for species"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:953
-msgid "Data File"
+#: ../src/backend/filters/ionDownsample.cpp:505
+#: ../src/backend/filters/ionDownsample.cpp:529
+msgid "Sampling rates"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:957
-msgid "Pos file of points to subtract/replace/etc"
+#: ../src/backend/filters/ionDownsample.cpp:513
+msgid "Output Count"
+msgstr "Ausgabe Anzahl"
+
+#: ../src/backend/filters/ionDownsample.cpp:516
+msgid "Sample up to this value of points"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:962
-msgid "Match Tol."
+#: ../src/backend/filters/ionDownsample.cpp:521
+msgid "Out Fraction"
+msgstr "Ausgabe Anteil"
+
+#: ../src/backend/filters/ionDownsample.cpp:525
+msgid "Sample this fraction of points"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:965
-msgid "Tolerance to allow for matching"
+#: ../src/backend/filters/clusterAnalysis.cpp:84
+#: ../src/backend/filters/clusterAnalysis.cpp:1060
+msgid "Size Distribution"
+msgstr "Größenverteilung"
+
+#: ../src/backend/filters/clusterAnalysis.cpp:85
+msgid "Chemistry Distribution"
+msgstr "Chemische Verteilung"
+
+#: ../src/backend/filters/clusterAnalysis.cpp:503
+msgid "No range data. Can't cluster."
+msgstr "Keine Rangedaten. Clusteranalyse nicht möglich."
+
+#: ../src/backend/filters/clusterAnalysis.cpp:514
+msgid ""
+"No ranges selected for cluster \"core\". Cannot continue with clustering."
 msgstr ""
+"Kein Range für cluster \"core\" ausgewählt. Kann mit Clusteranalyse nicht "
+"weitermachen."
 
-#: ../src/backend/filters/spatialAnalysis.cpp:981
-msgid "Replacment condition"
+#: ../src/backend/filters/clusterAnalysis.cpp:523
+msgid ""
+"No ranges selected for cluster \"bulk\". Cannot continue with clustering."
 msgstr ""
+"Kein Range für \"bulk\" ausgewählt. Kann mit Clusteranalyse nicht "
+"weitermachen."
 
-#: ../src/backend/filters/spatialAnalysis.cpp:987
-msgid "Replace value"
+#: ../src/backend/filters/clusterAnalysis.cpp:689
+msgid "Morphology Plot"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:990
-msgid "Use value data from file when replacing ions"
+#: ../src/backend/filters/clusterAnalysis.cpp:690
+msgid "\\lambda_1:\\lambda_2 ratio"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:995
-msgid "Replacement"
+#: ../src/backend/filters/clusterAnalysis.cpp:691
+msgid "\\lambda_2:\\lambda_3 ratio"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2092
-#: ../src/backend/filters/spatialAnalysis.cpp:2145
-#: ../src/backend/filters/spatialAnalysis.cpp:2495
-#: ../src/backend/filters/spatialAnalysis.cpp:2781
-#: ../src/backend/filters/spatialAnalysis.cpp:3300
-msgid "Build"
+#: ../src/backend/filters/clusterAnalysis.cpp:736
+msgid "No clusters had sufficient dimensionality to compute singular values"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2199
-#: ../src/backend/filters/spatialAnalysis.cpp:2518
-#: ../src/backend/filters/spatialAnalysis.cpp:2805
-msgid "Analyse"
-msgstr "Analyse"
+#: ../src/backend/filters/clusterAnalysis.cpp:794
+msgid "Found :"
+msgstr "Gefunden:"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2278
-#: ../src/backend/filters/spatialAnalysis.cpp:2368
-#: ../src/backend/filters/spatialAnalysis.cpp:2434
-msgid "Radial Distance"
-msgstr "Radialer Abstand"
+#: ../src/backend/filters/clusterAnalysis.cpp:796
+msgid " clusters"
+msgstr " Cluster"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2280
-#: ../src/backend/filters/spatialAnalysis.cpp:2373
-msgid "Count/Distance"
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:888
+msgid "Compositions (fractional, core+bulk)"
+msgstr "Zusammensetzungen (fractional, core+bulk)"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2285
-#: ../src/backend/filters/spatialAnalysis.cpp:2378
-msgid "NN Freq."
-msgstr "NN Freq."
+#: ../src/backend/filters/clusterAnalysis.cpp:890
+msgid "Compositions (fractional, core only)"
+msgstr "Zusammensetzungen (fractional, core only)"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2425
-msgid "Warning, "
-msgstr "Warnung, "
+#: ../src/backend/filters/clusterAnalysis.cpp:908
+msgid "Frequencies (core+bulk)"
+msgstr "Häufigkeiten (core+bulk)"
+
+#: ../src/backend/filters/clusterAnalysis.cpp:939
+msgid "Core Link + Erode"
+msgstr "Core Link + Erode"
+
+#: ../src/backend/filters/clusterAnalysis.cpp:947
+msgid "Cluster algorithm mode"
+msgstr ""
+
+#: ../src/backend/filters/clusterAnalysis.cpp:958
+msgid "Core Classify"
+msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2426
+#: ../src/backend/filters/clusterAnalysis.cpp:961
 msgid ""
-" points were unable to find neighbour points that exceeded the search "
-"radius, and thus terminated prematurely"
+"Enable core-classifcation pre-step in clustering (Stephenson et al, 2007)"
 msgstr ""
-" Punkte konnten keine Nachbapunkte die den Suchradius überschritten finden "
-"und beendeten vorzeitig."
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2436
-msgid " RDF"
-msgstr " RDF"
+#: ../src/backend/filters/clusterAnalysis.cpp:967
+msgid "Core Classify Dist"
+msgstr "Core Classify Dist"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2714
-#: ../src/backend/filters/spatialAnalysis.cpp:3011
-msgid "Number Density (\\#/Vol^3)"
-msgstr "Number Density (\\#/Vol^3)"
+#: ../src/backend/filters/clusterAnalysis.cpp:970
+msgid "Restrict only atoms by distance to be cluster sources"
+msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2736
-#: ../src/backend/filters/spatialAnalysis.cpp:3031
-msgid "Warning,"
-msgstr "Warnung,"
+#: ../src/backend/filters/clusterAnalysis.cpp:975
+msgid "Classify Knn Max"
+msgstr "Classify Knn Max"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2737
-#: ../src/backend/filters/spatialAnalysis.cpp:3032
-msgid " points were un-analysable. These have been dropped"
-msgstr " points were un-analysable. These have been dropped"
+#: ../src/backend/filters/clusterAnalysis.cpp:978
+msgid ""
+"Require that the kth NN (this number) is within the classify distance, to be "
+"a cluster source"
+msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:2759
-#: ../src/backend/filters/spatialAnalysis.cpp:3054
-msgid "And so on..."
-msgstr "Und so weiter..."
+#: ../src/backend/filters/clusterAnalysis.cpp:984
+msgid "Core Link Dist"
+msgstr "Core Link Dist"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3136
-msgid "Extract"
+#: ../src/backend/filters/clusterAnalysis.cpp:987
+msgid "Distance between clusters to allow linking"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3209
-msgid "Reduce"
+#: ../src/backend/filters/clusterAnalysis.cpp:992
+msgid "Bulk Link"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3318
-msgid "Compute"
+#: ../src/backend/filters/clusterAnalysis.cpp:995
+#: ../src/backend/filters/clusterAnalysis.cpp:1012
+msgid "Enable  linking of non-cluster species - eg for composition analysis "
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3364
-msgid "Insufficient points to complete analysis"
+#: ../src/backend/filters/clusterAnalysis.cpp:1002
+msgid "Bulk Link (Envelope) Dist"
+msgstr "Bulk Link (Envelope) Dist"
+
+#: ../src/backend/filters/clusterAnalysis.cpp:1005
+msgid ""
+"Distance from core points that form cluster that is used to grab surrounding "
+"bulk points"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3387
-msgid "Axial Distance"
+#: ../src/backend/filters/clusterAnalysis.cpp:1009
+msgid "Erosion"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3389
-msgid " 1D Dist. Func."
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:1018
+msgid "Erode Dist"
+msgstr "Erode Dist"
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3458
-msgid "Binomial"
+#: ../src/backend/filters/clusterAnalysis.cpp:1021
+msgid ""
+"Distance from unclustered material in which bulk points are eroded from "
+"cluster"
 msgstr ""
 
-#: ../src/backend/filters/spatialAnalysis.cpp:3589
-#: ../src/backend/filters/spatialAnalysis.cpp:3648
-msgid "Rel. Frequency"
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:1028
+msgid "Clustering Params"
+msgstr "Cluster Parameter"
 
-#: ../src/backend/filters/transform.cpp:81
-msgid "Translate"
-msgstr "Translate"
+#: ../src/backend/filters/clusterAnalysis.cpp:1033
+msgid "Size Cropping"
+msgstr "Größeneinschrankungen"
 
-#: ../src/backend/filters/transform.cpp:82
-msgid "Scale (isotropic)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1036
+msgid "Remove clusters based upon size distribution"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:83
-msgid "Scale (anisotropic)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1043
+msgid "Min Size"
+msgstr "Min Größe"
+
+#: ../src/backend/filters/clusterAnalysis.cpp:1046
+msgid "Remove clusters below this size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:84
-msgid "Rotate"
-msgstr "Rotieren"
+#: ../src/backend/filters/clusterAnalysis.cpp:1051
+msgid "Max Size"
+msgstr "Max Größe"
 
-#: ../src/backend/filters/transform.cpp:85
-msgid "Value Shuffle"
+#: ../src/backend/filters/clusterAnalysis.cpp:1054
+msgid "Remove clusters above this size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:86
-msgid "Spatial Noise"
+#: ../src/backend/filters/clusterAnalysis.cpp:1063
+msgid "Show number of clusters as a function of cluster size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:87
-msgid "Translate Value"
-msgstr "Translate Wert"
-
-#: ../src/backend/filters/transform.cpp:91
-msgid "Specify"
-msgstr "Angeben"
-
-#: ../src/backend/filters/transform.cpp:92
-msgid "Boundbox Centre"
-msgstr "Boundbox Zentrum"
-
-#: ../src/backend/filters/transform.cpp:93
-msgid "Mass Centre"
-msgstr "Massen-Zentrum"
-
-#: ../src/backend/filters/transform.cpp:996
-msgid "Mass-to-Charge (amu/e)"
-msgstr "Masse-zu-Ladung (amu/e)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1069
+msgid "Log Scale"
+msgstr "Log. Skala"
 
-#: ../src/backend/filters/transform.cpp:1050
-msgid "Shuffle"
+#: ../src/backend/filters/clusterAnalysis.cpp:1072
+msgid "Use logarithmic scale for size distribution"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1074
-msgid "Splice"
+#: ../src/backend/filters/clusterAnalysis.cpp:1079
+msgid "Morphology Dist."
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1122
-msgid "Algorithm to use to transform point data"
+#: ../src/backend/filters/clusterAnalysis.cpp:1082
+msgid "Create a plot showing cluster aspect ratio"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1139
-msgid "Origin mode"
+#: ../src/backend/filters/clusterAnalysis.cpp:1088
+msgid "Cluster Id"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1142
-msgid "Select how transform origin is computed"
+#: ../src/backend/filters/clusterAnalysis.cpp:1091
+msgid "Assign cluster output a unique per-cluster value (id)."
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1147
-msgid "Show marker"
-msgstr "Zeige Markierung"
+#: ../src/backend/filters/clusterAnalysis.cpp:1098
+msgid "Chemistry Dist."
+msgstr "Chemistry Dist."
 
-#: ../src/backend/filters/transform.cpp:1151
-msgid "Display an interactive object to set transform origin"
+#: ../src/backend/filters/clusterAnalysis.cpp:1101
+msgid "Create a plot showing chemistry for each cluster size"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1153
-msgid "Display a small marker to denote transform origin"
+#: ../src/backend/filters/clusterAnalysis.cpp:1111
+msgid "Convert cluster counts to composition"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1169
-msgid "Translation"
-msgstr "Translation"
+#: ../src/backend/filters/clusterAnalysis.cpp:1117
+msgid "Postprocess"
+msgstr "Postprozess"
 
-#: ../src/backend/filters/transform.cpp:1172
-msgid "Translation vector for transform"
+#: ../src/backend/filters/clusterAnalysis.cpp:1136
+msgid "If selected, use as \"core\" ion type (can make clusters)"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1184
-msgid "Offset"
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:1141
+msgid "Core Ranges"
+msgstr "Core Ranges"
 
-#: ../src/backend/filters/transform.cpp:1188
-msgid "Scalar to use to offset each point's associated value"
+#: ../src/backend/filters/clusterAnalysis.cpp:1147
+msgid "Enable/Disable All"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1205
-#: ../src/backend/filters/transform.cpp:1232
-msgid "Origin of scale trasnform"
+#: ../src/backend/filters/clusterAnalysis.cpp:1152
+msgid "Enable/disable all ions"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1212
-#: ../src/backend/filters/transform.cpp:1239
-msgid "Scale Fact."
-msgstr "Skalierungsfaktor"
-
-#: ../src/backend/filters/transform.cpp:1215
-#: ../src/backend/filters/transform.cpp:1242
-msgid "Enlargement factor for scaling around origin"
+#: ../src/backend/filters/clusterAnalysis.cpp:1165
+msgid ""
+"If selected, use as \"bulk\" ion type (can be included in existing clusters)"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1258
-msgid "Origin of rotation"
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:1170
+msgid "Bulk Ranges"
+msgstr "Bulk Ranges"
 
-#: ../src/backend/filters/transform.cpp:1266
-msgid "Axis around which to revolve"
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:1186
+msgid "Max. Sep + Erode"
+msgstr "Max. Sep + Erode"
 
-#: ../src/backend/filters/transform.cpp:1271
-msgid "Angle (deg)"
-msgstr "Winkel (deg)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1939
+msgid " --------------------------- Parameter selection notice ------------- "
+msgstr " --------------------------- Parameterauswahl Notiz ------------- "
 
-#: ../src/backend/filters/transform.cpp:1274
-msgid "Angle to perform rotation (ACW, as viewed from axis towards origin)"
+#: ../src/backend/filters/clusterAnalysis.cpp:1940
+msgid "You have specified a bulk distance larger than half your link distance."
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1291
-msgid "Noise Type"
+#: ../src/backend/filters/clusterAnalysis.cpp:1941
+msgid ""
+"You can do this; thats OK, but the output is no longer independent of the "
+"computational process;"
 msgstr ""
+"Sie könne das machen, das ist in Ordnung, aber die Ausgabe ist nicht länger "
+"unabhängig vom Berechnungsprozess"
 
-#: ../src/backend/filters/transform.cpp:1294
-msgid "Method to use to degrade point data"
+#: ../src/backend/filters/clusterAnalysis.cpp:1942
+msgid ""
+"This will be a problem in the case where two or more clusters can equally "
+"lay claim to a \"bulk\" ion. "
 msgstr ""
+"Dies ist ein Problem wenn zwei oder mehrere Cluster auf dasselbe \"bulk\" "
+"Ion Anspruch erheben. "
 
-#: ../src/backend/filters/transform.cpp:1301
-msgid "Noise level"
+#: ../src/backend/filters/clusterAnalysis.cpp:1943
+msgid ""
+" If your inter-cluster distance is sufficiently large (larger than your bulk "
+"linking distance), then you can get away with this."
 msgstr ""
+" If your inter-cluster distance is sufficiently large (larger than your bulk "
+"linking distance), then you can get away with this."
 
-#: ../src/backend/filters/transform.cpp:1303
-msgid "Standard dev."
-msgstr "Standardabweichung"
+#: ../src/backend/filters/clusterAnalysis.cpp:1944
+msgid ""
+" In theory it is possible to \"join\" the clusters, but this has not been "
+"implemented for speed reasons."
+msgstr ""
+"Theoretisch ist es möglich die Cluster zu 'verbinden', dies wurde jedoch aus "
+"Gescheindigkeitsgründen nicht implementiert."
 
-#: ../src/backend/filters/transform.cpp:1311
-msgid "Amplitude of noise"
+#: ../src/backend/filters/clusterAnalysis.cpp:1945
+msgid ""
+"If you want this, please contact the author, or just use the source to add "
+"this in yourself."
 msgstr ""
+"Sollten Sie dies wollen, kontaktieren Sie den Autor oder verwenden Sie den "
+"Sourcecode um es selbst hinzuzufügen."
 
-#: ../src/backend/filters/transform.cpp:1323
-msgid "Transform Params"
-msgstr "Transformationsparameter"
+#: ../src/backend/filters/clusterAnalysis.cpp:1946
+msgid "---------------------------------------------------------------------- "
+msgstr "---------------------------------------------------------------------- "
 
-#: ../src/backend/filters/transform.cpp:1660
-msgid "White"
+#: ../src/backend/filters/clusterAnalysis.cpp:1975
+msgid "Build Core"
 msgstr ""
 
-#: ../src/backend/filters/transform.cpp:1662
-msgid "Gaussian"
-msgstr ""
+#: ../src/backend/filters/clusterAnalysis.cpp:2003
+msgid "Core"
+msgstr "Kern"
 
-#: ../src/backend/filters/boundingBox.cpp:60
-msgid "Box only"
+#: ../src/backend/filters/clusterAnalysis.cpp:2126
+msgid "Bulk"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:61
-msgid "Tick"
+#: ../src/backend/filters/clusterAnalysis.cpp:2204
+msgid "Erode"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:62
-msgid "Dimension"
+#: ../src/backend/filters/clusterAnalysis.cpp:2282
+msgid "Re-Collate"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:531
-msgid "If true, show box, otherwise hide box"
+#: ../src/backend/filters/clusterAnalysis.cpp:2337
+msgid "Classify Core"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:544
-msgid "Style"
+#: ../src/backend/filters/clusterAnalysis.cpp:2428
+msgid "Build Bulk"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:547
-msgid "Box display mode"
+#: ../src/backend/filters/clusterAnalysis.cpp:2676
+#: ../src/backend/filters/clusterAnalysis.cpp:2879
+msgid "Cluster Size"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:550
-msgid "Display mode"
+#: ../src/backend/filters/clusterAnalysis.cpp:2677
+#: ../src/backend/filters/clusterAnalysis.cpp:2883
+msgid "Frequency"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:559
-msgid "Fixed Tick Num"
-msgstr "Fixed Tick Num"
-
-#: ../src/backend/filters/boundingBox.cpp:563
-msgid ""
-"If true, evenly use specified number of ticks. Otherwise, use distance to "
-"determine tick count"
+#: ../src/backend/filters/clusterAnalysis.cpp:2881
+msgid "Composition"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:571
-msgid "Num X"
-msgstr "Num X"
+#: ../src/backend/filters/spatialAnalysis.cpp:123
+msgid "Local Density"
+msgstr "Lokale Dichte"
 
-#: ../src/backend/filters/boundingBox.cpp:574
-msgid "Tick count in X direction"
+#: ../src/backend/filters/spatialAnalysis.cpp:124
+msgid "Density Filtering"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:579
-msgid "Num Y"
-msgstr "Num Y"
+#: ../src/backend/filters/spatialAnalysis.cpp:125
+msgid "Radial Distribution"
+msgstr "Radial Distribution"
 
-#: ../src/backend/filters/boundingBox.cpp:582
-msgid "Tick count in Y direction"
+#: ../src/backend/filters/spatialAnalysis.cpp:126
+msgid "Axial Distribution"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:587
-msgid "Num Z"
-msgstr "Num Z"
-
-#: ../src/backend/filters/boundingBox.cpp:590
-msgid "Tick count in Z direction"
+#: ../src/backend/filters/spatialAnalysis.cpp:127
+msgid "Binomial Distribution"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:596
-msgid "Spacing X"
-msgstr "X-Abstand"
-
-#: ../src/backend/filters/boundingBox.cpp:600
-msgid "Distance between ticks on X axis"
+#: ../src/backend/filters/spatialAnalysis.cpp:128
+msgid "Point Em/Replacement"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:604
-msgid "Spacing Y"
-msgstr "Y-Abstand"
-
-#: ../src/backend/filters/boundingBox.cpp:608
-msgid "Distance between ticks on Y axis"
+#: ../src/backend/filters/spatialAnalysis.cpp:129
+msgid "Local Concentration"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:612
-msgid "Spacing Z"
-msgstr "Z-Abstand"
-
-#: ../src/backend/filters/boundingBox.cpp:616
-msgid "Distance between ticks on Z axis"
+#: ../src/backend/filters/spatialAnalysis.cpp:133
+msgid "Neighbour Count"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:619
-msgid "Tick marks"
+#: ../src/backend/filters/spatialAnalysis.cpp:643
+msgid "Load"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:626
-msgid "Box Colour"
-msgstr "Box Farbe"
-
-#: ../src/backend/filters/boundingBox.cpp:630
-msgid "Colour of the bounding box"
+#: ../src/backend/filters/spatialAnalysis.cpp:660
+#: ../src/backend/filters/spatialAnalysis.cpp:2330
+#: ../src/backend/filters/spatialAnalysis.cpp:2383
+#: ../src/backend/filters/spatialAnalysis.cpp:2733
+#: ../src/backend/filters/spatialAnalysis.cpp:3022
+#: ../src/backend/filters/spatialAnalysis.cpp:3540
+#: ../src/backend/filters/spatialAnalysis.cpp:4184
+msgid "Build"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:635
-msgid "Line thickness"
-msgstr "Linienbreite"
-
-#: ../src/backend/filters/boundingBox.cpp:639
-msgid "Thickness of the lines used to draw the box"
+#: ../src/backend/filters/spatialAnalysis.cpp:705
+#: ../src/backend/filters/spatialAnalysis.cpp:3558
+#: ../src/backend/filters/spatialAnalysis.cpp:4073
+#: ../src/backend/filters/spatialAnalysis.cpp:4201
+msgid "Compute"
 msgstr ""
 
-#: ../src/backend/filters/boundingBox.cpp:647
-#: ../src/backend/filters/annotation.cpp:848
-msgid "Font Size"
-msgstr "Schriftgröße"
-
-#: ../src/backend/filters/boundingBox.cpp:650
-msgid "Relative size for text"
+#: ../src/backend/filters/spatialAnalysis.cpp:803
+msgid "Spatial analysis algorithm to use"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:73
-msgid "Arrow"
-msgstr "Pfeil"
-
-#: ../src/backend/filters/annotation.cpp:74
-msgid "Text"
-msgstr "Text"
-
-#: ../src/backend/filters/annotation.cpp:75
-msgid "Arrow+Text"
-msgstr "Pfeil+Text"
-
-#: ../src/backend/filters/annotation.cpp:76
-msgid "Angle"
-msgstr "Winkel"
-
-#: ../src/backend/filters/annotation.cpp:77
-msgid "Ruler"
-msgstr "Lineal"
-
-#: ../src/backend/filters/annotation.cpp:524
-msgid "Enable"
+#: ../src/backend/filters/spatialAnalysis.cpp:827
+#: ../src/backend/filters/spatialAnalysis.cpp:878
+msgid "Stop Mode"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:527
-msgid "Enable/disable annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:830
+msgid "Method to use to terminate algorithm when examining each point"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:548
-msgid "Type or style of annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:837
+msgid "NN Max"
+msgstr "NN Max"
+
+#: ../src/backend/filters/spatialAnalysis.cpp:840
+msgid "Maximum number of neighbours to examine"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:564
-#: ../src/backend/filters/annotation.cpp:668
-msgid "Text of annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:847
+msgid "Normalise bins"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:572
-msgid "Position of annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:850
+msgid ""
+"Normalise counts by binwidth. Needed when comparing NN histograms against "
+"one another"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:576
-#: ../src/backend/filters/annotation.cpp:683
-#: ../src/backend/filters/annotation.cpp:742
-#: ../src/backend/filters/annotation.cpp:831
-msgid "Up dir"
-msgstr "Up dir"
-
-#: ../src/backend/filters/annotation.cpp:580
-#: ../src/backend/filters/annotation.cpp:835
-msgid "Vector for up direction of annotation text"
+#: ../src/backend/filters/spatialAnalysis.cpp:856
+msgid "Show Random"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:584
-#: ../src/backend/filters/annotation.cpp:690
-#: ../src/backend/filters/annotation.cpp:734
-#: ../src/backend/filters/annotation.cpp:839
-msgid "Across dir"
-msgstr "Across dir"
-
-#: ../src/backend/filters/annotation.cpp:588
-#: ../src/backend/filters/annotation.cpp:843
-msgid "Reading direction for annotation"
+#: ../src/backend/filters/spatialAnalysis.cpp:859
+msgid "Show a fitted (density matched) theoretical distribution"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:593
-#: ../src/backend/filters/annotation.cpp:675
-#: ../src/backend/filters/annotation.cpp:769
-msgid "Text size"
-msgstr "Textgröße"
+#: ../src/backend/filters/spatialAnalysis.cpp:870
+msgid "Dist Max"
+msgstr "Abst. Max."
 
-#: ../src/backend/filters/annotation.cpp:597
-#: ../src/backend/filters/annotation.cpp:679
-#: ../src/backend/filters/annotation.cpp:851
-msgid "Relative size of annotation text"
+#: ../src/backend/filters/spatialAnalysis.cpp:873
+msgid "Maximum distance from each point for search"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:609
-#: ../src/backend/filters/annotation.cpp:650
-msgid "3D position for tail of arrow"
+#: ../src/backend/filters/spatialAnalysis.cpp:890
+#: ../src/backend/filters/spatialAnalysis.cpp:1024
+msgid "Number of bins for output 1D RDF plot"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:617
-#: ../src/backend/filters/annotation.cpp:659
-msgid "3D Position to which arrow points"
+#: ../src/backend/filters/spatialAnalysis.cpp:896
+msgid "Surface Remove"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:620
-#: ../src/backend/filters/annotation.cpp:730
-msgid "Positioning"
+#: ../src/backend/filters/spatialAnalysis.cpp:899
+msgid ""
+"Exclude surface as part of source to minimise bias in RDF (at cost of "
+"increased noise)"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:625
-#: ../src/backend/filters/annotation.cpp:697
-msgid "Tip radius"
+#: ../src/backend/filters/spatialAnalysis.cpp:906
+msgid "Remove Dist"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:629
-msgid "Size of the arrow head"
+#: ../src/backend/filters/spatialAnalysis.cpp:909
+msgid "Minimum distance to remove from surface"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:633
-msgid "Line size"
+#: ../src/backend/filters/spatialAnalysis.cpp:917
+#: ../src/backend/filters/spatialAnalysis.cpp:1029
+msgid "Plot colour "
+msgstr "Plotfarbe "
+
+#: ../src/backend/filters/spatialAnalysis.cpp:920
+#: ../src/backend/filters/spatialAnalysis.cpp:1032
+msgid "Colour of output plot"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:637
-msgid "Thickness of line used to draw arrow stem"
+#: ../src/backend/filters/spatialAnalysis.cpp:924
+#: ../src/backend/filters/spatialAnalysis.cpp:1010
+#: ../src/backend/filters/spatialAnalysis.cpp:1015
+#: ../src/backend/filters/spatialAnalysis.cpp:1064
+#: ../src/backend/filters/spatialAnalysis.cpp:1103
+msgid "Alg. Params."
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:671
-msgid "Options"
+#: ../src/backend/filters/spatialAnalysis.cpp:937
+#: ../src/backend/filters/spatialAnalysis.cpp:1207
+msgid "Source"
+msgstr "Quelle"
+
+#: ../src/backend/filters/spatialAnalysis.cpp:940
+msgid "Ions to use for initiating RDF search"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:707
-msgid "Position A"
-msgstr "Position A"
+#: ../src/backend/filters/spatialAnalysis.cpp:953
+#: ../src/backend/filters/spatialAnalysis.cpp:1223
+#: ../src/backend/filters/spatialAnalysis.cpp:1249
+msgid "Enable/disable ion as source"
+msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:711
-msgid "Location of first non-central vertex"
+#: ../src/backend/filters/spatialAnalysis.cpp:958
+#: ../src/backend/filters/spatialAnalysis.cpp:1228
+msgid "Source Ion"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:715
-msgid "Origin "
-msgstr "Ursprung "
+#: ../src/backend/filters/spatialAnalysis.cpp:965 ../src/gl/cameras.cpp:611
+msgid "Target"
+msgstr "Ziel"
 
-#: ../src/backend/filters/annotation.cpp:719
-msgid "Location of central vertex"
+#: ../src/backend/filters/spatialAnalysis.cpp:968
+#: ../src/backend/filters/spatialAnalysis.cpp:1264
+msgid "Enable/disable all ions as target"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:723
-msgid "Position B"
-msgstr "Position B"
+#: ../src/backend/filters/spatialAnalysis.cpp:980
+#: ../src/backend/filters/spatialAnalysis.cpp:1276
+msgid "Enable/disable this ion as target"
+msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:727
-msgid "Location of second non-central vertex"
+#: ../src/backend/filters/spatialAnalysis.cpp:984
+msgid "Target Ion"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:738
-msgid "Reading direction for angle text"
+#: ../src/backend/filters/spatialAnalysis.cpp:994
+msgid "Cutoff"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:743
-msgid "Vector for up direction of angle text"
+#: ../src/backend/filters/spatialAnalysis.cpp:997
+msgid "Remove points with local density above/below this value"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:751
-msgid "Reflexive"
-msgstr "Reflexive"
+#: ../src/backend/filters/spatialAnalysis.cpp:1003
+msgid "Retain Upper"
+msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:754
-msgid "Measure interor (enabled) or exterior angle (disabled)"
+#: ../src/backend/filters/spatialAnalysis.cpp:1006
+msgid "Retain either points with density above (enabled) or below cutoff"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:759
-msgid "Show Angle"
-msgstr "Zeige Winkel"
+#: ../src/backend/filters/spatialAnalysis.cpp:1052
+msgid "Vector between centre and end of cylinder"
+msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:763
-msgid "Display angle text (when enabled)"
+#: ../src/backend/filters/spatialAnalysis.cpp:1071
+#: ../src/backend/filters/spatialAnalysis.cpp:3827
+#: ../src/backend/filters/spatialAnalysis.cpp:3886
+msgid "Block size"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:773
-msgid "Size of angle text"
+#: ../src/backend/filters/spatialAnalysis.cpp:1074
+msgid "Number of ions to use per block"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:791
-msgid "Digit format"
-msgstr "Zahlenformat"
+#: ../src/backend/filters/spatialAnalysis.cpp:1081
+msgid "Max Block Aspect"
+msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:795
+#: ../src/backend/filters/spatialAnalysis.cpp:1084
 msgid ""
-"Format of angle text; # for numeral position, '.' for separator, eg ##.## "
-"gives 12.34"
+"Maximum allowable block aspect ratio. Blocks above this aspect are "
+"discarded. Setting too high decreases correlation strength. Too low causes "
+"loss of statistical power."
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:801
-#: ../src/backend/filters/annotation.cpp:886
-msgid "Sphere size"
-msgstr "Kugelgröße"
-
-#: ../src/backend/filters/annotation.cpp:805
-#: ../src/backend/filters/annotation.cpp:890
-msgid "Marker sphere size for manipulating tool"
+#: ../src/backend/filters/spatialAnalysis.cpp:1095
+msgid "Extrusion Direction"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:819
-msgid "Ruler beginning 3D location"
+#: ../src/backend/filters/spatialAnalysis.cpp:1098
+msgid "Direction in which blocks are extended during construction."
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:827
-msgid "Ruler finish 3D location"
+#: ../src/backend/filters/spatialAnalysis.cpp:1107
+msgid "Plot Counts"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:857
-msgid "Fixed ticks"
-msgstr "Fixe Marker"
+#: ../src/backend/filters/spatialAnalysis.cpp:1110
+msgid "Show the counts in the binomial histogram"
+msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:860
+#: ../src/backend/filters/spatialAnalysis.cpp:1119
 msgid ""
-"Use fixed (enabled) number of text markers, or one every fixed distance "
-"(disabled)"
+"Normalise the counts in the binomial histogram to a probability density "
+"function"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:867
-msgid "Num Ticks"
-msgstr "Anzahl Marker"
-
-#: ../src/backend/filters/annotation.cpp:870
-msgid "Number of tick marks along ruler"
+#: ../src/backend/filters/spatialAnalysis.cpp:1133
+msgid "Display Grid"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:877
-msgid "Tick Spacing"
-msgstr "Markerabstand"
-
-#: ../src/backend/filters/annotation.cpp:880
-msgid "Distance between tick marks along ruler"
+#: ../src/backend/filters/spatialAnalysis.cpp:1142
+msgid "View Options"
 msgstr ""
 
-#: ../src/backend/filters/annotation.cpp:904
-msgid "Colour for ruler and ticks"
+#: ../src/backend/filters/spatialAnalysis.cpp:1148
+msgid "Data File"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:191
-msgid "Sampling"
+#: ../src/backend/filters/spatialAnalysis.cpp:1152
+msgid "Pos file of points to subtract/replace/etc"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:447
-msgid "By Count"
-msgstr "Nach Anzahl"
+#: ../src/backend/filters/spatialAnalysis.cpp:1157
+msgid "Match Tol."
+msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:450
-msgid "Sample up to a fixed number of ions"
+#: ../src/backend/filters/spatialAnalysis.cpp:1160
+msgid "Tolerance to allow for matching"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:456
-msgid "Per Species"
-msgstr "Nach Spezies"
+#: ../src/backend/filters/spatialAnalysis.cpp:1176
+msgid "Replacment condition"
+msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:460
-msgid "Use species specific (from ranging) sampling values"
+#: ../src/backend/filters/spatialAnalysis.cpp:1182
+msgid "Replace value"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:489
-msgid "Sampling value for species"
+#: ../src/backend/filters/spatialAnalysis.cpp:1185
+msgid "Use value data from file when replacing ions"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:497
-#: ../src/backend/filters/ionDownsample.cpp:521
-msgid "Sampling rates"
+#: ../src/backend/filters/spatialAnalysis.cpp:1190
+msgid "Replacement"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:505
-msgid "Output Count"
-msgstr "Ausgabe Anzahl"
+#: ../src/backend/filters/spatialAnalysis.cpp:1210
+msgid "Enable/disable all ions as source"
+msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:508
-msgid "Sample up to this value of points"
+#: ../src/backend/filters/spatialAnalysis.cpp:1236
+msgid "Ions to use as Numerator for conc. calculation"
 msgstr ""
 
-#: ../src/backend/filters/ionDownsample.cpp:513
-msgid "Out Fraction"
-msgstr "Ausgabe Anteil"
+#: ../src/backend/filters/spatialAnalysis.cpp:1785
+msgid "Spatial analysis aborted by user"
+msgstr "Spatial analysis aborted by user"
 
-#: ../src/backend/filters/ionDownsample.cpp:517
-msgid "Sample this fraction of points"
+#: ../src/backend/filters/spatialAnalysis.cpp:1786
+msgid "Insufficient memory to complete analysis"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:37
-msgid "Rectilinear"
-msgstr "Geradlinig"
-
-#: ../src/backend/filters/ionInfo.cpp:38
-msgid "Convex hull"
-msgstr "Konvexe Hülle"
+#: ../src/backend/filters/spatialAnalysis.cpp:1787
+msgid "Required range data not present"
+msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:200
-msgid "No ions"
+#: ../src/backend/filters/spatialAnalysis.cpp:1788
+msgid "Insufficient memory for binomial. Reduce input size?"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:226
-#: ../src/backend/filters/spectrumPlot.cpp:432
-msgid ""
-"Background fit failed - input data was considered ill formed (gauss-test)"
+#: ../src/backend/filters/spatialAnalysis.cpp:1789
+msgid "Insufficient points to continue"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:227
-msgid "Following data has not been corrected"
+#: ../src/backend/filters/spatialAnalysis.cpp:1790
+msgid "Unable to load file"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:279
-msgid "--Counts--"
-msgstr "- Anzahl -"
+#: ../src/backend/filters/spatialAnalysis.cpp:2437
+#: ../src/backend/filters/spatialAnalysis.cpp:2756
+#: ../src/backend/filters/spatialAnalysis.cpp:3046
+msgid "Analyse"
+msgstr "Analyse"
 
-#: ../src/backend/filters/ionInfo.cpp:289
-msgid "Total Ranged\t"
-msgstr "Gesamt ranged\t"
+#: ../src/backend/filters/spatialAnalysis.cpp:2516
+#: ../src/backend/filters/spatialAnalysis.cpp:2606
+#: ../src/backend/filters/spatialAnalysis.cpp:2672
+msgid "Radial Distance"
+msgstr "Radialer Abstand"
 
-#: ../src/backend/filters/ionInfo.cpp:294
-msgid "Total (incl. unranged)\t"
-msgstr "Total (inkl. nicht geranged)"
+#: ../src/backend/filters/spatialAnalysis.cpp:2518
+#: ../src/backend/filters/spatialAnalysis.cpp:2611
+msgid "Count/Distance"
+msgstr ""
+
+#: ../src/backend/filters/spatialAnalysis.cpp:2523
+#: ../src/backend/filters/spatialAnalysis.cpp:2616
+msgid "NN Freq."
+msgstr "NN Freq."
+
+#: ../src/backend/filters/spatialAnalysis.cpp:2663
+msgid "Warning, "
+msgstr "Warnung, "
 
-#: ../src/backend/filters/ionInfo.cpp:307
-msgid "n/a"
+#: ../src/backend/filters/spatialAnalysis.cpp:2664
+msgid ""
+" points were unable to find neighbour points that exceeded the search "
+"radius, and thus terminated prematurely"
 msgstr ""
+" Punkte konnten keine Nachbapunkte die den Suchradius überschritten finden "
+"und beendeten vorzeitig."
 
-#: ../src/backend/filters/ionInfo.cpp:317
-msgid "Unranged"
-msgstr "Nicht Geranged"
+#: ../src/backend/filters/spatialAnalysis.cpp:2674
+msgid " RDF"
+msgstr " RDF"
 
-#: ../src/backend/filters/ionInfo.cpp:330
-msgid "Number of points : "
-msgstr "Anzahl der Punkte: "
+#: ../src/backend/filters/spatialAnalysis.cpp:2952
+#: ../src/backend/filters/spatialAnalysis.cpp:3251
+msgid "Number Density (\\#/Vol^3)"
+msgstr "Number Density (\\#/Vol^3)"
 
-#: ../src/backend/filters/ionInfo.cpp:359
-msgid "Rectilinear Bounds : "
-msgstr "Geradlinige Grenzen:"
+#: ../src/backend/filters/spatialAnalysis.cpp:2977
+#: ../src/backend/filters/spatialAnalysis.cpp:3271
+msgid "Warning,"
+msgstr "Warnung,"
 
-#: ../src/backend/filters/ionInfo.cpp:364
-msgid "Volume (len^3): "
-msgstr "Volumen (Läng.^3)"
+#: ../src/backend/filters/spatialAnalysis.cpp:2978
+#: ../src/backend/filters/spatialAnalysis.cpp:3272
+msgid " points were un-analysable. These have been dropped"
+msgstr " points were un-analysable. These have been dropped"
 
-#: ../src/backend/filters/ionInfo.cpp:381
-msgid "Convex Volume (len^3): "
-msgstr "Konvexes Volumen (Läng.^3)"
+#: ../src/backend/filters/spatialAnalysis.cpp:3000
+#: ../src/backend/filters/spatialAnalysis.cpp:3294
+msgid "And so on..."
+msgstr "Und so weiter..."
 
-#: ../src/backend/filters/ionInfo.cpp:384
-msgid "Unable to compute volume"
-msgstr "Kann Volumen nicht berechnen"
+#: ../src/backend/filters/spatialAnalysis.cpp:3376
+msgid "Extract"
+msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:413
-msgid "Ranged Density (pts/vol):"
-msgstr "Ranged Dichte (pts / vol):"
+#: ../src/backend/filters/spatialAnalysis.cpp:3449
+msgid "Reduce"
+msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:418
-msgid "Total Density (pts/vol):"
-msgstr "Gesamtdichte (pts / vol):"
+#: ../src/backend/filters/spatialAnalysis.cpp:3604
+msgid "Insufficient points to complete analysis"
+msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:445
-msgid "Compositions"
-msgstr "Zusammensetzungen"
+#: ../src/backend/filters/spatialAnalysis.cpp:3627
+msgid "Axial Distance"
+msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:446
-msgid "Display compositional data for points in console"
+#: ../src/backend/filters/spatialAnalysis.cpp:3629
+msgid " 1D Dist. Func."
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:450
-msgid "Counts"
-msgstr "Anzahl"
+#: ../src/backend/filters/spatialAnalysis.cpp:3698
+msgid "Binomial"
+msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:451
-msgid "Display count data for points in console"
+#: ../src/backend/filters/spatialAnalysis.cpp:3829
+#: ../src/backend/filters/spatialAnalysis.cpp:3888
+msgid "Rel. Frequency"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:458
-msgid "Ion data"
+#: ../src/backend/filters/spatialAnalysis.cpp:3966
+msgid "Build Numerator"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:466
-msgid "Normalise count data"
+#: ../src/backend/filters/spatialAnalysis.cpp:3980
+msgid "Build Denominator"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:530
-msgid "Volume"
-msgstr "Volumen"
+#: ../src/backend/filters/ionColour.cpp:257
+msgid "Colour Map"
+msgstr "Farbtabelle"
 
-#: ../src/backend/filters/ionInfo.cpp:533
-msgid "Compute volume for point data"
+#: ../src/backend/filters/ionColour.cpp:265
+msgid "Reverse map"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:549
-msgid "Select volume counting technique"
+#: ../src/backend/filters/ionColour.cpp:266
+msgid "Reverse the colour scale"
 msgstr ""
 
-#: ../src/backend/filters/ionInfo.cpp:562
-msgid "Volume data"
+#: ../src/backend/filters/ionColour.cpp:279
+msgid "Opacity"
+msgstr ""
+
+#: ../src/backend/filters/ionColour.cpp:286
+msgid "Num Colours"
+msgstr ""
+
+#: ../src/backend/filters/ionColour.cpp:288
+msgid "Number of unique colours to use in colour map"
 msgstr ""
 
 #: ../src/backend/filters/dataLoad.cpp:61
@@ -4384,13 +4753,6 @@ msgstr ""
 "der numerischen Stabilität des internen Datentyps (Größenordnung zu groß). "
 "Erwägen Sie die Daten vor dem Laden zu skalieren. "
 
-#: ../src/backend/filters/dataLoad.cpp:484
-#: ../src/backend/filters/dataLoad.cpp:505
-#: ../src/backend/filters/rangeFile.cpp:558
-#: ../src/backend/filters/rangeFile.cpp:578
-msgid "File"
-msgstr "Datei"
-
 #: ../src/backend/filters/dataLoad.cpp:485
 msgid "File from which to load data"
 msgstr ""
@@ -4532,335 +4894,146 @@ msgstr "Anzahl"
 msgid "Mixed data"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:441
+#: ../src/backend/filters/spectrumPlot.cpp:445
 msgid "Background:"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:496
+#: ../src/backend/filters/spectrumPlot.cpp:504
 msgid "Relative "
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:499
+#: ../src/backend/filters/spectrumPlot.cpp:507
 msgid "Probability Density"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:576
+#: ../src/backend/filters/spectrumPlot.cpp:584
 msgid "Step size for spectrum"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:581
+#: ../src/backend/filters/spectrumPlot.cpp:589
 msgid "Auto Min/max"
 msgstr "Auto Min/max"
 
-#: ../src/backend/filters/spectrumPlot.cpp:585
+#: ../src/backend/filters/spectrumPlot.cpp:593
 msgid "Automatically compute spectrum upper and lower bound"
 msgstr ""
 
-#: ../src/backend/filters/spectrumPlot.cpp:590
+#: ../src/backend/filters/spectrumPlot.cpp:598
 msgid "Min"
 msgstr "Min"
 
-#: ../src/backend/filters/spectrumPlot.cpp:593
-msgid "Starting position for spectrum"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:598
-msgid "Max"
-msgstr "Max"
-
-#: ../src/backend/filters/spectrumPlot.cpp:601
-msgid "Ending position for spectrum"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:609
-msgid "Logarithmic"
-msgstr "Logarithmisch"
-
-#: ../src/backend/filters/spectrumPlot.cpp:612
-msgid "Convert the plot to logarithmic mode"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:624
-msgid "Normalisation"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:627
-msgid "Rescale the plot height, to make inter-spectrum comparisons easier"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:634
-msgid "Lower Bound"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:638
-msgid "Do not use data below this x-value for normalisation"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:642
-msgid "Upper Bound"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:646
-msgid "Do not use data above this x-value for normalisation"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:664
-msgid "Visual style of plot"
-msgstr ""
-
-#: ../src/backend/filters/spectrumPlot.cpp:671
-msgid "Colour of plotted spectrum"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:153
-msgid "Pre-Allocate"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:288 ../src/backend/filter.cpp:54
-msgid "Range"
-msgstr "Range"
-
-#: ../src/backend/filters/rangeFile.cpp:561
-msgid "File to use for range data"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:571
-msgid "Drop unranged"
-msgstr "Nicht gerangete ausschalten"
-
-#: ../src/backend/filters/rangeFile.cpp:573
-msgid "Remove unranged points when generating output"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:583
-msgid "Legend"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:585
-msgid "Display colour legend for enabled ions"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:589
-msgid "View"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:605
-msgid "All Ions"
-msgstr "Alle Ionen"
-
-#: ../src/backend/filters/rangeFile.cpp:606
-msgid "Enable/disable all ions at once"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:614
-msgid "Species"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:621
-msgid "IonID "
-msgstr "IonID "
-
-#: ../src/backend/filters/rangeFile.cpp:622
-msgid "Enable/disable specified ion"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:632
-msgid "Active Ion "
-msgstr "Actives Ion "
-
-#: ../src/backend/filters/rangeFile.cpp:634
-msgid "If true, ion is used in output"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:644
-msgid "Colour "
-msgstr "Farbe"
-
-#: ../src/backend/filters/rangeFile.cpp:648
-msgid "Colour used to represent ion"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:671
-msgid "All Ranges"
-msgstr "Alle Range"
-
-#: ../src/backend/filters/rangeFile.cpp:672
-msgid "Enable/disable all ranges"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:687
-msgid "Active Rng "
-msgstr "Activer Rng "
-
-#: ../src/backend/filters/rangeFile.cpp:690
-msgid ""
-"Enable/disable specified range (ion must also be enabled to activiate range)"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:694
-msgid "Ion "
-msgstr "Ion "
-
-#: ../src/backend/filters/rangeFile.cpp:697
-msgid "Name of ion associate to this range"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:706
-msgid "Start rng "
-msgstr "Start rng "
-
-#: ../src/backend/filters/rangeFile.cpp:709
-msgid "Start value for range"
-msgstr ""
-
-#: ../src/backend/filters/rangeFile.cpp:714
-msgid "End rng "
-msgstr "End rng "
-
-#: ../src/backend/filters/rangeFile.cpp:717
-msgid "Stopping value for range`"
-msgstr ""
-
-#: ../src/backend/state.cpp:151
-msgid ""
-"This file is a \"state\" file for the 3Depict program, and stores "
-"information about a particular analysis session. This file should be a valid "
-"\"XML\" file"
-msgstr ""
-"Diese Datei ist ein \"Status\" Datei für das Programm 3Depict. Sie speichert "
-"Informationen über die jeweiligen Analysesitzung. Dies sollte ein gültige "
-"\"XML\" Datei sein."
-
-#: ../src/backend/state.cpp:318
-msgid "Failed to allocate parser"
-msgstr "Kann Parser nicht zuordnen"
-
-#: ../src/backend/state.cpp:353
-msgid ""
-"Unable to retrieve root node in input state file... Is this really a non-"
-"empty XML file?"
-msgstr ""
-
-#: ../src/backend/state.cpp:360
-msgid "Base state node missing. Is this really a state XML file??"
-msgstr ""
-
-#: ../src/backend/state.cpp:389
-msgid "State was created by a newer version of this program.. "
-msgstr "Status wurde von einer neueren Version dieses Programmes erstellt.. "
-
-#: ../src/backend/state.cpp:390
-msgid "file reading will continue, but may fail."
-msgstr "Datei wird weiter eingelesen kann aber unter Umständen fehlschlagen."
-
-#: ../src/backend/state.cpp:395
-msgid ""
-"Warning, unparseable version number in state file. File reading will "
-"continue, but may fail"
+#: ../src/backend/filters/spectrumPlot.cpp:601
+msgid "Starting position for spectrum"
 msgstr ""
-"Warnung: Nicht lesbare Versionsnummer in Statusdatei. Datei wird weiter "
-"eingelesen kann aber unter Umständen fehlschlagen."
 
-#: ../src/backend/state.cpp:402
-msgid "Unable to find the \"writer\" node"
-msgstr "Kann \"writer\" node nicht finden"
+#: ../src/backend/filters/spectrumPlot.cpp:606
+msgid "Max"
+msgstr "Max"
 
-#: ../src/backend/state.cpp:412
-msgid "Unable to find the \"backcolour\" node."
-msgstr "Unable to find the \"backcolour\" node."
+#: ../src/backend/filters/spectrumPlot.cpp:609
+msgid "Ending position for spectrum"
+msgstr ""
 
-#: ../src/backend/state.cpp:419
-msgid "\"backcolour\" node missing \"r\" value."
-msgstr "\"backcolour\" node fehlt \"r\" Wert."
+#: ../src/backend/filters/spectrumPlot.cpp:617
+msgid "Logarithmic"
+msgstr "Logarithmisch"
 
-#: ../src/backend/state.cpp:424
-msgid "Unable to interpret \"backColour\" node's \"r\" value."
-msgstr "Kann \"backColour\" node's \"r\" Wert nicht interpretieren."
+#: ../src/backend/filters/spectrumPlot.cpp:620
+msgid "Convert the plot to logarithmic mode"
+msgstr ""
 
-#: ../src/backend/state.cpp:432
-msgid "\"backcolour\" node missing \"g\" value."
-msgstr "\"backcolour\" node fehlt \"g\" Wert."
+#: ../src/backend/filters/spectrumPlot.cpp:632
+msgid "Normalisation"
+msgstr ""
 
-#: ../src/backend/state.cpp:438
-msgid "Unable to interpret \"backColour\" node's \"g\" value."
-msgstr "Kann \"backColour\" node's \"g\" Wert nicht interpretieren."
+#: ../src/backend/filters/spectrumPlot.cpp:635
+msgid "Rescale the plot height, to make inter-spectrum comparisons easier"
+msgstr ""
 
-#: ../src/backend/state.cpp:446
-msgid "\"backcolour\" node missing \"b\" value."
-msgstr "\"backcolour\" node fehlt \"b\" Wert."
+#: ../src/backend/filters/spectrumPlot.cpp:642
+msgid "Lower Bound"
+msgstr ""
 
-#: ../src/backend/state.cpp:452
-msgid "Unable to interpret \"backColour\" node's \"b\" value."
-msgstr "Kann \"backColour\" node's \"b\" Wert nicht interpretieren."
+#: ../src/backend/filters/spectrumPlot.cpp:646
+msgid "Do not use data below this x-value for normalisation"
+msgstr ""
 
-#: ../src/backend/state.cpp:459
-msgid "\"backcolour\"s rgb values must be in range [0,1]"
-msgstr "\"backcolour\"s rgb Wert muss im Bereich [0,1] liegen"
+#: ../src/backend/filters/spectrumPlot.cpp:650
+msgid "Upper Bound"
+msgstr ""
 
-#: ../src/backend/state.cpp:487
-msgid "Unable to find or interpret \"showaxis\" node"
-msgstr "Kann \"showaxis\" node nicht interpretieren"
+#: ../src/backend/filters/spectrumPlot.cpp:654
+msgid "Do not use data above this x-value for normalisation"
+msgstr ""
 
-#: ../src/backend/state.cpp:531
-msgid "Unable to locate \"filtertree\" node."
-msgstr "Kann \"filtertree\" node nicht finden."
+#: ../src/backend/filters/spectrumPlot.cpp:672
+msgid "Visual style of plot"
+msgstr ""
 
-#: ../src/backend/state.cpp:547
-msgid "Cameras section missing \"active\" node."
-msgstr "Cameras section fehlt \"active\" node."
+#: ../src/backend/filters/spectrumPlot.cpp:679
+msgid "Colour of plotted spectrum"
+msgstr ""
 
-#: ../src/backend/state.cpp:555
-msgid "Unable to find property \"value\"  for \"cameras->active\" node."
-msgstr "Kann \"Eigenschaftswert\"  für \"Kamera->aktiv\" Node nicht finden."
+#: ../src/backend/filters/spectrumPlot.cpp:694
+msgid "Model"
+msgstr ""
 
-#: ../src/backend/state.cpp:561
-msgid "Unable to interpret property \"value\"  for \"cameras->active\" node."
+#: ../src/backend/filters/spectrumPlot.cpp:697
+msgid "Fitting method to use"
 msgstr ""
-"Kann \"Eigenschaftswert\"  für \"Kamera->aktiv\" Node nicht interpretieren."
 
-#: ../src/backend/state.cpp:580
-msgid "Failed to interpret camera state for camera : "
+#: ../src/backend/filters/spectrumPlot.cpp:708
+msgid "Fit Start"
 msgstr ""
 
-#: ../src/backend/state.cpp:588
-msgid "Unable to interpret the camera type for camera : "
-msgstr "Kann den Kameratype nicht interpretieren für :"
+#: ../src/backend/filters/spectrumPlot.cpp:709
+msgid "Start mass value for fitting background"
+msgstr ""
 
-#: ../src/backend/state.cpp:632
-msgid "Unable to locate stash name for stash "
-msgstr "Kann den Stashnamen für Stash  nicht finden"
+#: ../src/backend/filters/spectrumPlot.cpp:715
+msgid "Fit End"
+msgstr ""
 
-#: ../src/backend/state.cpp:639
-msgid "Empty stash name for stash "
-msgstr "Leerer Stashname für Stash"
+#: ../src/backend/filters/spectrumPlot.cpp:716
+msgid "End mass value for fitting background"
+msgstr ""
 
-#: ../src/backend/state.cpp:648
-msgid "No filter tree for stash:"
+#: ../src/backend/filters/spectrumPlot.cpp:729
+msgid "Corr. Only"
 msgstr ""
 
-#: ../src/backend/state.cpp:654
-msgid "For stash "
-msgstr "Für Stash "
+#: ../src/backend/filters/spectrumPlot.cpp:730
+msgid "Only show corrected spectrum, not fit"
+msgstr ""
 
-#: ../src/backend/state.cpp:686
-msgid "Unrecognised effect :"
-msgstr "Nichterkannter Effekt :"
+#: ../src/backend/filters/spectrumPlot.cpp:738
+msgid "Background Mode"
+msgstr ""
 
-#: ../src/backend/state.cpp:696
-msgid "Duplicate effect found"
-msgstr "Doppelter Effekt gefunden"
+#: ../src/backend/configFile.cpp:187
+msgid "Config file present, but is not valid (root node test)"
+msgstr "Konfigurationsdatei vorhanden, aber nicht gültig (root node test)"
 
-#: ../src/backend/state.cpp:696
-msgid " cannot use."
-msgstr "kann nicht   verwenden."
+#: ../src/backend/configFile.cpp:228
+msgid "Unable to interpret recent file entry"
+msgstr "Kann den letzten Dateieintrag nicht interpretieren"
 
-#: ../src/backend/state.cpp:706
-msgid "Error reading effect : "
-msgstr "Fehler beim Lesen:"
+#: ../src/backend/configFile.cpp:268
+msgid "Unable to determine filter type in defaults listing."
+msgstr "Kann den Filtertyp im Defaultslisting nicht bestimmen."
 
-#: ../src/backend/state.cpp:898
-msgid "-merge"
+#: ../src/backend/configFile.cpp:605
+msgid "Online access for non win32/apple platforms is intentionally disabled, "
+msgstr ""
+"Onlinezugang für nicht Win32/apple systeme wurde absichtlich deaktiviert."
+
+#: ../src/backend/configFile.cpp:606
+msgid ""
+"regardless of the settings you use here. Use your package manager to keep up-"
+"to-date"
 msgstr ""
+"Nutzen Sie Ihren Paketmanager um up-to-date zu sein unabhängig von den "
+"Einstellungen die Sie hier verwenden"
 
 #: ../src/backend/filtertreeAnalyse.cpp:223
 msgid ""
@@ -4934,268 +5107,287 @@ msgid ""
 "provisional only."
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:44 ../src/backend/APT/APTFileIO.cpp:79
-#: ../src/backend/APT/APTFileIO.cpp:103
-msgid "Error opening file"
-msgstr "Fehler beim Öffnen der Datei"
+#: ../src/backend/plot.cpp:29
+msgid "Moving avg."
+msgstr "Gleit.Durchschn."
 
-#: ../src/backend/APT/APTFileIO.cpp:45
-msgid "Only found header, no data"
-msgstr ""
+#: ../src/backend/plot.cpp:33
+msgid "Lines"
+msgstr "Linien"
 
-#: ../src/backend/APT/APTFileIO.cpp:46
-msgid "Unable to reopen file after first scan"
-msgstr ""
+#: ../src/backend/plot.cpp:34
+msgid "Bars"
+msgstr "Block"
 
-#: ../src/backend/APT/APTFileIO.cpp:47
-msgid "Error whilst reading file contents"
-msgstr "Fehler beim Lesen des Dateiinhaltes"
+#: ../src/backend/plot.cpp:35
+msgid "Steps"
+msgstr "Stufen"
 
-#: ../src/backend/APT/APTFileIO.cpp:48 ../src/backend/APT/APTFileIO.cpp:49
-msgid "Unexpected file format"
-msgstr ""
+#: ../src/backend/plot.cpp:36
+msgid "Stem"
+msgstr "Stem"
 
-#: ../src/backend/APT/APTFileIO.cpp:50
-msgid "Insufficient memory to continue"
+#: ../src/backend/plot.cpp:37
+msgid "Points"
+msgstr "Punkte"
+
+#: ../src/backend/plot.cpp:39
+msgid "Density"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:54
-msgid "Memory allocation failure on POS load"
-msgstr "Speicherzuweisungsfeher beim Laden der pos-Datei"
+#: ../src/backend/plot.cpp:40
+msgid "Scatter"
+msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:55
-msgid "Error opening pos file"
-msgstr "Fehler beim Öffnen der pos-Datei"
+#: ../src/backend/plot.cpp:739 ../src/backend/plot.cpp:747
+msgid "Multiple data types"
+msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:56
-msgid "Pos file empty"
-msgstr "Pos-Datei ist leer"
+#: ../src/backend/plot.cpp:1581
+msgid "error"
+msgstr "Fehler"
 
-#: ../src/backend/APT/APTFileIO.cpp:57
-msgid "Pos file size appears to have non-integer number of entries"
+#: ../src/backend/plot.cpp:1821
+msgid "Amplitude"
 msgstr ""
-"Pos-Dateigröße scheint eine nicht ganzzahlige Anzahl an Einträgen zu haben"
 
-#: ../src/backend/APT/APTFileIO.cpp:58
-msgid "Error reading from pos file (after open)"
-msgstr "Fehler beim Lesen aus pos-Datei (nach dem öffnen)"
+#: ../src/backend/filtertree.cpp:1151
+msgid "WARNING: Skipping node "
+msgstr "WARNUNG: Skipping node "
 
-#: ../src/backend/APT/APTFileIO.cpp:59
-msgid "Error - Found NaN in pos file"
-msgstr "Fehler - Fand NaN in pos-Datei"
+#: ../src/backend/filtertree.cpp:1151
+msgid " as it was not recognised"
+msgstr " wurde nicht erkannt."
 
-#: ../src/backend/APT/APTFileIO.cpp:60
-msgid "Error - Found Inf in pos file"
-msgstr ""
+#: ../src/backend/filtertree.cpp:1189
+msgid "Error processing node: "
+msgstr "Fehler beim Verarbeiten von Node: "
 
-#: ../src/backend/APT/APTFileIO.cpp:61
-msgid "Pos load aborted by interrupt."
-msgstr "Pos laden durch Interrupt abgebrochen."
+#: ../src/gl/cameras.cpp:596
+msgid "Lock"
+msgstr "Sperren"
 
-#: ../src/backend/APT/APTFileIO.cpp:80
-msgid "No numerical data found"
-msgstr "Keine numerischen Daten gefunden"
+#: ../src/gl/cameras.cpp:617
+msgid "Up Dir."
+msgstr "Up Dir."
 
-#: ../src/backend/APT/APTFileIO.cpp:81
-msgid "Error re-opening file, after first scan"
-msgstr "Fehler beim nochmaligen Öffnen der Datei nach dem ersten Scan"
+#: ../src/gl/cameras.cpp:625 ../src/gl/cameras.cpp:728
+msgid "Perspective"
+msgstr "Perspektivisch"
 
-#: ../src/backend/APT/APTFileIO.cpp:82
-msgid "Unable to read file contents after open"
-msgstr "Kann den Dateiinhalt nach dem Öffnen nich lesen"
+#: ../src/gl/cameras.cpp:631
+msgid "Projection"
+msgstr "Projektion"
 
-#: ../src/backend/APT/APTFileIO.cpp:83
-msgid "Error interpreting field in file"
-msgstr "Fehler beim Interpretieren eine Feldes in der Datei"
+#: ../src/gl/cameras.cpp:640
+msgid "Field of View (deg)"
+msgstr "Bildausschnitt"
 
-#: ../src/backend/APT/APTFileIO.cpp:84
-msgid "Incorrect number of fields in file"
-msgstr "Die Datei enthält eine falsche Anzahl von Feldern"
+#: ../src/gl/cameras.cpp:646
+msgid "View size"
+msgstr "Anzeigegröße"
 
-#: ../src/backend/APT/APTFileIO.cpp:85 ../src/backend/APT/APTFileIO.cpp:107
-msgid "Unable to allocate memory to store data"
-msgstr "Kann Speicher nicht zuordnen"
+#: ../src/3Depict.cpp:397
+msgid "File : "
+msgstr "Datei : "
 
-#: ../src/backend/APT/APTFileIO.cpp:104
-msgid "File is empty"
+#: ../src/3Depict.cpp:397
+msgid " does not exist. Skipping"
+msgstr " existiert nicht. Überspringe"
+
+#: ../src/common/constants.cpp:22
+msgid ""
+"Range Files (*.rng; *.env; *.rrng)|*.rng;*.env;*.rrng;*.RRNG;*.RNG;*.ENV|RNG "
+"File (*.rng)|*.rng;*.RNG|Environment File (*.env)|*.env;*.ENV|RRNG Files (*."
+"rrng)|*.rrng;*.RRNG|All Files (*)|*"
 msgstr ""
 
-#: ../src/backend/APT/APTFileIO.cpp:105
-msgid "Filesize does not match expected format"
-msgstr ""
+#: ../src/common/basics.cpp:183
+msgid "in the future?"
+msgstr "in Zukunft?"
+
+#: ../src/common/basics.cpp:234
+msgid "a decade ago"
+msgstr "vor zehn Jahren"
+
+#: ../src/common/basics.cpp:235
+msgid "a year ago"
+msgstr "vor einem Jahr"
+
+#: ../src/common/basics.cpp:236
+msgid "a month ago"
+msgstr "vor einem Monat"
+
+#: ../src/common/basics.cpp:237
+msgid "a week ago"
+msgstr "vor einer Woche"
+
+#: ../src/common/basics.cpp:238
+msgid "a day ago"
+msgstr "gestern"
 
-#: ../src/backend/APT/APTFileIO.cpp:106
-msgid "File version number not <4, as expected"
-msgstr ""
+#: ../src/common/basics.cpp:239
+msgid "an hour ago"
+msgstr "vor einer Stunde"
 
-#: ../src/backend/APT/APTFileIO.cpp:108
-msgid "Unable to detect endian-ness in file"
-msgstr ""
+#: ../src/common/basics.cpp:240
+msgid "45 minutes ago"
+msgstr "vor 45 Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:48
-msgid "Error opening file, check name and permissions."
-msgstr "Fehler beim Öffnen der Datei, überprüfe Namen und Berechtigungen."
+#: ../src/common/basics.cpp:241
+msgid "30 minutes ago"
+msgstr "vor 30 Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:49
-msgid ""
-"Error interpreting range file header, expecting ion count and range count, "
-"respectively."
-msgstr ""
-"Fehler beim Rangedatei interpretieren, erwarte Ionenanzahl bzw. Rangeanzahl."
+#: ../src/common/basics.cpp:242
+msgid "20 minutes ago"
+msgstr "vor 20 Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:50
-msgid ""
-"Range file appears to be empty, check file is a proper range file and is not "
-"empty."
-msgstr ""
-"Rangedatei scheint leer zu sein. Prüfe ob die Datei wirklich ein Rangedatei "
-"und nicht leer ist."
+#: ../src/common/basics.cpp:243
+msgid "15 minutes ago"
+msgstr "vor 15 Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:51
-msgid "Error reading the long name for ion."
-msgstr "Fehler beim Lesen des langen Namens für Ion."
+#: ../src/common/basics.cpp:244
+msgid "10 minutes ago"
+msgstr "vor 10 Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:52
-msgid "Error reading the short name for ion."
-msgstr "Fehler beim Lesen des kurzen Namens für Ion."
+#: ../src/common/basics.cpp:245
+msgid "5 minutes ago"
+msgstr "vor 5 Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:53
-msgid ""
-"Error reading colour data in the file, expecting 3 decimal values, space "
-"separated."
-msgstr ""
-"Fehler beim Lesen der Farbinformationen in der Datei. Erwarte 3, durch "
-"Leerzeichen getrennte, Dezimalwerte."
+#: ../src/common/basics.cpp:246
+msgid "a minute ago"
+msgstr "vor einer Minute"
 
-#: ../src/backend/APT/APTRanges.cpp:54
-msgid ""
-"Tried skipping to table separator line (line with dashes), but did not find "
-"it."
-msgstr ""
+#: ../src/common/basics.cpp:247
+msgid "30 seconds ago"
+msgstr "vor 30 Sekunden"
 
-#: ../src/backend/APT/APTRanges.cpp:55
-msgid ""
-"Number of ions in the table header did not match the number specified at the "
-"start of the file"
-msgstr ""
+#: ../src/common/basics.cpp:248
+msgid "10 seconds ago"
+msgstr "vor 10 Sekunden"
 
-#: ../src/backend/APT/APTRanges.cpp:56
-msgid ""
-"Unexpected failure whilst trying to skip over range lead-in data (bit before "
-"range start value)"
-msgstr ""
+#: ../src/common/basics.cpp:249
+msgid "a second ago"
+msgstr "vor einer Sekunde"
 
-#: ../src/backend/APT/APTRanges.cpp:57
-msgid ""
-"Range table had an incorrect number of entries, should be 2 or 3 + number of "
-"ranges"
-msgstr ""
+#: ../src/common/basics.cpp:254
+msgid "a few decades ago"
+msgstr "vor einigen Dekaden"
 
-#: ../src/backend/APT/APTRanges.cpp:58
-msgid "Unable to read range start and end values"
-msgstr "Kann Anfangs und Endwert des Range nicht lesen"
+#: ../src/common/basics.cpp:255
+msgid "a few years ago"
+msgstr "vor einigen Jahren"
 
-#: ../src/backend/APT/APTRanges.cpp:59
-msgid "Unable to read range table entry"
-msgstr "Kann Rangetabelleneintrag nich lesen"
+#: ../src/common/basics.cpp:256
+msgid "a few months ago"
+msgstr "vor einigen Monaten"
 
-#: ../src/backend/APT/APTRanges.cpp:60
-msgid ""
-"Error reading file, unexpected format, are you sure it is a proper range "
-"file?"
-msgstr ""
-"Fehler beim Lesen der Datei: Unerwartetes Format, sind Sie sicher, dass dies "
-"eine korrekte Rangedatei ist?"
+#: ../src/common/basics.cpp:257
+msgid "a few weeks ago"
+msgstr "vor einigen Wochen"
 
-#: ../src/backend/APT/APTRanges.cpp:61
-msgid ""
-"Too many ranges appeared to have range entries with no usable data (eg, all "
-"blank)"
-msgstr "Zu viele Ranges scheinen  ungültige Einträge zu haben (z.B. alle leer)"
+#: ../src/common/basics.cpp:258
+msgid "a few days ago"
+msgstr "vor einigen Tagen"
 
-#: ../src/backend/APT/APTRanges.cpp:62
-msgid ""
-"Range file appears to contain malformed data, check things like start and "
-"ends of m/c are not equal or flipped."
-msgstr ""
+#: ../src/common/basics.cpp:259
+msgid "a few hours ago"
+msgstr "vor einigen Stunden"
 
-#: ../src/backend/APT/APTRanges.cpp:63
-msgid "Range file appears to be inconsistent (eg, overlapping ranges)"
-msgstr "Rangedatei schein inkonsistent zu sein (z.B. überlappende Ranges)"
+#: ../src/common/basics.cpp:266
+msgid "a few minutes ago"
+msgstr "vor einigen Minuten"
 
-#: ../src/backend/APT/APTRanges.cpp:64
-msgid "No ion name mapping found  for multiple ion."
-msgstr ""
+#: ../src/common/basics.cpp:269
+msgid "a few seconds ago"
+msgstr "vor einigen Sekunden"
 
-#: ../src/backend/APT/APTRanges.cpp:65
-msgid "Polyatomic extension range matches multiple masses in first section"
-msgstr ""
+#: ../src/common/basics.cpp:296
+msgid "moments ago"
+msgstr "kürzlich"
 
-#: ../src/backend/APT/APTRanges.cpp:66
-msgid "Range file is exceedingly large. Refusing to open"
-msgstr ""
+#: ../src/common/colourmap.cpp:242
+msgid "Jet"
+msgstr "Jet"
 
-#: ../src/backend/APT/APTRanges.cpp:1404
-msgid ""
-"Range headings do not match order of the ions listed in the name "
-"specifications. The name specification ordering will be used when reading "
-"the range table, as the range heading section is declared as a comment in "
-"the file-format specifications, and is not to be intepreted by this program. "
-"Check range-species associations actually match what you expect."
-msgstr ""
+#: ../src/common/colourmap.cpp:243
+msgid "Hot"
+msgstr "Heiss"
 
-#: ../src/backend/filter.cpp:52
-msgid "2D Plot"
-msgstr ""
+#: ../src/common/colourmap.cpp:244
+msgid "Cold"
+msgstr "Kalt"
 
-#: ../src/backend/filter.cpp:53
-msgid "Draw"
-msgstr "Zeichnen"
+#: ../src/common/colourmap.cpp:245
+msgid "Grey"
+msgstr "Grau"
 
-#: ../src/backend/filter.cpp:55
-msgid "Voxel"
-msgstr "Voxel"
+#: ../src/common/colourmap.cpp:246
+msgid "Cyclic"
+msgstr "Cyclic"
 
-#: ../src/wx/wxcomponents.h:82
-msgid "treeCtrl"
-msgstr ""
+#: ../src/common/colourmap.cpp:247
+msgid "General"
+msgstr "Allgemein"
 
-#: ../src/backend/filters/transform.h:71
-msgid "Ion. Transform"
-msgstr "Ion. Transformieren"
+#: ../src/common/colourmap.cpp:248
+msgid "Blue"
+msgstr "Blau"
 
-#: ../src/backend/filters/ionColour.h:63
-msgid "Spectral Colour"
-msgstr "Spectral Farbe"
+#: ../src/common/colourmap.cpp:249
+msgid "Pseudo-Random"
+msgstr "Pseudo-Random"
 
-#: ../src/backend/filters/boundingBox.h:72
-msgid "Bound box"
-msgstr "Begrenzungs-Box"
+#: ../src/wx/wxcomponents.cpp:191
+msgid "Save Data..."
+msgstr "Datei speichern..."
 
-#: ../src/backend/filters/ionDownsample.h:79
-msgid "Ion Sampler"
-msgstr "Ion Sampler"
+#: ../src/wx/wxcomponents.cpp:192
+msgid "Text File (*.txt)|*.txt|All Files (*)|*"
+msgstr "Text Datei (*.txt)|*.txt|Alle Dateien (*)|*"
 
-#: ../src/backend/filters/ionInfo.h:103
-msgid "Ion info"
-msgstr "Ioneninfo"
+#: ../src/wx/wxcomponents.cpp:204
+msgid "Error saving file. Check output dir is writable."
+msgstr ""
+"Fehler beim Schreiben der Datei. Stellen Sie sicher, dass das "
+"Zielverzeichnis nicht schreibgeschüzt ist."
 
 #: ../src/backend/filters/dataLoad.h:135
 msgid "Pos Data"
 msgstr "POS-Daten"
 
+#: ../src/backend/filters/ionInfo.h:103
+msgid "Ion info"
+msgstr "Ioneninfo"
+
 #: ../src/backend/filters/externalProgram.h:69
 msgid "Ext. Program"
 msgstr "Ext. Programm"
 
-#: ../src/backend/filters/rangeFile.h:96
-msgid "Ranging"
-msgstr "Ranging"
+#: ../src/backend/filters/ionColour.h:63
+msgid "Spectral Colour"
+msgstr "Spectral Farbe"
 
-#: ../src/backend/filters/compositionProfile.h:120
+#: ../src/backend/filters/profile.h:123
 msgid "Comp. Prof."
 msgstr "Konz. Prof."
 
+#: ../src/backend/filters/ionDownsample.h:79
+msgid "Ion Sampler"
+msgstr "Ion Sampler"
+
+#: ../src/backend/filters/boundingBox.h:76
+msgid "Bound box"
+msgstr "Begrenzungs-Box"
+
+#: ../src/backend/filters/transform.h:71
+msgid "Ion. Transform"
+msgstr "Ion. Transformieren"
+
+#: ../src/wx/wxcomponents.h:82
+msgid "treeCtrl"
+msgstr ""
+
 #: ../data/startup-tips.txt:5
 msgid ""
 "You can reset the main view by tapping the space bar. Hold down modifier "
@@ -5248,7 +5440,9 @@ msgid ""
 msgstr ""
 
 #: ../data/startup-tips.txt:14
-msgid "You can abort most calculations by pressing Escape"
+msgid ""
+"You can abort most calculations either by pressing Escape (OSX/Linux), or by "
+"using the Abort button (Windows)"
 msgstr ""
 
 #: ../data/startup-tips.txt:15
@@ -5294,7 +5488,7 @@ msgstr ""
 #: ../data/startup-tips.txt:22
 msgid ""
 "You can ask questions about the program, or using it on your data on our "
-"forums (http://sourceforge.net/apps/phpbb/threedepict/)"
+"forums (https://sourceforge.net/p/threedepict/discussion/general/)"
 msgstr ""
 
 #: ../data/startup-tips.txt:23
@@ -5303,6 +5497,21 @@ msgid ""
 "views"
 msgstr ""
 
+#: ../data/startup-tips.txt:24
+msgid ""
+"You can open multiple files at once, and get a side-by-side view by "
+"translating (shifting) one of the datasets to one side"
+msgstr ""
+
+#~ msgid "ORNL format RNG (*.rng)|*.rng|All Files (*)|*"
+#~ msgstr "ORNL Format RNG (*.rng)|*.rng|Alle Dateien (*)|*"
+
+#~ msgid "POS Data (*.pos)|*.pos|All Files (*)|*"
+#~ msgstr "POS-Daten (*.pos)|*.pos|All Files (*)|*"
+
+#~ msgid "Mass-to-Charge (amu/e)"
+#~ msgstr "Masse-zu-Ladung (amu/e)"
+
 #~ msgid "Last Outputs"
 #~ msgstr "Letzte Ausgabe"
 
@@ -5445,9 +5654,6 @@ msgstr ""
 #~ msgid "Aborted composition prof."
 #~ msgstr "Konzentrationspr. abgebr."
 
-#~ msgid "Spatial analysis aborted by user"
-#~ msgstr "Spatial analysis aborted by user"
-
 #~ msgid "Insufficient data to complete analysis."
 #~ msgstr "Ungenügend Daten zum Fertigstellen der Analyse."
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/3depict.git



More information about the debian-science-commits mailing list