diff --git a/MANIFEST.in b/MANIFEST.in
index 1e837ff..401d931 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,4 +4,5 @@ include mantis_xray/Mantis_batch_settings.txt
 include mantis_xray/images/*
 include mantis_xray/henke.xdr
 include mantis_xray/*.ui
+include mantis_xray/*.qss
 recursive-include mantis_xray *.py
diff --git a/PKG-INFO b/PKG-INFO
index 9fcf799..cc0bbeb 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: mantis-xray
-Version: 3.0.11
+Version: 3.1.8
 Summary: MANTiS is a Multivariate ANalysis Tool for x-ray Spectromicroscopy
 Home-page: https://spectromicroscopy.com/
 Author: Mirna Lerotic
@@ -8,33 +8,6 @@ Author-email: mirna@2ndlookconsulting.com
 License: UNKNOWN
 Project-URL: Code, https://github.com/mlerotic/spectromicroscopy
 Project-URL: Documentation, https://docs.spectromicroscopy.com
-Description: # Spectromicroscopy #
-        [Spectromicroscopy](http://spectromicroscopy.com) combines spectral data with microscopy,
-        where typical datasets consist of a stack of microscopic images
-        taken across an energy range. Due to the data complexity, manual analysis 
-        can be time consuming and inefficient, whereas multivariate analysis tools 
-        not only reduce the time needed but also can uncover hidden trends in the data.
-        
-        # Mantis #
-        [MANTiS](http://spectromicroscopy.com) is Multivariate ANalysis Tool for Spectromicroscopy developed in Python by [2nd Look Consulting](http://2ndlookconsulting.com). It uses principal component analysis and cluster analysis to classify pixels according to spectral similarity.
-        
-        ## Download ##
-        Mantis package and binaries can be downloaded from 
-        [spectromicroscopy.com](http://spectromicroscopy.com).
-        Alternatively, you can install [Python](https://www.python.org/downloads/) and then run the command: `python3 -m pip install mantis-xray`
-        
-        ## Run ##
-        Installation via pip provides the `mantis-xray` command to start the Mantis GUI.
-        
-        ## User Guide ##
-        Mantis User Guide can be found on https://docs.spectromicroscopy.com/.
-        
-        ## References ##
-        
-        Please use the following reference when quoting Mantis
-        
-        Lerotic M, Mak R, Wirick S, Meirer F, Jacobsen C. MANTiS: a program for the analysis of X-ray spectromicroscopy data. J. Synchrotron Rad. 2014 Sep; 21(5); 1206–1212 [http://dx.doi.org/10.1107/S1600577514013964]
-        
 Platform: UNKNOWN
 Classifier: Programming Language :: Python :: 3
 Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -43,4 +16,37 @@ Classifier: Topic :: Scientific/Engineering
 Requires-Python: >=3
 Description-Content-Type: text/markdown
 Provides-Extra: netCDF
-Provides-Extra: SIRT
+License-File: LICENSE
+
+# Spectromicroscopy #
+[Spectromicroscopy](http://spectromicroscopy.com) combines spectral data with microscopy,
+where typical datasets consist of a stack of microscopic images
+taken across an energy range. Due to the data complexity, manual analysis 
+can be time consuming and inefficient, whereas multivariate analysis tools 
+not only reduce the time needed but also can uncover hidden trends in the data.
+
+# Mantis #
+[MANTiS](http://spectromicroscopy.com) is Multivariate ANalysis Tool for Spectromicroscopy developed in Python by [2nd Look Consulting](http://2ndlookconsulting.com). It uses principal component analysis and cluster analysis to classify pixels according to spectral similarity.
+
+## Download ##
+Mantis package and binaries can be downloaded from 
+[spectromicroscopy.com](http://spectromicroscopy.com).
+Alternatively, you can install [Python](https://www.python.org/downloads/) and then run the command: `python3 -m pip install mantis-xray`
+
+## Update ##
+You can upgrade to the latest package release with the command: `pip3 install mantis-xray -U`.
+It is recommended that you also upgrade the dependencies with: `pip3 install mantis-xray -U --upgrade-strategy "eager"`
+
+## Run ##
+Installation via pip provides the `mantis-xray` command (alternatively `python3 -m mantis_xray`) to start the Mantis GUI.
+
+## User Guide ##
+Mantis User Guide can be found on the project Wiki pages [Home](https://github.com/mlerotic/spectromicroscopy/wiki).
+
+## References ##
+
+Please use the following reference when quoting Mantis
+
+Lerotic M, Mak R, Wirick S, Meirer F, Jacobsen C. MANTiS: a program for the analysis of X-ray spectromicroscopy data. J. Synchrotron Rad. 2014 Sep; 21(5); 1206–1212 [http://dx.doi.org/10.1107/S1600577514013964]
+
+
diff --git a/README.md b/README.md
index 4feab31..df7163d 100644
--- a/README.md
+++ b/README.md
@@ -13,11 +13,15 @@ Mantis package and binaries can be downloaded from
 [spectromicroscopy.com](http://spectromicroscopy.com).
 Alternatively, you can install [Python](https://www.python.org/downloads/) and then run the command: `python3 -m pip install mantis-xray`
 
+## Update ##
+You can upgrade to the latest package release with the command: `pip3 install mantis-xray -U`.
+It is recommended that you also upgrade the dependencies with: `pip3 install mantis-xray -U --upgrade-strategy "eager"`
+
 ## Run ##
-Installation via pip provides the `mantis-xray` command to start the Mantis GUI.
+Installation via pip provides the `mantis-xray` command (alternatively `python3 -m mantis_xray`) to start the Mantis GUI.
 
 ## User Guide ##
-Mantis User Guide can be found on https://docs.spectromicroscopy.com/.
+Mantis User Guide can be found on the project Wiki pages [Home](https://github.com/mlerotic/spectromicroscopy/wiki).
 
 ## References ##
 
diff --git a/mantis_xray.egg-info/PKG-INFO b/mantis_xray.egg-info/PKG-INFO
index 9fcf799..cc0bbeb 100644
--- a/mantis_xray.egg-info/PKG-INFO
+++ b/mantis_xray.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: mantis-xray
-Version: 3.0.11
+Version: 3.1.8
 Summary: MANTiS is a Multivariate ANalysis Tool for x-ray Spectromicroscopy
 Home-page: https://spectromicroscopy.com/
 Author: Mirna Lerotic
@@ -8,33 +8,6 @@ Author-email: mirna@2ndlookconsulting.com
 License: UNKNOWN
 Project-URL: Code, https://github.com/mlerotic/spectromicroscopy
 Project-URL: Documentation, https://docs.spectromicroscopy.com
-Description: # Spectromicroscopy #
-        [Spectromicroscopy](http://spectromicroscopy.com) combines spectral data with microscopy,
-        where typical datasets consist of a stack of microscopic images
-        taken across an energy range. Due to the data complexity, manual analysis 
-        can be time consuming and inefficient, whereas multivariate analysis tools 
-        not only reduce the time needed but also can uncover hidden trends in the data.
-        
-        # Mantis #
-        [MANTiS](http://spectromicroscopy.com) is Multivariate ANalysis Tool for Spectromicroscopy developed in Python by [2nd Look Consulting](http://2ndlookconsulting.com). It uses principal component analysis and cluster analysis to classify pixels according to spectral similarity.
-        
-        ## Download ##
-        Mantis package and binaries can be downloaded from 
-        [spectromicroscopy.com](http://spectromicroscopy.com).
-        Alternatively, you can install [Python](https://www.python.org/downloads/) and then run the command: `python3 -m pip install mantis-xray`
-        
-        ## Run ##
-        Installation via pip provides the `mantis-xray` command to start the Mantis GUI.
-        
-        ## User Guide ##
-        Mantis User Guide can be found on https://docs.spectromicroscopy.com/.
-        
-        ## References ##
-        
-        Please use the following reference when quoting Mantis
-        
-        Lerotic M, Mak R, Wirick S, Meirer F, Jacobsen C. MANTiS: a program for the analysis of X-ray spectromicroscopy data. J. Synchrotron Rad. 2014 Sep; 21(5); 1206–1212 [http://dx.doi.org/10.1107/S1600577514013964]
-        
 Platform: UNKNOWN
 Classifier: Programming Language :: Python :: 3
 Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -43,4 +16,37 @@ Classifier: Topic :: Scientific/Engineering
 Requires-Python: >=3
 Description-Content-Type: text/markdown
 Provides-Extra: netCDF
-Provides-Extra: SIRT
+License-File: LICENSE
+
+# Spectromicroscopy #
+[Spectromicroscopy](http://spectromicroscopy.com) combines spectral data with microscopy,
+where typical datasets consist of a stack of microscopic images
+taken across an energy range. Due to the data complexity, manual analysis 
+can be time consuming and inefficient, whereas multivariate analysis tools 
+not only reduce the time needed but also can uncover hidden trends in the data.
+
+# Mantis #
+[MANTiS](http://spectromicroscopy.com) is Multivariate ANalysis Tool for Spectromicroscopy developed in Python by [2nd Look Consulting](http://2ndlookconsulting.com). It uses principal component analysis and cluster analysis to classify pixels according to spectral similarity.
+
+## Download ##
+Mantis package and binaries can be downloaded from 
+[spectromicroscopy.com](http://spectromicroscopy.com).
+Alternatively, you can install [Python](https://www.python.org/downloads/) and then run the command: `python3 -m pip install mantis-xray`
+
+## Update ##
+You can upgrade to the latest package release with the command: `pip3 install mantis-xray -U`.
+It is recommended that you also upgrade the dependencies with: `pip3 install mantis-xray -U --upgrade-strategy "eager"`
+
+## Run ##
+Installation via pip provides the `mantis-xray` command (alternatively `python3 -m mantis_xray`) to start the Mantis GUI.
+
+## User Guide ##
+Mantis User Guide can be found on the project Wiki pages [Home](https://github.com/mlerotic/spectromicroscopy/wiki).
+
+## References ##
+
+Please use the following reference when quoting Mantis
+
+Lerotic M, Mak R, Wirick S, Meirer F, Jacobsen C. MANTiS: a program for the analysis of X-ray spectromicroscopy data. J. Synchrotron Rad. 2014 Sep; 21(5); 1206–1212 [http://dx.doi.org/10.1107/S1600577514013964]
+
+
diff --git a/mantis_xray.egg-info/SOURCES.txt b/mantis_xray.egg-info/SOURCES.txt
index 8b193ae..0fe56da 100644
--- a/mantis_xray.egg-info/SOURCES.txt
+++ b/mantis_xray.egg-info/SOURCES.txt
@@ -9,6 +9,7 @@ mantis_xray/__main__.py
 mantis_xray/analyze.py
 mantis_xray/data_stack.py
 mantis_xray/data_struct.py
+mantis_xray/dialogalign.ui
 mantis_xray/helpers.py
 mantis_xray/henke.py
 mantis_xray/henke.xdr
@@ -16,8 +17,14 @@ mantis_xray/logos.py
 mantis_xray/mantis.py
 mantis_xray/mantis_qt.py
 mantis_xray/nnma.py
+mantis_xray/pageloaddata.ui
 mantis_xray/pagemap.ui
+mantis_xray/showalign2.ui
+mantis_xray/showartefacts.ui
 mantis_xray/showhistogram.ui
+mantis_xray/showmulticrop.ui
+mantis_xray/showspectralroi.ui
+mantis_xray/stylesheet_global.qss
 mantis_xray/tomo_reconstruction.py
 mantis_xray.egg-info/PKG-INFO
 mantis_xray.egg-info/SOURCES.txt
@@ -51,4 +58,6 @@ mantis_xray/images/document-open.png
 mantis_xray/images/help-browser.png
 mantis_xray/images/logo-2l-32.ico
 mantis_xray/images/media-floppy.png
-mantis_xray/images/open-sl.png
\ No newline at end of file
+mantis_xray/images/mirror.png
+mantis_xray/images/open-sl.png
+mantis_xray/images/rotate.png
\ No newline at end of file
diff --git a/mantis_xray.egg-info/requires.txt b/mantis_xray.egg-info/requires.txt
index fdb14a1..6c98b20 100644
--- a/mantis_xray.egg-info/requires.txt
+++ b/mantis_xray.egg-info/requires.txt
@@ -1,14 +1,12 @@
+Pillow
 PyQt5
-numpy
-scipy
-matplotlib
 h5py
-Pillow
 lxml
+matplotlib
+numpy
 pyqtgraph
-
-[SIRT]
 scikit-image
+scipy
 
 [netCDF]
 netcdf4-python
diff --git a/mantis_xray/__init__.py b/mantis_xray/__init__.py
index 7ee0829..a526423 100644
--- a/mantis_xray/__init__.py
+++ b/mantis_xray/__init__.py
@@ -1 +1 @@
-__version__ = '3.0.11'
+__version__ = '3.1.08'
diff --git a/mantis_xray/__main__.py b/mantis_xray/__main__.py
index 13f8125..4de727d 100644
--- a/mantis_xray/__main__.py
+++ b/mantis_xray/__main__.py
@@ -1,4 +1,4 @@
-import sys
+import sys, getopt
 
 
 def main(args=None):
@@ -8,10 +8,23 @@ def main(args=None):
 
     # Do argument parsing here (eg. with argparse) and anything else
     # you want your project to do. Return values are exit codes.
+    try:
+        options, extraParams = getopt.getopt(args, '', ['batch', 'nnma'])
+    except:
+        print('Error - wrong command line option used. Available options are --batch and --nnma')
+        return
     
-    from . import mantis_qt
-    mantis_qt.main()  # Open the GUI
-
+    batch_mode = False
+    for opt, arg in options:
+        if opt in '--batch':
+            batch_mode = True
+    
+    if batch_mode:
+        from . import mantis
+        mantis.main()
+    else:
+        from . import mantis_qt
+        mantis_qt.main()  # Open the GUI
 
 if __name__ == "__main__":
     sys.exit(main())
diff --git a/mantis_xray/data_stack.py b/mantis_xray/data_stack.py
index 2da6df2..841dfc5 100755
--- a/mantis_xray/data_stack.py
+++ b/mantis_xray/data_stack.py
@@ -19,13 +19,12 @@
 from __future__ import division
 from __future__ import print_function
 
-
 import numpy as np
 import scipy as sp
 import scipy.interpolate
 import scipy.ndimage
-import h5py 
-import datetime 
+import h5py
+import datetime
 import os
 
 from .file_plugins import file_stk
@@ -36,24 +35,25 @@ from .file_plugins import file_dataexch_hdf5
 
 from . import data_struct
 
-#----------------------------------------------------------------------
+
+# ----------------------------------------------------------------------
 class data:
     def __init__(self, data_struct):
         self.data_struct = data_struct
-        self.i0_dwell = None 
+        self.i0_dwell = None
+        self.i0data = np.zeros(1)
         self.n_ev = 0
         self.n_theta = 0
-        self.shifts=[]
+        self.shifts = []
         self.stack4D = None
-        
 
-#----------------------------------------------------------------------   
+    # ----------------------------------------------------------------------
     def new_data(self):
         self.n_cols = 0
         self.n_rows = 0
         self.n_ev = 0
-               
-        self.x_dist = 0       
+
+        self.x_dist = 0
         self.y_dist = 0
 
         self.x_start = 0
@@ -63,150 +63,135 @@ class data:
         self.x_pxsize = 0
         self.y_pxsize = 0
         self.squarepx = True
-        
-        self.i0_dwell = None 
 
-        self.ev = 0         
+        self.i0_dwell = None
+
+        self.ev = 0
         self.absdata = 0
 
-        
-        self.i0data = 0
+        self.i0data = np.zeros(1)
         self.evi0 = 0
-        
+
         self.od = 0
         self.od3d = 0
-        
+
         self.xshifts = 0
         self.yshifts = 0
         self.shifts = []
-        
+
         self.stack4D = None
         self.n_theta = 0
         self.theta = 0
         self.od4D = 0
-        
 
         self.data_struct.spectromicroscopy.normalization.white_spectrum = None
         self.data_struct.spectromicroscopy.normalization.white_spectrum_energy = None
         self.data_struct.spectromicroscopy.normalization.white_spectrum_energy_units = None
-        
-        self.data_struct.spectromicroscopy.optical_density = None        
-           
-#----------------------------------------------------------------------   
+
+        self.data_struct.spectromicroscopy.optical_density = None
+
+    # ----------------------------------------------------------------------
     def read_stk_i0(self, filename, extension):
         if extension == '.xas':
-            file_stk.read_stk_i0_xas(self,filename)
+            file_stk.read_stk_i0_xas(self, filename)
         elif extension == '.csv':
-            file_stk.read_stk_i0_csv(self,filename)
-            
+            file_stk.read_stk_i0_csv(self, filename)
+
         self.calculate_optical_density()
         self.fill_h5_struct_normalization()
-        
-        
-#----------------------------------------------------------------------   
+
+    # ----------------------------------------------------------------------
     def read_sdf_i0(self, filename):
-        file_sdf.read_sdf_i0(self,filename)
+        file_sdf.read_sdf_i0(self, filename)
         self.calculate_optical_density()
-        
+
         self.fill_h5_struct_normalization()
-        
-        
-#----------------------------------------------------------------------   
+
+    # ----------------------------------------------------------------------
     def read_xrm_ReferenceImages(self, filenames):
 
-        
         self.calculate_optical_density_from_refimgs(filenames)
-        
+
         self.fill_h5_struct_normalization()
-        
-        
-#----------------------------------------------------------------------          
-    def read_h54D(self, filename):    
 
+    # ----------------------------------------------------------------------
+    def read_h54D(self, filename):
 
         file_dataexch_hdf5.read(filename, self)
 
         if self.data_struct.spectromicroscopy.normalization.white_spectrum is not None:
-            
             self.calculate_optical_density()
-            self.fill_h5_struct_normalization()           
+            self.fill_h5_struct_normalization()
 
         self.scale_bar()
-            
-#---------------------------------------------------------------------- 
-    def read_ncb4D(self, filenames):    
-        self.new_data()  
+
+    # ----------------------------------------------------------------------
+    def read_ncb4D(self, filenames):
+        self.new_data()
         file_ncb.read_ncb4D(self, filenames)
-        
         now = datetime.datetime.now()
-        
+
         self.data_struct.implements = 'information:exchange:spectromicroscopy'
         self.data_struct.version = '1.0'
-        
+
         self.data_struct.information.file_creation_datetime = now.strftime("%Y-%m-%dT%H:%M")
         self.data_struct.information.comment = 'Converted in Mantis'
-        
-        
+
         self.data_struct.exchange.data = self.stack4D
         self.data_struct.exchange.data_signal = 1
-        self.data_struct.exchange.data_axes='x:y:energy:theta'
-        
-        self.data_struct.exchange.theta = self.theta
+        self.data_struct.exchange.data_axes = 'x:y:energy:theta'
+
+        self.data_struct.exchange.theta = np.array(self.theta)
         self.data_struct.exchange.theta_units = 'degrees'
-        
-        
+
         self.data_struct.exchange.x = self.x_dist
         self.data_struct.exchange.y = self.y_dist
-        
-        
+
         self.scale_bar()
 
-#---------------------------------------------------------------------- 
-    def read_ncb4Denergy(self, filename):    
-        
-        f = open(str(filename),'rU')
-        
-        elist = []  
-    
+    # ----------------------------------------------------------------------
+    def read_ncb4Denergy(self, filename):
+
+        f = open(str(filename), 'rU')
+
+        elist = []
+
         for line in f:
             if line.startswith('*'):
                 if 'Common name' in line:
                     spectrum_common_name = line.split(':')[-1].strip()
 
             else:
-                e, = [float (x) for x in line.split()] 
+                e, = [float(x) for x in line.split()]
                 elist.append(e)
-                
+
         self.ev = np.array(elist)
-        
-                
+
         f.close()
 
         self.n_ev = self.ev.size
-        self.data_struct.exchange.energy=self.ev
+        self.data_struct.exchange.energy = self.ev
         self.data_struct.exchange.energy_units = 'ev'
-        
 
-#---------------------------------------------------------------------- 
-    def read_dpt(self, filename):    
-        self.new_data()  
-        
+    # ----------------------------------------------------------------------
+    def read_dpt(self, filename):
+        self.new_data()
+
         n_rows = 11
-        n_cols = 8 
-        
-        imgstack = np.zeros((n_rows,n_cols))
-        
+        n_cols = 8
+
+        imgstack = np.zeros((n_rows, n_cols))
+
+        f = open(str(filename), 'r')
+
+        elist = []
 
-        f = open(str(filename),'r')
-        
-        elist = []   
-    
         for line in f:
             if line.startswith("*"):
                 pass
             else:
                 x = line.split(',')
-                e = float (x[0]) 
+                e = float(x[0])
                 x = x[1:]
                 data = []
                 for i in range(len(x)):
@@ -215,433 +200,403 @@ class data:
                 data = np.array(data)
                 data = np.reshape(data, (n_rows, n_cols), order='F')
                 imgstack = np.dstack((imgstack, data))
-                
-                
-        imgstack = imgstack[:,:,1:]
-                
+
+        imgstack = imgstack[:, :, 1:]
+
         f.close()
-        
-        
-            
+
         self.n_cols = imgstack.shape[0]
         self.n_rows = imgstack.shape[1]
         self.n_ev = imgstack.shape[2]
-        
-        
+
         pixelsize = 1
-        #Since we do not have a scanning microscope we fill the x_dist and y_dist from pixel_size
-        self.x_dist = np.arange(np.float(self.n_cols))*pixelsize
-        self.y_dist = np.arange(np.float(self.n_rows))*pixelsize
+        # Since we do not have a scanning microscope we fill the x_dist and y_dist from pixel_size
+        self.x_dist = np.arange(np.float(self.n_cols)) * pixelsize
+        self.y_dist = np.arange(np.float(self.n_rows)) * pixelsize
 
-                
         self.ev = np.array(elist)
 
         msec = np.ones((self.n_ev))
-         
+
         self.data_dwell = msec
-                       
+
         self.absdata = imgstack
-                
-        #Check if the energies are consecutive, if they are not sort the data
+
+        # Check if the energies are consecutive, if they are not sort the data
         sort = 0
         for i in range(self.n_ev - 1):
-            if self.ev[i] > self.ev[i+1]:
+            if self.ev[i] > self.ev[i + 1]:
                 sort = 1
                 break
         if sort == 1:
             sortind = np.argsort(self.ev)
             self.ev = self.ev[sortind]
-            self.absdata = self.absdata[:,:,sortind]
+            self.absdata = self.absdata[:, :, sortind]
 
-        
-#         self.original_n_cols = imgstack.shape[0]
-#         self.original_n_rows = imgstack.shape[1]
-#         self.original_n_ev = imgstack.shape[2]
-#         self.original_ev = self.ev.copy()
-#         self.original_absdata = self.absdata.copy()
+        #         self.original_n_cols = imgstack.shape[0]
+        #         self.original_n_rows = imgstack.shape[1]
+        #         self.original_n_ev = imgstack.shape[2]
+        #         self.original_ev = self.ev.copy()
+        #         self.original_absdata = self.absdata.copy()
 
-       
         self.fill_h5_struct_from_stk()
-         
+
         self.scale_bar()
-        
-        
-        #Fix the normalization
+
+        # Fix the normalization
         self.evi0 = self.ev.copy()
         self.i0data = np.ones(self.n_ev)
-        
+
         self.i0_dwell = self.data_dwell
-   
-        
+
         self.fill_h5_struct_normalization()
-        
-        #Optical density does not have to be calculated - use raw data
-        
+
+        # Optical density does not have to be calculated - use raw data
+
         self.od3d = self.absdata.copy()
-        
-        self.od = np.reshape(self.od3d, (n_rows*n_cols, self.n_ev), order='F')
-        
-        
-                
-#---------------------------------------------------------------------- 
-    def fill_h5_struct_from_stk(self):   
-        
-        
+
+        self.od = np.reshape(self.od3d, (n_rows * n_cols, self.n_ev), order='F')
+
+    # ----------------------------------------------------------------------
+    def fill_h5_struct_from_stk(self):
+
         now = datetime.datetime.now()
-        
+
         self.data_struct.implements = 'information:exchange:spectromicroscopy'
         self.data_struct.version = '1.0'
-        
+
         self.data_struct.information.file_creation_datetime = now.strftime("%Y-%m-%dT%H:%M")
         self.data_struct.information.comment = 'Converted in Mantis'
-        
-        
+
         self.data_struct.exchange.data = self.absdata
         self.data_struct.exchange.data_signal = 1
-        self.data_struct.exchange.data_axes='x:y:energy'
-        
-        self.data_struct.exchange.energy=self.ev
+        self.data_struct.exchange.data_axes = 'x:y:energy'
+
+        self.data_struct.exchange.energy = self.ev
         self.data_struct.exchange.energy_units = 'ev'
-        
-        
+
         self.data_struct.exchange.x = self.x_dist
         self.data_struct.exchange.y = self.y_dist
 
-        
-#---------------------------------------------------------------------- 
-    def fill_h5_struct_normalization(self):   
-        
-        self.data_struct.spectromicroscopy.normalization.white_spectrum = self.i0data 
+    # ----------------------------------------------------------------------
+    def fill_h5_struct_normalization(self):
+
+        self.data_struct.spectromicroscopy.normalization.white_spectrum = self.i0data
         self.data_struct.spectromicroscopy.normalization.white_spectrum_energy = self.evi0
         self.data_struct.spectromicroscopy.normalization.white_spectrum_energy_units = 'eV'
-        
+
         if self.stack4D is None:
             self.data_struct.spectromicroscopy.optical_density = self.od
         else:
             self.data_struct.spectromicroscopy.optical_density = self.od4D
-        
-    
-#----------------------------------------------------------------------   
+
+    # ----------------------------------------------------------------------
     def calc_histogram(self):
-        #calculate average flux for each pixel
-        self.averageflux = np.mean(self.absdata,axis=2)
+        # calculate average flux for each pixel
+        self.averageflux = np.nanmean(self.absdata, axis=2)
         self.histogram = self.averageflux
-        
+
         return
-        
-        
-#----------------------------------------------------------------------
+
+    # ----------------------------------------------------------------------
     def i0_from_histogram(self, i0_indices):
 
         self.evi0hist = self.ev.copy()
 
-        #i0_indices = np.where((fluxmin<=self.averageflux)&(self.averageflux<=fluxmax))
+        # i0_indices = np.where((fluxmin<=self.averageflux)&(self.averageflux<=fluxmax))
 
         self.evi0 = self.ev.copy()
-        
+
         self.i0_dwell = self.data_dwell
-                
+
         if self.stack4D is None:
             self.i0datahist = np.zeros((self.n_ev))
-            self.i0data = self.i0datahist 
+            self.i0data = self.i0datahist
             if np.any(i0_indices):
-                invnumel = 1./self.averageflux[i0_indices].shape[0]
-                for ie in range(self.n_ev):  
-                    thiseng_abs = self.absdata[:,:,ie]
-                    self.i0datahist[ie] = np.sum(thiseng_abs[i0_indices])*invnumel
+                #invnumel = 1. / self.averageflux[i0_indices].shape[0]
+                for ie in range(self.n_ev):
+                    thiseng_abs = self.absdata[:, :, ie]
+                    #self.i0datahist[ie] = np.sum(thiseng_abs[i0_indices]) * invnumel
+                    finite_vals = thiseng_abs[i0_indices][np.isfinite(thiseng_abs[i0_indices])]
+                    if len(finite_vals)>0:
+                        self.i0datahist[ie] = np.nanmean(finite_vals)
+                    else:
+                        self.i0datahist[ie] = self.i0datahist[ie-1] #If this fails on the first image then the data is probably completely empty anyway
+
+            self.calculate_optical_density()
 
-            self.calculate_optical_density()   
-            
         else:
             self.i0datahist = np.zeros((self.n_ev, self.n_theta))
-            self.i0data = self.i0datahist 
+            self.i0data = self.i0datahist
             self.od4D = np.zeros((self.n_cols, self.n_rows, self.n_ev, self.n_theta))
-            
+
             if np.any(i0_indices):
-                invnumel = 1./self.averageflux[i0_indices].shape[0]
+                invnumel = 1. / self.averageflux[i0_indices].shape[0]
             else:
                 return
-            
+
             for i in range(self.n_theta):
-                for ie in range(self.n_ev):  
-                    thiseng_abs = self.stack4D[:,:,ie, i]
-                    self.i0datahist[ie,i] = np.sum(thiseng_abs[i0_indices])*invnumel
-                        
-            self.calculate_optical_density_4D() 
-                
+                for ie in range(self.n_ev):
+                    thiseng_abs = self.stack4D[:, :, ie, i]
+                    self.i0datahist[ie, i] = np.sum(thiseng_abs[i0_indices]) * invnumel
+
+            self.calculate_optical_density_4D()
+
         self.fill_h5_struct_normalization()
-        
-        return    
-    
-#----------------------------------------------------------------------   
+
+        return
+
+    # ----------------------------------------------------------------------
     def UsePreNormalizedData(self):
-    
+
         self.evi0 = self.ev.copy()
         self.i0data = np.ones(self.n_ev)
-        
+
         self.i0_dwell = self.data_dwell
-        
+
         self.od = np.empty((self.n_cols, self.n_rows, self.n_ev))
         for i in range(self.n_ev):
-            self.od[:,:,i] = self.absdata[:,:,i]
-        
-           
+            self.od[:, :, i] = self.absdata[:, :, i]
+
         self.od3d = self.od.copy()
-        
-        n_pixels = self.n_cols*self.n_rows
-        #Optical density matrix is rearranged into n_pixelsxn_ev
+
+        n_pixels = self.n_cols * self.n_rows
+        # Optical density matrix is rearranged into n_pixelsxn_ev
         self.od = np.reshape(self.od, (n_pixels, self.n_ev), order='F')
-        
+
         if self.stack4D is not None:
             self.od4D = self.stack4D.copy()
-        
+
         self.fill_h5_struct_normalization()
-        
+
         return
-        
-    
-#----------------------------------------------------------------------   
+
+    # ----------------------------------------------------------------------
     def set_i0(self, i0data, evdata):
 
         self.evi0 = evdata
-        self.i0data = i0data 
-        
+        self.i0data = i0data
+
         self.i0_dwell = self.data_dwell
 
         self.calculate_optical_density()
-        
+
         self.fill_h5_struct_normalization()
-    
-        return  
-    
-#----------------------------------------------------------------------   
+
+        return
+
+    # ----------------------------------------------------------------------
     def reset_i0(self):
-        
 
-        self.i0_dwell = None 
+        self.i0_dwell = None
 
         self.i0data = 0
         self.evi0 = 0
-        
+
         self.od = 0
         self.od3d = 0
-        
+
         self.data_struct.spectromicroscopy.normalization.white_spectrum = None
         self.data_struct.spectromicroscopy.normalization.white_spectrum_energy = None
         self.data_struct.spectromicroscopy.normalization.white_spectrum_energy_units = None
-        
-        self.data_struct.spectromicroscopy.optical_density = None      
-    
-#----------------------------------------------------------------------   
-# Normalize the data: calculate optical density matrix D 
+
+        self.data_struct.spectromicroscopy.optical_density = None
+
+    # ----------------------------------------------------------------------
+    # Normalize the data: calculate optical density matrix D
     def calculate_optical_density(self):
-        
+
         if self.stack4D is not None:
             self.calculate_optical_density_4D()
             return
-            
-        n_pixels = self.n_cols*self.n_rows
+
+        n_pixels = self.n_cols * self.n_rows
         self.od = np.empty((self.n_cols, self.n_rows, self.n_ev))
-        
-        #little hack to deal with rounding errors
-        self.evi0[self.evi0.size-1] += 0.001
+
+        # little hack to deal with rounding errors
+        self.evi0[self.evi0.size - 1] += 0.001
         self.evi0[0] -= 0.001
+        if len(self.evi0) > 3: # >3 is needed to avoid boundary error!
+            fi0int = scipy.interpolate.interp1d(self.evi0.astype(np.double), self.i0data.astype(np.double),
+                                                kind='cubic', bounds_error=False, fill_value=0.0)
+        elif len(self.evi0) > 1: # use linear interpolation when there are fewer points
+            fi0int = scipy.interpolate.interp1d(self.evi0.astype(np.double), self.i0data.astype(np.double),
+                                                bounds_error=False, fill_value=0.0)
+        else: # use constant value when only a single value is available
+            fi0int = lambda x: self.i0data.astype(np.double)
         
-        if len(self.evi0) > 2:
-            fi0int = scipy.interpolate.interp1d(self.evi0.astype(np.double),self.i0data.astype(np.double), kind='cubic', bounds_error=False, fill_value=0.0)
-        else:
-            fi0int = scipy.interpolate.interp1d(self.evi0.astype(np.double),self.i0data.astype(np.double), bounds_error=False, fill_value=0.0)
         i0 = fi0int(self.ev)
-        
-         
+
         if (self.data_dwell is not None) and (self.i0_dwell is not None):
- 
-            i0 = i0*(self.data_dwell/self.i0_dwell)
-        
-        #zero out all negative values in the image stack
+            i0 = i0 * (self.data_dwell / self.i0_dwell)
+
+        # zero out all negative values in the image stack
         negative_indices = np.where(self.absdata <= 0)
         if negative_indices:
             self.absdata[negative_indices] = 0.01
-            
- 
+
         for i in range(self.n_ev):
-            self.od[:,:,i] = - np.log(self.absdata[:,:,i]/i0[i])
-         
-        #clean up the result
+            self.od[:, :, i] = - np.log(self.absdata[:, :, i] / i0[i])
+
+        # clean up the result
         nan_indices = np.where(np.isfinite(self.od) == False)
         if nan_indices:
             self.od[nan_indices] = 0
-             
+
         self.od3d = self.od.copy()
-         
-        #Optical density matrix is rearranged into n_pixelsxn_ev
+
+        # Optical density matrix is rearranged into n_pixelsxn_ev
         self.od = np.reshape(self.od, (n_pixels, self.n_ev), order='F')
-        
 
         return
- 
-#----------------------------------------------------------------------   
-# Normalize the data: calculate optical density matrix D 
+
+    # ----------------------------------------------------------------------
+    # Normalize the data: calculate optical density matrix D
     def calculate_optical_density_4D(self):
 
-        n_pixels = self.n_cols*self.n_rows
+        n_pixels = self.n_cols * self.n_rows
         self.od4D = np.zeros((self.n_cols, self.n_rows, self.n_ev, self.n_theta))
-        
-        #little hack to deal with rounding errors
-        self.evi0[self.evi0.size-1] += 0.001
-        
+
+        # little hack to deal with rounding errors
+        self.evi0[self.evi0.size - 1] += 0.001
+
         self.i0data = np.array(self.i0data)
         i0dims = self.i0data.shape
 
-        
         for ith in range(self.n_theta):
             self.od = np.empty((self.n_cols, self.n_rows, self.n_ev))
-            
+
             if len(i0dims) == 2:
-                self.i0data = self.i0datahist[:,ith]
-        
+                self.i0data = self.i0datahist[:, ith]
+
             if len(self.evi0) > 2:
-                fi0int = scipy.interpolate.interp1d(self.evi0, self.i0data, kind='cubic', bounds_error=False, fill_value=0.0)      
+                fi0int = scipy.interpolate.interp1d(self.evi0, self.i0data, kind='cubic', bounds_error=False,
+                                                    fill_value=0.0)
             else:
-                fi0int = scipy.interpolate.interp1d(self.evi0,self.i0data, bounds_error=False, fill_value=0.0)      
+                fi0int = scipy.interpolate.interp1d(self.evi0, self.i0data, bounds_error=False, fill_value=0.0)
             i0 = fi0int(self.ev)
-            
-             
+
             if (self.data_dwell is not None) and (self.i0_dwell is not None):
-     
-                i0 = i0*(self.data_dwell/self.i0_dwell)
-            
-            #zero out all negative values in the image stack
+                i0 = i0 * (self.data_dwell / self.i0_dwell)
+
+            # zero out all negative values in the image stack
             negative_indices = np.where(self.stack4D <= 0)
             if negative_indices:
                 self.stack4D[negative_indices] = 0.01
-                                
-     
+
             for i in range(self.n_ev):
-                self.od[:,:,i] = - np.log(self.stack4D[:,:,i,ith]/i0[i])
-             
-            #clean up the result
+                self.od[:, :, i] = - np.log(self.stack4D[:, :, i, ith] / i0[i])
+
+            # clean up the result
             nan_indices = np.where(np.isfinite(self.od) == False)
             if nan_indices:
                 self.od[nan_indices] = 0
-                 
-        
-            self.od4D[:,:,:,ith] = self.od[:,:,:]
-            
-                    
-                    
+
+            self.od4D[:, :, :, ith] = self.od[:, :, :]
+
         self.od3d = self.od.copy()
-         
-        #Optical density matrix is rearranged into n_pixelsxn_ev
+
+        # Optical density matrix is rearranged into n_pixelsxn_ev
         self.od = np.reshape(self.od, (n_pixels, self.n_ev), order='F')
 
-        return   
+        return
 
-#----------------------------------------------------------------------   
-# Normalize the data: calculate optical density matrix D 
+    # ----------------------------------------------------------------------
+    # Normalize the data: calculate optical density matrix D
     def calculate_optical_density_from_refimgs(self, files):
 
-        n_pixels = self.n_cols*self.n_rows
+        n_pixels = self.n_cols * self.n_rows
         self.od = np.empty((self.n_cols, self.n_rows, self.n_ev))
-                
-        #zero out all negative values in the image stack
+
+        # zero out all negative values in the image stack
         negative_indices = np.where(self.absdata <= 0)
         if negative_indices:
             self.absdata[negative_indices] = 0.01
-                           
 
-        #Load reference images
+        # Load reference images
         refimgs = np.empty((self.n_cols, self.n_rows, self.n_ev))
         refimgs_ev = []
         for i in range(len(files)):
-            ncols, nrows, iev, imgdata = file_xrm.read_xrm_fileinfo(files[i], readimgdata = True)
-            refimgs[:,:,i] = np.reshape(imgdata, (ncols, nrows), order='F')
+            ncols, nrows, iev, imgdata = file_xrm.read_xrm_fileinfo(files[i], readimgdata=True)
+            refimgs[:, :, i] = np.reshape(imgdata, (ncols, nrows), order='F')
             refimgs_ev.append(iev)
 
-        #Check if the energies are consecutive, if they are not sort the data
+        # Check if the energies are consecutive, if they are not sort the data
         consec = 0
         for i in range(len(refimgs_ev) - 1):
-            if refimgs_ev[i] > refimgs_ev[i+1]:
+            if refimgs_ev[i] > refimgs_ev[i + 1]:
                 consec = 1
                 break
         if consec == 1:
             sortind = np.argsort(refimgs_ev)
             refimgs_ev = refimgs_ev[sortind]
-            refimgs = refimgs[:,:,refimgs_ev]
-        
-            
+            refimgs = refimgs[:, :, refimgs_ev]
+
         for i in range(self.n_ev):
             if self.ev[i] != refimgs_ev[i]:
-                print ('Error, wrong reference image energy')
+                print('Error, wrong reference image energy')
                 return
-            
-            self.od[:,:,i] = - np.log(self.absdata[:,:,i]/refimgs[:,:,i])
-        
-        #clean up the result
+
+            self.od[:, :, i] = - np.log(self.absdata[:, :, i] / refimgs[:, :, i])
+
+        # clean up the result
         nan_indices = np.where(np.isfinite(self.od) == False)
         if nan_indices:
             self.od[nan_indices] = 0
-            
+
         self.od3d = self.od.copy()
-        
 
-        #Optical density matrix is rearranged into n_pixelsxn_ev
+        # Optical density matrix is rearranged into n_pixelsxn_ev
         self.od = np.reshape(self.od, (n_pixels, self.n_ev), order='F')
-        
-        
+
         self.evi0 = refimgs_ev
         self.i0data = np.ones((self.n_ev))
         self.i0_dwell = self.data_dwell
-        
-
-        return    
 
+        return
 
-#----------------------------------------------------------------------   
+    # ----------------------------------------------------------------------
     def scale_bar(self):
         self.x_start = np.min(self.x_dist)
         self.x_stop = np.max(self.x_dist)
-        self.x_pxsize = np.round(np.abs(self.x_stop-self.x_start)/(self.n_cols-1),5) # um per px in y direction, "-1" because stop-start is 1 px shorter than n_rows
+        self.x_pxsize = np.round(np.abs(self.x_stop - self.x_start) / (self.n_cols - 1),
+                                 5)  # um per px in y direction, "-1" because stop-start is 1 px shorter than n_rows
 
         self.y_start = np.min(self.y_dist)
         self.y_stop = np.max(self.y_dist)
-        self.y_pxsize = np.round(np.abs(self.y_stop-self.y_start)/(self.n_rows-1),5) # um per px in y direction, "-1" because stop-start is 1 px shorter than n_rows
+        self.y_pxsize = np.round(np.abs(self.y_stop - self.y_start) / (self.n_rows - 1),
+                                 5)  # um per px in y direction, "-1" because stop-start is 1 px shorter than n_rows
 
         if self.x_pxsize == self.y_pxsize:
             self.squarepx = True
         else:
             self.squarepx = False
-        bar_microns = 0.2*np.abs(self.x_stop-self.x_start)
-        
-        
+        bar_microns = 0.2 * np.abs(self.x_stop - self.x_start)
+
         if bar_microns >= 10.:
-            bar_microns = 10.*int(0.5+0.1*int(0.5+bar_microns))
-            bar_string = str(int(0.01+bar_microns)).strip()
-        elif bar_microns >= 1.:      
-            bar_microns = float(int(0.5+bar_microns))
+            bar_microns = 10. * int(0.5 + 0.1 * int(0.5 + bar_microns))
+            bar_string = str(int(0.01 + bar_microns)).strip()
+        elif bar_microns >= 1.:
+            bar_microns = float(int(0.5 + bar_microns))
             if bar_microns == 1.:
                 bar_string = '1'
             else:
-                bar_string = str(int(0.01+bar_microns)).strip()
+                bar_string = str(int(0.01 + bar_microns)).strip()
         else:
-            bar_microns = np.maximum(0.1*int(0.5+10*bar_microns),0.1)
+            bar_microns = np.maximum(0.1 * int(0.5 + 10 * bar_microns), 0.1)
             bar_string = str(bar_microns).strip()
-            
+
         self.scale_bar_string = bar_string
 
+        self.scale_bar_pixels_x = int(0.5 + float(self.n_cols) *
+                                      float(bar_microns) / float(abs(self.x_stop - self.x_start)))
+
+        self.scale_bar_pixels_y = int(0.01 * self.n_rows)
 
-        self.scale_bar_pixels_x = int(0.5+float(self.n_cols)*
-                       float(bar_microns)/float(abs(self.x_stop-self.x_start)))
-        
-        self.scale_bar_pixels_y = int(0.01*self.n_rows)
-        
         if self.scale_bar_pixels_y < 2:
-                self.scale_bar_pixels_y = 2
-                
-             
-             
-    
-#----------------------------------------------------------------------   
+            self.scale_bar_pixels_y = 2
+
+    # ----------------------------------------------------------------------
     def write_xas(self, filename, evdata, data):
         f = open(filename, 'w')
         print('*********************  X-ray Absorption Data  ********************', file=f)
@@ -650,7 +605,7 @@ class data:
         print('* Common name: ', file=f)
         print('* Edge: ', file=f)
         print('* Acquisition mode: ', file=f)
-        print('* Source and purity: ' , file=f)
+        print('* Source and purity: ', file=f)
         print('* Comments: Stack list ROI ""', file=f)
         print('* Delta eV: ', file=f)
         print('* Min eV: ', file=f)
@@ -672,13 +627,13 @@ class data:
         print('*--------------------------------------------------------------', file=f)
         for ie in range(self.n_ev):
             print('\t {0:06.2f}, {1:06f}'.format(evdata[ie], data[ie]), file=f)
-        
+
         f.close()
-    
-        return  
-    
-#----------------------------------------------------------------------   
-    def write_csv(self, filename, evdata, data, cname = ''):
+
+        return
+
+    # ----------------------------------------------------------------------
+    def write_csv(self, filename, evdata, data, cname=''):
         f = open(filename, 'w')
         print('*********************  X-ray Absorption Data  ********************', file=f)
         print('*', file=f)
@@ -686,7 +641,7 @@ class data:
         print('* Common name: {0}'.format(cname), file=f)
         print('* Edge: ', file=f)
         print('* Acquisition mode: ', file=f)
-        print('* Source and purity: ' , file=f)
+        print('* Source and purity: ', file=f)
         print('* Comments: Stack list ROI ""', file=f)
         print('* Delta eV: ', file=f)
         print('* Min eV: ', file=f)
@@ -708,92 +663,89 @@ class data:
         print('*--------------------------------------------------------------', file=f)
         for ie in range(self.n_ev):
             print('{0:06.2f}, {1:06f}'.format(evdata[ie], data[ie]), file=f)
-        
+
         f.close()
-    
-        return  
-    
-#----------------------------------------------------------------------   
-#Read x-ray absorption spectrum
+
+        return
+
+    # ----------------------------------------------------------------------
+    # Read x-ray absorption spectrum
     def read_xas(self, filename):
-        
+
         spectrum_common_name = ' '
- 
-        f = open(str(filename),'rU')
-        
+
+        f = open(str(filename), 'rU')
+
         elist = []
-        ilist = []    
-    
+        ilist = []
+
         for line in f:
             if line.startswith('*'):
                 if 'Common name' in line:
                     spectrum_common_name = line.split(':')[-1].strip()
 
             else:
-                e, i = [float (x) for x in line.split()] 
+                e, i = [float(x) for x in line.split()]
                 elist.append(e)
                 ilist.append(i)
-                
+
         spectrum_evdata = np.array(elist)
-        spectrum_data = np.array(ilist) 
-                
+        spectrum_data = np.array(ilist)
+
         f.close()
-        
-        if spectrum_evdata[-1]<spectrum_evdata[0]:
+
+        if spectrum_evdata[-1] < spectrum_evdata[0]:
             spectrum_evdata = spectrum_evdata[::-1]
             spectrum_data = spectrum_data[::-1]
-            
+
         if spectrum_common_name == ' ':
             spectrum_common_name = os.path.splitext(os.path.basename(str(filename)))[0]
-        
+
         return spectrum_evdata, spectrum_data, spectrum_common_name
-    
-    
-#----------------------------------------------------------------------   
-#Read x-ray absorption spectrum
+
+    # ----------------------------------------------------------------------
+    # Read x-ray absorption spectrum
     def read_txt(self, filename):
-        
+
         spectrum_common_name = os.path.splitext(os.path.basename(str(filename)))[0]
- 
-        f = open(str(filename),'rU')
-        
+
+        f = open(str(filename), 'rU')
+
         elist = []
-        ilist = []    
-    
+        ilist = []
+
         for line in f:
             if line.startswith('%'):
                 pass
             else:
-                e, i = [float (x) for x in line.split()] 
+                e, i = [float(x) for x in line.split()]
                 elist.append(e)
                 ilist.append(i)
-                
+
         spectrum_evdata = np.array(elist)
-        spectrum_data = np.array(ilist) 
-                
+        spectrum_data = np.array(ilist)
+
         f.close()
-        
-        if spectrum_evdata[-1]<spectrum_evdata[0]:
+
+        if spectrum_evdata[-1] < spectrum_evdata[0]:
             spectrum_evdata = spectrum_evdata[::-1]
             spectrum_data = spectrum_data[::-1]
-        
+
         return spectrum_evdata, spectrum_data, spectrum_common_name
 
-#----------------------------------------------------------------------   
-#Read x-ray absorption spectrum
+    # ----------------------------------------------------------------------
+    # Read x-ray absorption spectrum
     def read_csv(self, filename):
-        
+
         spectrum_common_name = ' '
- 
-        f = open(str(filename),'rU')
-        
+
+        f = open(str(filename), 'rU')
+
         elist = []
-        ilist = []    
-        
-        
-        #Check the first character of the line and skip if not a number
-        allowedchars = ['0','1','2','3','4','5','6','7','8','9','-','.']
-    
+        ilist = []
+
+        # Check the first character of the line and skip if not a number
+        allowedchars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.']
 
         for line in f:
             if line.startswith('*'):
@@ -802,118 +754,109 @@ class data:
             elif line[0] not in allowedchars:
                 continue
             else:
-                e, i = [float (x) for x in line.split(',')] 
+                e, i = [float(x) for x in line.split(',')]
                 elist.append(e)
                 ilist.append(i)
-                
-                
+
         spectrum_evdata = np.array(elist)
-        spectrum_data = np.array(ilist) 
-                
+        spectrum_data = np.array(ilist)
+
         f.close()
-        
-        if spectrum_evdata[-1]<spectrum_evdata[0]:
+
+        if spectrum_evdata[-1] < spectrum_evdata[0]:
             spectrum_evdata = spectrum_evdata[::-1]
             spectrum_data = spectrum_data[::-1]
-            
-            
+
         if spectrum_common_name == ' ':
             spectrum_common_name = os.path.splitext(os.path.basename(str(filename)))[0]
-        
+
         return spectrum_evdata, spectrum_data, spectrum_common_name
-        
-                
-    
-#----------------------------------------------------------------------   
-#Register images using Fourier Shift Theorem
-#EdgeEnhancement: 0 = no edge enhacement; 1 = sobel; 2 = prewitt
-    def register_images(self, ref_image, image2, have_ref_img_fft = False, edge_enhancement = 0):
-        
+
+    # ----------------------------------------------------------------------
+    # Register images using Fourier Shift Theorem
+    # EdgeEnhancement: 0 = no edge enhacement; 1 = sobel; 2 = prewitt
+    def register_images(self, ref_image, image2, have_ref_img_fft=False, edge_enhancement=0):
+
         if have_ref_img_fft == False:
             if edge_enhancement == 1:
                 self.ref_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(scipy.ndimage.filters.sobel(ref_image))))
             elif edge_enhancement == 2:
-                self.ref_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(scipy.ndimage.filters.prewitt(ref_image))))  
+                self.ref_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(scipy.ndimage.filters.prewitt(ref_image))))
             else:
-                self.ref_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(ref_image)))              
-            
+                self.ref_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(ref_image)))
+
         if edge_enhancement == 1:
             img2_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(scipy.ndimage.filters.sobel(image2))))
         if edge_enhancement == 2:
-            img2_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(scipy.ndimage.filters.prewitt(image2))))     
+            img2_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(scipy.ndimage.filters.prewitt(image2))))
         else:
             img2_fft = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(image2)))
-        
-        fr = (self.ref_fft*img2_fft.conjugate())/(np.abs(self.ref_fft)*np.abs(img2_fft))
+
+        fr = (self.ref_fft * img2_fft.conjugate()) / (np.abs(self.ref_fft) * np.abs(img2_fft))
         fr = np.fft.fftshift(np.fft.ifft2(np.fft.fftshift(fr)))
         fr = np.abs(fr)
-        
+
         shape = ref_image.shape
-        
+
         xc, yc = np.unravel_index(np.argmax(fr), shape)
-        
+
         # Limit the search to 1 pixel border
         if xc == 0:
-            xc=1
-        if xc == shape[0]-1:
-            xc = shape[0]-2
-            
+            xc = 1
+        if xc == shape[0] - 1:
+            xc = shape[0] - 2
+
         if yc == 0:
-            yc=1
-        if yc == shape[1]-1:
-            yc = shape[1]-2
-            
-            
-        #Use peak fit to find the shifts 
-        xpts = [xc-1,xc,xc+1]
-        ypts = fr[xpts,yc]     
+            yc = 1
+        if yc == shape[1] - 1:
+            yc = shape[1] - 2
+
+        # Use peak fit to find the shifts
+        xpts = [xc - 1, xc, xc + 1]
+        ypts = fr[xpts, yc]
         xf, fit = self.peak_fit(xpts, ypts)
 
-        xpts = [yc-1,yc,yc+1]
-        ypts = fr[xc,xpts]     
-        yf, fit = self.peak_fit(xpts, ypts)   
-              
-        
-        xshift = xf - np.float(shape[0])/2.0
-        yshift = yf - np.float(shape[1])/2.0
-        
-                
-                
+        xpts = [yc - 1, yc, yc + 1]
+        ypts = fr[xc, xpts]
+        yf, fit = self.peak_fit(xpts, ypts)
+
+        xshift = xf - np.float(shape[0]) / 2.0
+        yshift = yf - np.float(shape[1]) / 2.0
+
         return xshift, yshift, fr
-    
 
-#----------------------------------------------------------------------   
-#Apply image registration
+    # ----------------------------------------------------------------------
+    # Apply image registration
     def apply_image_registration(self, image, xshift, yshift):
-        
+
         shape = image.shape
         nx = shape[0]
         ny = shape[1]
-        
-        outofboundariesval = np.sum(image)/float(nx*ny)        
-        shifted_img = scipy.ndimage.interpolation.shift(image,[xshift,yshift],
-                                                        mode='constant', 
+
+        outofboundariesval = np.sum(image) / float(nx * ny)
+        shifted_img = scipy.ndimage.interpolation.shift(image, [xshift, yshift],
+                                                        mode='constant',
                                                         cval=outofboundariesval)
-        
+
         return shifted_img
-    
-#----------------------------------------------------------------------   
-#Apply image registration
+
+    # ----------------------------------------------------------------------
+    # Apply image registration
     def crop_registed_images(self, images, min_xshift, max_xshift, min_yshift, max_yshift):
 
-        # if the image is moved to the right (positive) we need to crop the left side 
+        # if the image is moved to the right (positive) we need to crop the left side
         xleft = int(np.ceil(max_xshift))
         if xleft < 0:
             xleft = 0
-        # if the image is moved to the left (negative) we need to crop the right side 
-        xright = int(np.floor(self.n_cols+min_xshift))
-        if xright>(self.n_cols):
+        # if the image is moved to the left (negative) we need to crop the right side
+        xright = int(np.floor(self.n_cols + min_xshift))
+        if xright > (self.n_cols):
             xright = int(self.n_cols)
-        
+
         ybottom = int(np.ceil(max_yshift))
         if ybottom < 0:
             ybottom = 0
-        ytop = int(np.floor(self.n_rows+min_yshift))
+        ytop = int(np.floor(self.n_rows + min_yshift))
         if ytop > (self.n_rows):
             ytop = int(self.n_rows)
 
@@ -921,74 +864,70 @@ class data:
             cropped_stack = images[xleft:xright, ybottom:ytop, :, :]
         else:
             cropped_stack = images[xleft:xright, ybottom:ytop, :]
-        
-        return cropped_stack, xleft, xright, ybottom, ytop
 
+        return cropped_stack, xleft, xright, ybottom, ytop
 
-#----------------------------------------------------------------------   
-#Quadratic peak fit: Fits the 3 data pairs to y=a+bx+cx^2, returning fit=[a,b,c]'
-#  and xpeak at position of inflection'
+    # ----------------------------------------------------------------------
+    # Quadratic peak fit: Fits the 3 data pairs to y=a+bx+cx^2, returning fit=[a,b,c]'
+    #  and xpeak at position of inflection'
     def peak_fit(self, x, y):
-        
-        y1y0=y[1]-y[0]
-        y2y0=y[2]-y[0]
-        x1x0=np.float(x[1]-x[0])
-        x2x0=np.float(x[2]-x[0])
-        x1x0sq=np.float(x[1]*x[1]-x[0]*x[0])
-        x2x0sq=np.float(x[2]*x[2]-x[0]*x[0])
-                
-        c_num=y2y0*x1x0-y1y0*x2x0
-        c_denom=x2x0sq*x1x0-x1x0sq*x2x0
-        
+
+        y1y0 = y[1] - y[0]
+        y2y0 = y[2] - y[0]
+        x1x0 = np.float(x[1] - x[0])
+        x2x0 = np.float(x[2] - x[0])
+        x1x0sq = np.float(x[1] * x[1] - x[0] * x[0])
+        x2x0sq = np.float(x[2] * x[2] - x[0] * x[0])
+
+        c_num = y2y0 * x1x0 - y1y0 * x2x0
+        c_denom = x2x0sq * x1x0 - x1x0sq * x2x0
+
         if c_denom == 0:
-            print ('Divide by zero error')
-            return 
+            print('Divide by zero error')
+            return
 
-        c=c_num/np.float(c_denom)
+        c = c_num / np.float(c_denom)
         if x1x0 == 0:
-            print ('Divide by zero error')
+            print('Divide by zero error')
             return
 
-        b=(y1y0-c*x1x0sq)/np.float(x1x0)
-        a=y[0]-b*x[0]-c*x[0]*x[0]
-  
-        fit=[a,b,c]
+        b = (y1y0 - c * x1x0sq) / np.float(x1x0)
+        a = y[0] - b * x[0] - c * x[0] * x[0]
+
+        fit = [a, b, c]
         if c == 0:
-            xpeak=0.
-            print ('Cannot find xpeak')
+            xpeak = 0.
+            print('Cannot find xpeak')
             return
         else:
-            #Constrain the fit to be within these three points. 
-            xpeak=-b/(2.0*c)
+            # Constrain the fit to be within these three points.
+            xpeak = -b / (2.0 * c)
             if xpeak < x[0]:
                 xpeak = np.float(x[0])
             if xpeak > x[2]:
                 xpeak = np.float(x[2])
-        
+
         return xpeak, fit
-        
-        
-#-----------------------------------------------------------------------------
-#Despike image using Enhanced Lee Filter
-    def despike(self, image, leefilt_percent = 50.0):
-        
+
+    # -----------------------------------------------------------------------------
+    # Despike image using Enhanced Lee Filter
+    def despike(self, image, leefilt_percent=50.0):
+
         fimg = self.lee_filter(image)
-        
+
         leefilt_max = np.amax(fimg)
-        threshold = (1.+0.01*leefilt_percent)*leefilt_max
-    
-        
+        threshold = (1. + 0.01 * leefilt_percent) * leefilt_max
+
         datadim = np.int32(image.shape)
 
         ncols = datadim[0].copy()
-        nrows =  datadim[1].copy()
-              
+        nrows = datadim[1].copy()
+
         spikes = np.where(image > threshold)
         n_spikes = fimg[spikes].shape[0]
-        
 
         result_img = image.copy()
-        
+
         if n_spikes > 0:
 
             xsp = spikes[0]
@@ -996,75 +935,69 @@ class data:
             for i in range(n_spikes):
                 ix = xsp[i]
                 iy = ysp[i]
-                print(ix,iy)
+                print(ix, iy)
                 if ix == 0:
                     ix1 = 1
                     ix2 = 2
-                elif ix == (ncols-1):
-                    ix1 = ncols-2
-                    ix2 = ncols -3
+                elif ix == (ncols - 1):
+                    ix1 = ncols - 2
+                    ix2 = ncols - 3
                 else:
                     ix1 = ix - 1
                     ix2 = ix + 1
-                    
+
                 if iy == 0:
                     iy1 = 1
                     iy2 = 2
-                elif iy == (nrows-1):
-                    iy1 = nrows-2
-                    iy2 = nrows-3
+                elif iy == (nrows - 1):
+                    iy1 = nrows - 2
+                    iy2 = nrows - 3
                 else:
                     iy1 = iy - 1
-                    iy2 = iy + 1      
-                 
-                print(result_img[ix,iy])
-                result_img[ix,iy] = 0.25*(image[ix1,iy]+image[ix2,iy]+
-                                          image[ix,iy1]+image[ix,iy2])  
-                print (result_img[ix,iy])
-            
-        return result_img        
-                                        
-            
-#-----------------------------------------------------------------------------   
-# Lee filter
+                    iy2 = iy + 1
+
+                print(result_img[ix, iy])
+                result_img[ix, iy] = 0.25 * (image[ix1, iy] + image[ix2, iy] +
+                                             image[ix, iy1] + image[ix, iy2])
+                print(result_img[ix, iy])
+
+        return result_img
+
+    # -----------------------------------------------------------------------------
+    # Lee filter
     def lee_filter(self, image):
-    
-        nbox = 5 #The size of the filter box is 2N+1.  The default value is 5.
-        sig = 5.0 #Estimate of the standard deviation.  The default is 5.
-        
-        delta = int((nbox - 1)/2) #width of window
-        
+
+        nbox = 5  # The size of the filter box is 2N+1.  The default value is 5.
+        sig = 5.0  # Estimate of the standard deviation.  The default is 5.
+
+        delta = int((nbox - 1) / 2)  # width of window
+
         datadim = np.int32(image.shape)
-        
-        
+
         n_cols = datadim[0].copy()
-        n_rows =  datadim[1].copy()
-        
-        Imean = np.zeros((n_cols,n_rows))
+        n_rows = datadim[1].copy()
+
+        Imean = np.zeros((n_cols, n_rows))
         scipy.ndimage.filters.uniform_filter(image, size=nbox, output=Imean)
-        
-        Imean2 = Imean**2
-        
-        #variance
-        z = np.empty((n_cols,n_rows))
-        
 
-        for l in range(delta, n_cols-delta):
-            for s in range(delta, n_rows-delta):    
-                
-                z[l,s] = np.sum((image[l-delta:l+delta,s-delta:s+delta]-Imean[l,s])**2)
-                
+        Imean2 = Imean ** 2
+
+        # variance
+        z = np.empty((n_cols, n_rows))
+
+        for l in range(delta, n_cols - delta):
+            for s in range(delta, n_rows - delta):
+                z[l, s] = np.sum((image[l - delta:l + delta, s - delta:s + delta] - Imean[l, s]) ** 2)
+
+        z = z / float(nbox ** 2 - 1.0)
+
+        z = (z + Imean2) / float(1.0 + sig ** 2) - Imean2
 
-        z = z / float(nbox**2-1.0)
-        
-        z = (z + Imean2)/float(1.0+sig**2)-Imean2
-        
         ind = np.where(z < 0)
         n_ind = z[ind].shape[0]
         if n_ind > 0:
             z[ind] = 0
-        
-        lf_image = Imean + (image-Imean)*(z/(Imean2*sig**2+z))
-        
+
+        lf_image = Imean + (image - Imean) * (z / (Imean2 * sig ** 2 + z))
+
         return lf_image
-        
diff --git a/mantis_xray/data_struct.py b/mantis_xray/data_struct.py
index f62fac8..43015bb 100755
--- a/mantis_xray/data_struct.py
+++ b/mantis_xray/data_struct.py
@@ -26,241 +26,225 @@ class Descr(object):
         # Check if the value has been set
         if (not hasattr(self, "_value")):
             return None
-        #print "Getting value: %s" % self._value
+        # print "Getting value: %s" % self._value
         return self._value
 
     def __set__(self, instance, value):
-        #print "Setting to %s" % value
+        # print "Setting to %s" % value
         self._value = value
 
     def __delete__(self, instance):
-        del(self._value)
+        del (self._value)
 
 
 ### Information HDF5 Group
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
 class ids(object):
-
-    proposal = Descr()   
+    proposal = Descr()
     activity = Descr()
-    esaf = Descr() 
+    esaf = Descr()
 
 
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
 class experimenter(object):
-
-    name = Descr()   
+    name = Descr()
     role = Descr()
-    affiliation = Descr() 
-    address = Descr()  
+    affiliation = Descr()
+    address = Descr()
     phone = Descr()
     email = Descr()
-    facility_user_id = Descr() 
-    
+    facility_user_id = Descr()
+
 
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
 class sample(object):
-    
     name = Descr()
     description = Descr()
-#   preparation_date [string - ISO 8601 format]        
+    #   preparation_date [string - ISO 8601 format]
     preparation_datetime = Descr()
-#   chemical_formula [string - abbreviated CIF format]
-    chemical_formula = Descr()    
+    #   chemical_formula [string - abbreviated CIF format]
+    chemical_formula = Descr()
     environment = Descr()
     temperature = Descr()
     temperature_units = Descr()
     pressure = Descr()
     pressure_units = Descr()
-        
-        
-#----------------------------------------------------------------------
-class objective(object):
 
-    manufacturer = Descr()   
+
+# ----------------------------------------------------------------------
+class objective(object):
+    manufacturer = Descr()
     model = Descr()
-    comment = Descr() 
+    comment = Descr()
     magnification = Descr()
-    
 
-#----------------------------------------------------------------------
-class scintillator(object):
 
-    name = Descr()   
+# ----------------------------------------------------------------------
+class scintillator(object):
+    name = Descr()
     type = Descr()
-    comment = Descr() 
-    scintillating_thickness = Descr()   
+    comment = Descr()
+    scintillating_thickness = Descr()
     scintillating_thickness_units = Descr()
     substrate_thickness = Descr()
     substrate_thickness_units = Descr()
-    
-    
-#----------------------------------------------------------------------
-class facility(object):
 
-    name = Descr()   
+
+# ----------------------------------------------------------------------
+class facility(object):
+    name = Descr()
     beamline = Descr()
-    
-    
-#----------------------------------------------------------------------
+
+
+# ----------------------------------------------------------------------
 class accelerator(object):
-        
-    ring_current = Descr() 
+    ring_current = Descr()
     ring_current_units = Descr()
-    primary_beam_energy = Descr()   
+    primary_beam_energy = Descr()
     primary_beam_energy_units = Descr()
     monostripe = Descr()
-    
-    
-#----------------------------------------------------------------------
+
+
+# ----------------------------------------------------------------------
 class pixel_size(object):
-           
-    horizontal = Descr()     
-    horizontal_units = Descr()      
-    vertical = Descr()    
-    vertical_units = Descr()      
-           
-#----------------------------------------------------------------------
+    horizontal = Descr()
+    horizontal_units = Descr()
+    vertical = Descr()
+    vertical_units = Descr()
+
+
+# ----------------------------------------------------------------------
 class dimensions(object):
-           
     horizontal = Descr()
     vertical = Descr()
-           
-#----------------------------------------------------------------------
+
+
+# ----------------------------------------------------------------------
 class binning(object):
-           
     horizontal = Descr()
     vertical = Descr()
-           
-#----------------------------------------------------------------------
+
+
+# ----------------------------------------------------------------------
 class axis_directions(object):
-           
-    horizontal = Descr()     
-    vertical = Descr()    
-     
-#----------------------------------------------------------------------
+    horizontal = Descr()
+    vertical = Descr()
+
+
+# ----------------------------------------------------------------------
 class roi(object):
-           
     x1 = Descr()
     y1 = Descr()
     x2 = Descr()
-    y2 = Descr() 
-    
-    
-#----------------------------------------------------------------------
-class detector(object):  
-    
-    manufacturer = Descr()     
-    model = Descr()    
-    serial_number = Descr()      
-    bit_depth  = Descr()    
-    operating_temperature  = Descr()      
-    operating_temperature_units = Descr()     
-    exposure_time  = Descr()     
-    exposure_time_units = Descr()    
+    y2 = Descr()
+
+
+# ----------------------------------------------------------------------
+class detector(object):
+    manufacturer = Descr()
+    model = Descr()
+    serial_number = Descr()
+    bit_depth = Descr()
+    operating_temperature = Descr()
+    operating_temperature_units = Descr()
+    exposure_time = Descr()
+    exposure_time_units = Descr()
     frame_rate = Descr()
-    
+
     pixel_size = pixel_size()
     dimensions = dimensions()
     binning = binning()
     axis_directions = axis_directions()
     roi = roi()
 
-        
-#----------------------------------------------------------------------        
-class information(object):
 
+# ----------------------------------------------------------------------
+class information(object):
     title = Descr()
     comment = Descr()
     file_creation_datetime = Descr()
-    
+
     ids = ids()
-    experimenter = experimenter() 
+    experimenter = experimenter()
     sample = sample()
     objective = objective()
     scintillator = scintillator()
     facility = facility()
     accelerator = accelerator()
     detector = detector()
-    
-         
 
-#Exchange HDF5 group  
- #----------------------------------------------------------------------
-class exchange(object):
 
+# Exchange HDF5 group
+# ----------------------------------------------------------------------
+class exchange(object):
     title = Descr()
     comment = Descr()
     data_collection_datetime = Descr()
-    
-    #n-dimensional dataset 
+
+    # n-dimensional dataset
     data = Descr()
-    
+
     data_signal = Descr()
     data_description = Descr()
     data_units = Descr()
     data_axes = Descr()
     data_detector = Descr()
-    
-    #These are described in data attribute axes 'x:y:z' but can be arbitrary 
+
+    # These are described in data attribute axes 'x:y:z' but can be arbitrary
     x = Descr()
     x_units = Descr()
     y = Descr()
     y_units = Descr()
     z = Descr()
     z_units = Descr()
-    
-    energy = Descr()  
+
+    energy = Descr()
     energy_units = Descr()
-    
-    theta = Descr()  
+
+    theta = Descr()
     theta_units = Descr()
-    
+
     white_data = Descr()
     white_data_units = Descr()
     dark_data = Descr()
     dark_data_units = Descr()
     rotation = Descr()
-        
 
-# Spectromicroscopy HDF5 Group        
-#----------------------------------------------------------------------
-class normalization(object):
 
+# Spectromicroscopy HDF5 Group
+# ----------------------------------------------------------------------
+class normalization(object):
     white_spectrum = Descr()
     white_spectrum_units = Descr()
     white_spectrum_energy = Descr()
     white_spectrum_energy_units = Descr()
-               
-               
-#----------------------------------------------------------------------
-class spectromicroscopy(object):
 
+
+# ----------------------------------------------------------------------
+class spectromicroscopy(object):
     positions = Descr()
     positions_units = Descr()
     positions_names = Descr()
-        
+
     normalization = normalization()
-        
+
     optical_density = Descr()
-    
+
     data_dwell = Descr()
     i0_dwell = Descr()
-    
+
     xshifts = Descr()
     yshifts = Descr()
-        
+
 
 # HDF5 Root Group
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
 class h5(object):
-    
-    #implements [string] comma separated string that tells the user which entries file contains
+    # implements [string] comma separated string that tells the user which entries file contains
     implements = Descr()
-    version = Descr() 
+    version = Descr()
 
     information = information()
     exchange = exchange()
     spectromicroscopy = spectromicroscopy()
-    
-        
+
diff --git a/mantis_xray/dialogalign.ui b/mantis_xray/dialogalign.ui
new file mode 100644
index 0000000..3fba994
--- /dev/null
+++ b/mantis_xray/dialogalign.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>100</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Alignment Routine Selector</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="font">
+      <font>
+       <family>Ubuntu</family>
+       <pointsize>8</pointsize>
+      </font>
+     </property>
+     <property name="title">
+      <string>Choose an image registration tool:</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_3">
+      <item>
+       <widget class="QPushButton" name="bt_align2">
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>40</height>
+         </size>
+        </property>
+        <property name="font">
+         <font>
+          <family>Ubuntu</family>
+          <pointsize>8</pointsize>
+         </font>
+        </property>
+        <property name="text">
+         <string>FFT cross-correlation</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="bt_align">
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>40</height>
+         </size>
+        </property>
+        <property name="font">
+         <font>
+          <family>Ubuntu</family>
+          <pointsize>8</pointsize>
+         </font>
+        </property>
+        <property name="text">
+         <string>Manual alignment</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mantis_xray/file_plugins/file_dataexch_hdf5.py b/mantis_xray/file_plugins/file_dataexch_hdf5.py
index 691be81..f9919b5 100755
--- a/mantis_xray/file_plugins/file_dataexch_hdf5.py
+++ b/mantis_xray/file_plugins/file_dataexch_hdf5.py
@@ -316,7 +316,13 @@ def read(filename, stack_object, selection=None, *args, **kwargs):
             if 'axes' in dsdata.attrs:
                 data_struct.exchange.data_axes = dsdata.attrs['axes']
 
-
+                if 'x' in exchangeGrp:
+                    dsx = exchangeGrp['x']
+                    data_struct.exchange.x = dsx[...]
+                    data_struct.have_dimscale = 1
+                if 'y' in exchangeGrp:
+                    dsy = exchangeGrp['y']
+                    data_struct.exchange.y = dsy[...]
 #
 #                 if 'x' in detectorGrp:
 #                     dsx = detectorGrp['x']
diff --git a/mantis_xray/file_plugins/file_json.py b/mantis_xray/file_plugins/file_json.py
index b04ff78..62d0cb5 100644
--- a/mantis_xray/file_plugins/file_json.py
+++ b/mantis_xray/file_plugins/file_json.py
@@ -99,12 +99,23 @@ class JS_FileLoader:
       for num_Ch in range(self.num_channels):
         DataNames2.append([self.file_path+'_'+Alphabet[num_Ch]+'.xim'])
       DataNames.append(DataNames2)
-    elif DataFlag in ['Multi-Region Image', 'Multi-Region Image Stack']:
+    elif DataFlag in ['Multi-Region Image']:
       for num_R in range(self.num_regions):
-        DataNames2 = []
+          DataNames2 = []
+          for num_Ch in range(self.num_channels):
+              DataNames2.append([self.file_path + '_' + Alphabet[num_Ch] + str(num_R) + '.xim'])
+          DataNames.append(DataNames2)
+    elif DataFlag in ['Multi-Region Image Stack']:
         for num_Ch in range(self.num_channels):
-          DataNames2.append([self.file_path+'_'+Alphabet[num_Ch]+str(num_R)+'.xim'])
-        DataNames.append(DataNames2)
+            DataNames2 = []
+            for num_R in range(self.num_regions):
+                DataNames3 = []
+                for num_E in range(self.data_size[0][2]):
+                    DataNames3.append(
+                        self.file_path + '_' + Alphabet[num_Ch] + str(num_E).zfill(3) + str(num_R) + '.xim')
+                DataNames2.append(DataNames3)
+            DataNames = [DataNames2]
+            # print(DataNames[0])
     elif DataFlag == 'Image Stack':
       DataNames2 = []
       for num_Ch in range(self.num_channels):
@@ -141,23 +152,22 @@ class JS_FileLoader:
 #----------------------------------------------------------------------
 def read(filename, self, selection=None, *args, **kwargs):
     JS = JS_FileLoader(filename)
-    if JS.js['ScanDefinition']['Flags'] == 'Image Stack':
-
+    allowed = ['Image Stack', 'Image', 'Multi-Region Image Stack']
+    if JS.js['ScanDefinition']['Flags'] in allowed:
         self.x_dist = numpy.array([float(i) for i in JS.js['ScanDefinition']['Regions'][selection[0]+1]['PAxis']['Points'][1:] ])
         self.y_dist = numpy.array([float(i) for i in JS.js['ScanDefinition']['Regions'][selection[0]+1]['QAxis']['Points'][1:] ])
         self.ev = numpy.array([float(i) for i in JS.js['ScanDefinition']['StackAxis']['Points'][1:] ])
-
-        self.n_cols = numpy.array(len(self.x_dist))
-        self.n_rows = numpy.array(len(self.y_dist))
-        self.n_ev = numpy.array(len(self.ev))
+        self.n_cols = len(self.x_dist)
+        self.n_rows = len(self.y_dist)
+        self.n_ev = len(self.ev)
 
         msec = float(JS.js['ScanDefinition']['Dwell'])
         self.data_dwell = numpy.ones((self.n_ev))*msec
 
         imagestack = numpy.empty((self.n_cols,self.n_rows,self.n_ev), numpy.int32)
-        for i in range(len(JS.data_names[selection[0]][selection[1]])):
+        for i in range(len(JS.data_names[selection[1]][selection[0]])):
             try:
-                imagestack[:,:,i] = numpy.loadtxt(JS.data_names[selection[0]][selection[1]][i], numpy.int32).T
+                imagestack[:,:,i] = numpy.loadtxt(JS.data_names[selection[1]][selection[0]][i], numpy.int32).T
             except ValueError:
                 print("Aborted stack or XIMs with inconsistent dimensions.")
                 imagestack[:,:,i] = numpy.nan
@@ -171,7 +181,7 @@ def read(filename, self, selection=None, *args, **kwargs):
         self.fill_h5_struct_from_stk()
 
     else:
-        print("Only Image Stack files are supported.")
+        print("Unknown Format")
 
     return
 
@@ -200,4 +210,4 @@ def read_js_i0(self, filename, *args, **kwargs):
     self.i0_dwell = msec
     self.evi0 = numpy.array([float(i) for i in Energies])
     self.i0data = Data
-    return
+    return
\ No newline at end of file
diff --git a/mantis_xray/file_plugins/file_ncb.py b/mantis_xray/file_plugins/file_ncb.py
index 0ddab03..23828f7 100644
--- a/mantis_xray/file_plugins/file_ncb.py
+++ b/mantis_xray/file_plugins/file_ncb.py
@@ -27,282 +27,251 @@ verbose = 0
 
 title = 'Ncb'
 extension = ['*.ncb']
-read_types = ['image','stack']
-write_types = ['image','stack','results']
+read_types = ['image', 'stack']
+write_types = ['image', 'stack', 'results']
 
 
 def identify(filename):
     try:
-        basename, extension = os.path.splitext(filename) 
+        basename, extension = os.path.splitext(filename)
         dat_fn = basename + '.dat'
-        f = open(str(dat_fn),'r')
+        f = open(str(dat_fn), 'r')
         f.close()
         return True
     except:
         return False
 
+
 def GetFileStructure(FileName):
-    return None  
+    return None
 
 
-#---------------------------------------------------------------------- 
+# ----------------------------------------------------------------------
 def read(filename, self, selection=None, *args, **kwargs):
-    
-    
-    basename, extension = os.path.splitext(filename) 
+    basename, extension = os.path.splitext(filename)
     dat_fn = basename + '.dat'
-    
 
-    f = open(str(dat_fn),'r')
+    f = open(str(dat_fn), 'r')
     lines = f.readlines()
     temp = lines[0].split()
-    
+
     self.n_cols = int(temp[0])
     self.n_rows = int(temp[1])
     scale = float(temp[2])
 
-    #print self.n_cols, self.n_rows, scale
-    
+    # print self.n_cols, self.n_rows, scale
+
     temp = lines[1].split()
     x_start = float(temp[0])
     x_stop = float(temp[1])
-    
+
     temp = lines[2].split()
     y_start = float(temp[0])
     y_stop = float(temp[1])
 
     self.n_ev = int(lines[3])
 
-    #print self.n_ev
-    
+    # print self.n_ev
 
     self.ev = np.zeros((self.n_ev))
     self.data_dwell = np.zeros((self.n_ev))
     filename_list = []
     for i in range(self.n_ev):
-        self.ev[i] = float(lines[4+i])
-        
-    #print self.ev
+        self.ev[i] = float(lines[4 + i])
+
+    # print self.ev
 
     for i in range(self.n_ev):
-        self.ev[i] = float(lines[4+i])
+        self.ev[i] = float(lines[4 + i])
 
     try:
         for i in range(self.n_ev):
-            temp = lines[4+self.n_ev+i].split()
-            
+            temp = lines[4 + self.n_ev + i].split()
+
             filename_list.append(temp[0])
             self.data_dwell[i] = float(temp[2])
     except:
         self.data_dwell = np.ones((self.n_ev))
 
-
     f.close()
 
-    
-    
-    if scale < 0 :
+    if scale < 0:
         dataformat = np.float32
     else:
         dataformat = np.int16
-        
-    #print 'data format', dataformat
-        
-    f = open(str(filename),'rb')
-    big_array = np.fromfile(f, dataformat, self.n_cols*self.n_rows*self.n_ev)
-    f.close()    
-    
-    
-    if scale > 0 and scale != 1 :
-        image_stack = big_array.astype(np.float)/scale
-        print ("data rescaled by ", 1./scale)
+
+    # print 'data format', dataformat
+
+    f = open(str(filename), 'rb')
+    big_array = np.fromfile(f, dataformat, self.n_cols * self.n_rows * self.n_ev)
+    f.close()
+
+    if scale > 0 and scale != 1:
+        image_stack = big_array.astype(np.float) / scale
+        print("data rescaled by ", 1. / scale)
     else:
         image_stack = big_array.astype(np.float)
 
-
-    if (x_start > x_stop) :
-        image_stack = image_stack[::-1,:,:]
-        t = x_start 
-        x_start = x_stop 
+    if (x_start > x_stop):
+        image_stack = image_stack[::-1, :, :]
+        t = x_start
+        x_start = x_stop
         x_stop = t
-        print ('x data reversed')
+        print('x data reversed')
 
-    if (y_start > y_stop) :
-        image_stack = image_stack[:,::-1,:]
-        t = y_start 
-        y_start = y_stop 
+    if (y_start > y_stop):
+        image_stack = image_stack[:, ::-1, :]
+        t = y_start
+        y_start = y_stop
         y_stop = t
-        print ('y data reversed')
+        print('y data reversed')
 
-        
-    xstep = (x_stop-x_start)/(self.n_cols-1)
-    self.x_dist = np.arange(x_start,x_stop+xstep, xstep)
-    
-    ystep = (y_stop-y_start)/(self.n_rows-1)
-    self.y_dist = np.arange(y_start,y_stop+ystep, ystep)              
+    xstep = (x_stop - x_start) / (self.n_cols - 1)
+    self.x_dist = np.arange(x_start, x_stop + xstep, xstep)
 
+    ystep = (y_stop - y_start) / (self.n_rows - 1)
+    self.y_dist = np.arange(y_start, y_stop + ystep, ystep)
 
     self.absdata = np.empty((self.n_cols, self.n_rows, self.n_ev))
-            
-    self.absdata = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_ev), order='F')    
-    
-    
+
+    self.absdata = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_ev), order='F')
+
     self.fill_h5_struct_from_stk()
-      
 
     return
 
 
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
 def read_ncb4D(self, filenames):
-    
-    if verbose: print ('First energy stack:', filenames[0])
-    
-    
+    if verbose: print('First energy stack:', filenames[0])
+
     data_files = natural_sort(filenames)
 
     neng = len(data_files)
-    if verbose: print ('Number of energies ', neng)
-    
+    if verbose: print('Number of energies ', neng)
+
     self.stack4D = []
     theta = []
-    
-    for i in range(neng):     
-        #Read the data
+
+    for i in range(neng):
+        # Read the data
         thisstack, thistheta = read_ncb_data(self, data_files[i])
-                
-        #Check if we have negative angles, if yes convert to 0-360deg
+
+        # Check if we have negative angles, if yes convert to 0-360deg
         for ith in range(len(thistheta)):
             if thistheta[ith] < 0:
                 thistheta[ith] = thistheta[ith] + 360
-                
+
         self.stack4D.append(thisstack)
         theta.append(thistheta)
-        
+
         dims = thisstack.shape
-    
-    
+
     self.stack4D = np.array(self.stack4D)
-    self.stack4D = np.transpose(self.stack4D, axes=(1,2,0,3))
-    
+    self.stack4D = np.transpose(self.stack4D, axes=(1, 2, 0, 3))
+
     self.theta = theta[0]
     self.n_theta = len(theta)
-    
-            
-    self.absdata = self.stack4D[:,:,:,0]
-    
+
+    self.absdata = self.stack4D[:, :, :, 0]
+
     self.data_dwell = np.ones((neng))
-    
+
     self.fill_h5_struct_from_stk()
-    
-    return 
-    
-    
-#----------------------------------------------------------------------          
-def read_ncb_data(self, filename): 
-    
-    
-    basename, extension = os.path.splitext(filename) 
+
+    return
+
+
+# ----------------------------------------------------------------------
+def read_ncb_data(self, filename):
+    basename, extension = os.path.splitext(filename)
     dat_fn = basename + '.dat'
-    
 
-    f = open(str(dat_fn),'r')
+    f = open(str(dat_fn), 'r')
     lines = f.readlines()
     temp = lines[0].split()
-    
+
     self.n_cols = int(temp[0])
     self.n_rows = int(temp[1])
     scale = float(temp[2])
 
     if verbose:
-        print ('self.n_cols, self.n_rows, scale', self.n_cols, self.n_rows, scale)
-        
-    
-    
+        print('self.n_cols, self.n_rows, scale', self.n_cols, self.n_rows, scale)
+
     temp = lines[1].split()
     x_start = float(temp[0])
     x_stop = float(temp[1])
-    
+
     temp = lines[2].split()
     y_start = float(temp[0])
     y_stop = float(temp[1])
 
     self.n_theta = int(lines[3])
 
-    
-
     angles = np.zeros((self.n_theta))
     self.data_dwell = np.zeros((self.n_theta))
     filename_list = []
     for i in range(self.n_theta):
-        angles[i] = float(lines[4+i])
-
+        angles[i] = float(lines[4 + i])
 
     for i in range(self.n_theta):
-        angles[i] = float(lines[4+i])
+        angles[i] = float(lines[4 + i])
 
     try:
         for i in range(self.n_theta):
-            temp = lines[4+self.n_ev+i].split()
-            
+            temp = lines[4 + self.n_ev + i].split()
+
             filename_list.append(temp[0])
             self.data_dwell[i] = float(temp[2])
     except:
         self.data_dwell = np.ones((self.n_theta))
 
-
     f.close()
 
-    
-    
-    if scale < 0 :
+    if scale < 0:
         dataformat = np.float32
     else:
         dataformat = np.int16
 
-        
-    f = open(str(filename),'rb')
-    big_array = np.fromfile(f, dataformat, self.n_cols*self.n_rows*self.n_theta)
-    f.close()    
-    
-    
-    if scale > 0 and scale != 1 :
-        image_stack = big_array.astype(np.float)/scale
-        if verbose: print ("data rescaled by ", 1./scale)
+    f = open(str(filename), 'rb')
+    big_array = np.fromfile(f, dataformat, self.n_cols * self.n_rows * self.n_theta)
+    f.close()
+
+    if scale > 0 and scale != 1:
+        image_stack = big_array.astype(np.float) / scale
+        if verbose: print("data rescaled by ", 1. / scale)
     else:
         image_stack = big_array.astype(np.float)
 
-
-    if (x_start > x_stop) :
-        image_stack = image_stack[::-1,:,:]
-        t = x_start 
-        x_start = x_stop 
+    if (x_start > x_stop):
+        image_stack = image_stack[::-1, :, :]
+        t = x_start
+        x_start = x_stop
         x_stop = t
-        if verbose: print ('x data reversed')
+        if verbose: print('x data reversed')
 
-    if (y_start > y_stop) :
-        image_stack = image_stack[:,::-1,:]
-        t = y_start 
-        y_start = y_stop 
+    if (y_start > y_stop):
+        image_stack = image_stack[:, ::-1, :]
+        t = y_start
+        y_start = y_stop
         y_stop = t
-        if verbose: print ('y data reversed')
+        if verbose: print('y data reversed')
+
+    xstep = (x_stop - x_start) / (self.n_cols - 1)
+    self.x_dist = np.arange(x_start, x_stop + xstep, xstep)
 
-        
-    xstep = (x_stop-x_start)/(self.n_cols-1)
-    self.x_dist = np.arange(x_start,x_stop+xstep, xstep)
-    
-    ystep = (y_stop-y_start)/(self.n_rows-1)
-    self.y_dist = np.arange(y_start,y_stop+ystep, ystep)              
+    ystep = (y_stop - y_start) / (self.n_rows - 1)
+    self.y_dist = np.arange(y_start, y_stop + ystep, ystep)
 
-    image_stack = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_theta), order='F') 
+    image_stack = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_theta), order='F')
 
     return image_stack, angles
 
 
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
 #  This procedure writes  a whole stack (3d (E,x,y) array) to a binary file
 #  with associated *.dat file to track paramaters
-def write(filename, stack, data_type): #,norm):
+def write(filename, stack, data_type):  # ,norm):
     #
     # def operate_on_Narray(A, B, function):
     #     try:
@@ -323,14 +292,13 @@ def write(filename, stack, data_type): #,norm):
     #     else:
     #         plt.savefig(name+'.tif', dpi=(dpi * resize_fact))
     #         plt.close()
-    print ('Writing .ncb stack:', filename)
-    
-    
-    basename, extension = os.path.splitext(filename) 
+    print('Writing .ncb stack:', filename)
+
+    basename, extension = os.path.splitext(filename)
     dat_fn = basename + '.dat'
     filename = basename + '.ncb'
 
-    image_stack = np.transpose(stack.absdata, axes=(1,0,2))
+    image_stack = np.transpose(stack.absdata, axes=(1, 0, 2))
     '''Experimental OD filtering and edge substraction'''
     # if norm:
     #
@@ -370,400 +338,367 @@ def write(filename, stack, data_type): #,norm):
     #     #print(ave)
     #     for i in range(np.size(image_stack, 2)):
     #         image_stack[:,:,i] = image_stack[:,:,i] - operate_on_Narray(ave, image_stack[:,:,i], lambda a, b: a/((1+ np.exp(-b+0.5*a)**(25*1/a))))
-    
-    image_stack = np.reshape(image_stack, (stack.n_cols*stack.n_rows*stack.n_ev), order='F')
+
+    image_stack = np.reshape(image_stack, (stack.n_cols * stack.n_rows * stack.n_ev), order='F')
 
     tmax = np.amax(image_stack)
     tmin = np.amin(image_stack)
     test = np.amax([abs(tmin), abs(tmax)])
     scale = 1.
-    if test > 3e4 or test < 1e3 :
-        scale = 10.**(3-np.fix(np.math.log10(test)))
-
+    if test > 3e4 or test < 1e3:
+        scale = 10. ** (3 - np.fix(np.math.log10(test)))
 
-    #Save image stack to a binary .dat file
-    f = open(str(filename),'wb')
+    # Save image stack to a binary .dat file
+    f = open(str(filename), 'wb')
     if scale != 1.0:
-        print ('Scaling the data by ', scale)
-        saveddata = image_stack*scale
+        print('Scaling the data by ', scale)
+        saveddata = image_stack * scale
         saveddata.astype(np.int16).tofile(f)
     else:
         scale = -1.0
         image_stack.astype(np.float32).tofile(f)
     f.close()
 
-    #print 'imagedims', image_stack.shape
+    # print 'imagedims', image_stack.shape
 
+    f = open(str(dat_fn), 'w')
 
-    f = open(str(dat_fn),'w')
-
-    print('\t%d\t%d\t%.6f' %(stack.n_rows, stack.n_cols, scale), file=f)
+    print('\t%d\t%d\t%.6f' % (stack.n_rows, stack.n_cols, scale), file=f)
 
     x_start = stack.y_dist[0]
     x_stop = stack.y_dist[-1]
-    if x_start != 0. :
+    if x_start != 0.:
         x_stop = x_stop - x_start
         x_start = 0.
 
-    print('\t%.6f\t%.6f' %(x_start, x_stop), file=f)
+    print('\t%.6f\t%.6f' % (x_start, x_stop), file=f)
 
     y_start = stack.x_dist[0]
     y_stop = stack.x_dist[-1]
-    if y_start != 0. :
+    if y_start != 0.:
         y_stop = y_stop - y_start
         y_start = 0.
-    print('\t%.6f\t%.6f' %(y_start, y_stop), file=f)
+    print('\t%.6f\t%.6f' % (y_start, y_stop), file=f)
 
-    print('\t%d' %(stack.n_ev), file=f)
+    print('\t%d' % (stack.n_ev), file=f)
 
     for i in range(stack.n_ev):
-        print('\t%.6f' %(stack.ev[i]), file=f)
+        print('\t%.6f' % (stack.ev[i]), file=f)
 
     for i in range(stack.n_ev):
-        thisstr = 'image'+str(i+1)
-        print('%s\t%.6f\t%.6f' %(thisstr, stack.ev[i], stack.data_dwell[i]), file=f)
+        thisstr = 'image' + str(i + 1)
+        print('%s\t%.6f\t%.6f' % (thisstr, stack.ev[i], stack.data_dwell[i]), file=f)
 
     f.close()
-    
+
     return
 
-#----------------------------------------------------------------------  
-def natural_sort(l): 
-    convert = lambda text: int(text) if text.isdigit() else text.lower() 
-    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
-    return sorted(l, key = alphanum_key)
 
-#----------------------------------------------------------------------
+# ----------------------------------------------------------------------
+def natural_sort(l):
+    convert = lambda text: int(text) if text.isdigit() else text.lower()
+    alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
+    return sorted(l, key=alphanum_key)
+
+
+# ----------------------------------------------------------------------
 class Cncb:
     def __init__(self):
         pass
-    
-   
-           
-#----------------------------------------------------------------------
+
+    # ----------------------------------------------------------------------
     def read_ncb(self, filename):
-        
-        print ('Reading stack:', filename)
-        
-        basename, extension = os.path.splitext(filename) 
+
+        print('Reading stack:', filename)
+
+        basename, extension = os.path.splitext(filename)
         dat_fn = basename + '.dat'
-        
 
-        f = open(str(dat_fn),'r')
+        f = open(str(dat_fn), 'r')
         lines = f.readlines()
         temp = lines[0].split()
-        
+
         self.n_cols = int(temp[0])
         self.n_rows = int(temp[1])
         scale = float(temp[2])
-    
-        #print self.n_cols, self.n_rows, scale
-        
+
+        # print self.n_cols, self.n_rows, scale
+
         temp = lines[1].split()
         x_start = float(temp[0])
         x_stop = float(temp[1])
-        
+
         temp = lines[2].split()
         y_start = float(temp[0])
         y_stop = float(temp[1])
 
         self.n_ev = int(lines[3])
 
-        #print self.n_ev
-        
-    
+        # print self.n_ev
+
         self.ev = np.zeros((self.n_ev))
         self.data_dwell = np.zeros((self.n_ev))
         filename_list = []
         for i in range(self.n_ev):
-            self.ev[i] = float(lines[4+i])
-            
-        #print self.ev
+            self.ev[i] = float(lines[4 + i])
+
+        # print self.ev
 
         for i in range(self.n_ev):
-            self.ev[i] = float(lines[4+i])
+            self.ev[i] = float(lines[4 + i])
 
         try:
             for i in range(self.n_ev):
-                temp = lines[4+self.n_ev+i].split()
-                
+                temp = lines[4 + self.n_ev + i].split()
+
                 filename_list.append(temp[0])
                 self.data_dwell[i] = float(temp[2])
         except:
             self.data_dwell = np.ones((self.n_ev))
 
-    
         f.close()
 
-        
-        
-        if scale < 0 :
+        if scale < 0:
             dataformat = np.float32
         else:
             dataformat = np.int16
-            
-        #print 'data format', dataformat
-            
-        f = open(str(filename),'rb')
-        big_array = np.fromfile(f, dataformat, self.n_cols*self.n_rows*self.n_ev)
-        f.close()    
-        
-        
-        if scale > 0 and scale != 1 :
-            image_stack = big_array.astype(np.float)/scale
-            print ("data rescaled by ", 1./scale)
+
+        # print 'data format', dataformat
+
+        f = open(str(filename), 'rb')
+        big_array = np.fromfile(f, dataformat, self.n_cols * self.n_rows * self.n_ev)
+        f.close()
+
+        if scale > 0 and scale != 1:
+            image_stack = big_array.astype(np.float) / scale
+            print("data rescaled by ", 1. / scale)
         else:
             image_stack = big_array.astype(np.float)
 
-
-        if (x_start > x_stop) :
-            image_stack = image_stack[::-1,:,:]
-            t = x_start 
-            x_start = x_stop 
+        if (x_start > x_stop):
+            image_stack = image_stack[::-1, :, :]
+            t = x_start
+            x_start = x_stop
             x_stop = t
-            print ('x data reversed')
+            print('x data reversed')
 
-        if (y_start > y_stop) :
-            image_stack = image_stack[:,::-1,:]
-            t = y_start 
-            y_start = y_stop 
+        if (y_start > y_stop):
+            image_stack = image_stack[:, ::-1, :]
+            t = y_start
+            y_start = y_stop
             y_stop = t
-            print ('y data reversed')
+            print('y data reversed')
+
+        xstep = (x_stop - x_start) / (self.n_cols - 1)
+        self.x_dist = np.arange(x_start, x_stop + xstep, xstep)
 
-            
-        xstep = (x_stop-x_start)/(self.n_cols-1)
-        self.x_dist = np.arange(x_start,x_stop+xstep, xstep)
-        
-        ystep = (y_stop-y_start)/(self.n_rows-1)
-        self.y_dist = np.arange(y_start,y_stop+ystep, ystep)              
+        ystep = (y_stop - y_start) / (self.n_rows - 1)
+        self.y_dist = np.arange(y_start, y_stop + ystep, ystep)
 
-   
         self.absdata = np.empty((self.n_cols, self.n_rows, self.n_ev))
-                
-        self.absdata = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_ev), order='F')    
-        
-        
-  
+
+        self.absdata = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_ev), order='F')
+
         return
-    
-    
-#----------------------------------------------------------------------
-#  This procedure writes  a whole stack (3d (E,x,y) array) to a binary file
-#  with associated *.dat file to track paramaters
+
+    # ----------------------------------------------------------------------
+    #  This procedure writes  a whole stack (3d (E,x,y) array) to a binary file
+    #  with associated *.dat file to track paramaters
     def write_ncb(self, filename, data_struct):
-        
-        
-        print ('Writing .ncb stack:', filename)
-        
-        
-        basename, extension = os.path.splitext(filename) 
+
+        print('Writing .ncb stack:', filename)
+
+        basename, extension = os.path.splitext(filename)
         dat_fn = basename + '.dat'
-        
-        image_stack = np.transpose(self.absdata, axes=(1,0,2))
-        
-        #image_stack = self.absdata.copy()
-        
-        image_stack = np.reshape(image_stack, (self.n_cols*self.n_rows*self.n_ev), order='F') 
-        
+
+        image_stack = np.transpose(self.absdata, axes=(1, 0, 2))
+
+        # image_stack = self.absdata.copy()
+
+        image_stack = np.reshape(image_stack, (self.n_cols * self.n_rows * self.n_ev), order='F')
 
         tmax = np.amax(image_stack)
         tmin = np.amin(image_stack)
         test = np.amax([abs(tmin), abs(tmax)])
         scale = 1.
-        if test > 3e4 or test < 1e3 :
-            scale = 10.**(3-np.fix(np.math.log10(test)))
+        if test > 3e4 or test < 1e3:
+            scale = 10. ** (3 - np.fix(np.math.log10(test)))
 
-
-        #Save image stack to a binary .dat file
-        f = open(str(filename),'wb')
+        # Save image stack to a binary .dat file
+        f = open(str(filename), 'wb')
         if scale != 1.0:
-            print ('Scaling the data by ', scale)
-            saveddata = image_stack*scale
+            print('Scaling the data by ', scale)
+            saveddata = image_stack * scale
             saveddata.astype(np.int16).tofile(f)
         else:
             scale = -1.0
             image_stack.astype(np.float32).tofile(f)
         f.close()
 
-        #print 'imagedims', image_stack.shape
-        
-    
-        f = open(str(dat_fn),'w')
+        # print 'imagedims', image_stack.shape
+
+        f = open(str(dat_fn), 'w')
+
+        print('\t%d\t%d\t%.6f' % (self.n_rows, self.n_cols, scale), file=f)
+        # print('\t%d\t%d\t%.6f' %(self.n_cols, self.n_rows, scale)
 
-        print('\t%d\t%d\t%.6f' %(self.n_rows, self.n_cols, scale), file=f)
-        #print('\t%d\t%d\t%.6f' %(self.n_cols, self.n_rows, scale)
-        
-        
         x_start = self.y_dist[0]
         x_stop = self.y_dist[-1]
-        if x_start != 0. :
+        if x_start != 0.:
             x_stop = x_stop - x_start
             x_start = 0.
 
-        print('\t%.6f\t%.6f' %(x_start, x_stop), file=f)
-        
+        print('\t%.6f\t%.6f' % (x_start, x_stop), file=f)
+
         y_start = self.x_dist[0]
         y_stop = self.x_dist[-1]
-        if y_start != 0. :
+        if y_start != 0.:
             y_stop = y_stop - y_start
             y_start = 0.
-        print('\t%.6f\t%.6f' %(y_start, y_stop), file=f)
-        
-        print('\t%d' %(self.n_ev), file=f)
-        
+        print('\t%.6f\t%.6f' % (y_start, y_stop), file=f)
+
+        print('\t%d' % (self.n_ev), file=f)
+
         for i in range(self.n_ev):
-            print('\t%.6f' %(self.ev[i]), file=f)
-        
+            print('\t%.6f' % (self.ev[i]), file=f)
+
         for i in range(self.n_ev):
-            thisstr = 'image'+str(i+1)
-            print('%s\t%.6f\t%.6f' %(thisstr, self.ev[i], self.data_dwell[i]), file=f)
+            thisstr = 'image' + str(i + 1)
+            print('%s\t%.6f\t%.6f' % (thisstr, self.ev[i], self.data_dwell[i]), file=f)
 
         f.close()
-        
+
         return
 
-#----------------------------------------------------------------------          
-    def read_ncb_data(self, filename): 
-        
-        #print 'Reading stack:', filename
-        
-        basename, extension = os.path.splitext(filename) 
+    # ----------------------------------------------------------------------
+    def read_ncb_data(self, filename):
+
+        # print 'Reading stack:', filename
+
+        basename, extension = os.path.splitext(filename)
         dat_fn = basename + '.dat'
-        
 
-        f = open(str(dat_fn),'r')
+        f = open(str(dat_fn), 'r')
         lines = f.readlines()
         temp = lines[0].split()
-        
+
         self.n_cols = int(temp[0])
         self.n_rows = int(temp[1])
         scale = float(temp[2])
-    
+
         if verbose:
-            print ('self.n_cols, self.n_rows, scale', self.n_cols, self.n_rows, scale)
-        
+            print('self.n_cols, self.n_rows, scale', self.n_cols, self.n_rows, scale)
+
         temp = lines[1].split()
         x_start = float(temp[0])
         x_stop = float(temp[1])
-        
+
         temp = lines[2].split()
         y_start = float(temp[0])
         y_stop = float(temp[1])
 
         self.n_theta = int(lines[3])
 
-        #print self.n_ev
-        
-    
+        # print self.n_ev
+
         angles = np.zeros((self.n_theta))
         self.data_dwell = np.zeros((self.n_theta))
         filename_list = []
         for i in range(self.n_theta):
-            angles[i] = float(lines[4+i])
-            
-        #print self.ev
+            angles[i] = float(lines[4 + i])
+
+        # print self.ev
 
         for i in range(self.n_theta):
-            angles[i] = float(lines[4+i])
+            angles[i] = float(lines[4 + i])
 
         try:
             for i in range(self.n_theta):
-                temp = lines[4+self.n_ev+i].split()
-                
+                temp = lines[4 + self.n_ev + i].split()
+
                 filename_list.append(temp[0])
                 self.data_dwell[i] = float(temp[2])
         except:
             self.data_dwell = np.ones((self.n_theta))
 
-    
         f.close()
 
-        
-        
-        if scale < 0 :
+        if scale < 0:
             dataformat = np.float32
         else:
             dataformat = np.int16
-            
-        #print 'data format', dataformat
-            
-        f = open(str(filename),'rb')
-        big_array = np.fromfile(f, dataformat, self.n_cols*self.n_rows*self.n_theta)
-        f.close()    
-        
-        
-        if scale > 0 and scale != 1 :
-            image_stack = big_array.astype(np.float)/scale
-            if verbose: print ("data rescaled by ", 1./scale)
+
+        # print 'data format', dataformat
+
+        f = open(str(filename), 'rb')
+        big_array = np.fromfile(f, dataformat, self.n_cols * self.n_rows * self.n_theta)
+        f.close()
+
+        if scale > 0 and scale != 1:
+            image_stack = big_array.astype(np.float) / scale
+            if verbose: print("data rescaled by ", 1. / scale)
         else:
             image_stack = big_array.astype(np.float)
 
-
-        if (x_start > x_stop) :
-            image_stack = image_stack[::-1,:,:]
-            t = x_start 
-            x_start = x_stop 
+        if (x_start > x_stop):
+            image_stack = image_stack[::-1, :, :]
+            t = x_start
+            x_start = x_stop
             x_stop = t
-            if verbose: print ('x data reversed')
+            if verbose: print('x data reversed')
 
-        if (y_start > y_stop) :
-            image_stack = image_stack[:,::-1,:]
-            t = y_start 
-            y_start = y_stop 
+        if (y_start > y_stop):
+            image_stack = image_stack[:, ::-1, :]
+            t = y_start
+            y_start = y_stop
             y_stop = t
-            if verbose: print ('y data reversed')
-
-            
-        xstep = (x_stop-x_start)/(self.n_cols-1)
-        self.x_dist = np.arange(x_start,x_stop+xstep, xstep)
-        
-        ystep = (y_stop-y_start)/(self.n_rows-1)
-        self.y_dist = np.arange(y_start,y_stop+ystep, ystep)              
- 
-        image_stack = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_theta), order='F') 
-   
-        return image_stack, angles
+            if verbose: print('y data reversed')
+
+        xstep = (x_stop - x_start) / (self.n_cols - 1)
+        self.x_dist = np.arange(x_start, x_stop + xstep, xstep)
+
+        ystep = (y_stop - y_start) / (self.n_rows - 1)
+        self.y_dist = np.arange(y_start, y_stop + ystep, ystep)
+
+        image_stack = np.reshape(image_stack, (self.n_cols, self.n_rows, self.n_theta), order='F')
 
+        return image_stack, angles
 
-#----------------------------------------------------------------------
+    # ----------------------------------------------------------------------
     def read_ncb4D(self, filenames):
-        
-        if verbose: print ('First energy stack:', filenames[0])
-        
-        
+
+        if verbose: print('First energy stack:', filenames[0])
+
         data_files = natural_sort(filenames)
 
         neng = len(data_files)
-        if verbose: print ('Number of energies ', neng)
-        
+        if verbose: print('Number of energies ', neng)
+
         self.stack4D = []
         theta = []
-        
-        for i in range(neng):     
-            #Read the data
+
+        for i in range(neng):
+            # Read the data
             thisstack, thistheta = self.read_ncb_data(data_files[i])
-                    
-            #Check if we have negative angles, if yes convert to 0-360deg
+
+            # Check if we have negative angles, if yes convert to 0-360deg
             for ith in range(len(thistheta)):
                 if thistheta[ith] < 0:
                     thistheta[ith] = thistheta[ith] + 360
-                    
+
             self.stack4D.append(thisstack)
             theta.append(thistheta)
-            
+
             dims = thisstack.shape
-        
-        
+
         self.stack4D = np.array(self.stack4D)
-        self.stack4D = np.transpose(self.stack4D, axes=(1,2,0,3))
-        
+        self.stack4D = np.transpose(self.stack4D, axes=(1, 2, 0, 3))
+
         self.theta = theta[0]
         self.n_theta = len(theta)
-        
-                
-        self.absdata = self.stack4D[:,:,:,0]
-        
+
+        self.absdata = self.stack4D[:, :, :, 0]
+
         self.data_dwell = np.ones((neng))
-        
-        return 
-        
\ No newline at end of file
+
+        return
diff --git a/mantis_xray/file_plugins/file_nexus_hdf5.py b/mantis_xray/file_plugins/file_nexus_hdf5.py
index 4059edb..f4cd5ca 100755
--- a/mantis_xray/file_plugins/file_nexus_hdf5.py
+++ b/mantis_xray/file_plugins/file_nexus_hdf5.py
@@ -26,6 +26,12 @@ extension = ['*.hdf','*.hdf5','*.nxs']
 read_types = ['spectrum','image','stack']
 write_types = []#'spectrum','image','stack']
 
+def perhaps_decode(value):
+	try:
+		return value.decode("utf-8")	# h5py <3.0
+	except AttributeError:
+		return value					# h5py >=3.0
+
 def identify(filename):
     try:
         # Open HDF5 file
@@ -63,8 +69,10 @@ def read(FileName,stack_object,selection=(0,0), *args, **kwargs):
         axes_list = [item.decode('UTF-8') for item in F[entry][detector].attrs['axes']]
         if 'line_position' in axes_list:
             axes_order = [axes_list.index('line_position'),axes_list.index('line_position'),axes_list.index('energy')] #linescan
+        elif 'energy' in axes_list:
+            axes_order = [axes_list.index('sample_x'),axes_list.index('sample_y'),axes_list.index('energy')] #stack
         else:
-            axes_order = [axes_list.index('sample_x'),axes_list.index('sample_y'),axes_list.index('energy')] #stack or image
+            axes_order = [axes_list.index('sample_x'),axes_list.index('sample_y')] #image
     else: # Old version from before the specification was finalised
         if 'energy' in list(F[entry][detector]):
             try:
@@ -78,14 +86,15 @@ def read(FileName,stack_object,selection=(0,0), *args, **kwargs):
         axes_order = [F[entry][detector]['sample_x'].attrs['axis']-1,F[entry][detector]['sample_y'].attrs['axis']-1,energy_axis-1]
     signal_name = 'data'
     if 'signal' in list(F[entry][detector].attrs):
-        signal_name = F[entry][detector].attrs['signal'].decode("utf-8")
+        signal_name = perhaps_decode(F[entry][detector].attrs['signal'])
     if axes_order[0] == axes_order[1]: #i.e. if linescan
         temp = numpy.transpose(numpy.array(F[entry][detector][signal_name]),axes=axes_order[1:])
         stack_object.absdata = numpy.tile(temp,(temp.shape[0],1,1))
+    elif len(axes_order)<3: #i.e. if image
+        stack_object.absdata = numpy.expand_dims(numpy.transpose(numpy.array(F[entry][detector][signal_name]),axes=axes_order),2)
     else:
         stack_object.absdata = numpy.transpose(numpy.array(F[entry][detector][signal_name]),axes=axes_order)
 
-
     F.close()
 
     stack_object.fill_h5_struct_from_stk()
@@ -119,11 +128,11 @@ def GetFileStructure(FileName):
                     D[entry].scan_type = F[entry][channel_zero]['stxm_scan_type'][0].decode("utf-8")
                 signal_name = 'data'
                 if 'signal' in list(F[entry][channel_zero].attrs):
-                    signal_name = F[entry][channel_zero].attrs['signal'].decode("utf-8")
+                    signal_name = perhaps_decode(F[entry][channel_zero].attrs['signal'])
                 if signal_name in list(F[entry][channel_zero]):
                     D[entry].data_shape = F[entry][channel_zero][signal_name].shape
                 if 'axes' in list(F[entry][channel_zero].attrs):
-                    D[entry].data_axes = [item.decode('UTF-8') for item in F[entry][channel_zero].attrs['axes']]
+                    D[entry].data_axes = [perhaps_decode(item) for item in F[entry][channel_zero].attrs['axes']]
     F.close()
     if len(D) == 0:
         return None
diff --git a/mantis_xray/file_plugins/file_sdf.py b/mantis_xray/file_plugins/file_sdf.py
index 9117ba5..89fc64e 100644
--- a/mantis_xray/file_plugins/file_sdf.py
+++ b/mantis_xray/file_plugins/file_sdf.py
@@ -1,298 +1,308 @@
-# -*- coding: utf-8 -*-
-#
-#   This file is part of Mantis, a Multivariate ANalysis Tool for Spectromicroscopy.
-#
-#   Copyright (C) 2015 Benjamin Watts, Paul Scherrer Institut
-#   License: GNU GPL v3
-#
-#   Mantis 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
-#   any later version.
-#
-#   Mantis 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 <http://www.gnu.org/licenses/>.
-
-
-from __future__ import print_function
-import json
-import re, numpy, sys
-from os.path import splitext, join, dirname, isfile
-from collections import OrderedDict
-
-
-title = 'SDF'
-extension = ['*.hdr']
-read_types = ['spectrum','image','stack']
-write_types = []
-def identify(filename):
-    try:
-        if isfile(splitext(filename)[0] + '.json'):
-            print("JSON-file found. No need to fetch again.")
-            return False
-        else:
-            HDR = HDR_FileParser(filename)
-            return HDR.num_regions > 0  # return true if file contains at least one region
-    except:
-        return False
-
-def GetFileStructure(FileName):
-    HDR = HDR_FileParser(FileName)
-    if HDR.num_regions<2 and HDR.num_channels<2 and isfile(splitext(FileName)[0] + '.json'): #if json file exists, skip datachoicedialog
-        return None # exit if only one choice
-    D = OrderedDict()
-    for i,R in enumerate(['Region_'+str(r) for r in range(HDR.num_regions)]):
-        D[R] = OrderedDict()
-        D[R].definition = 'SDF'
-        D[R].scan_type = HDR.hdr['ScanDefinition']['Type']
-        D[R].data_shape = HDR.data_size[i]
-        D[R].data_axes = [HDR.hdr['ScanDefinition']['Regions'][1]['PAxis']['Name'],HDR.hdr['ScanDefinition']['Regions'][1]['QAxis']['Name'],HDR.hdr['ScanDefinition']['StackAxis']['Name']]
-        for ch in range(1,HDR.num_channels+1):
-            D[R][HDR.hdr['Channels'][ch]['Name']] = OrderedDict()
-    return D
-
-
-
-#----------------------------------------------------------------------
-class HDR_FileParser:
-  """Parse .hdr file for metadata."""
-  hdr = []
-  f = []
-  def __init__(self, fileName,identify=False):
-    if not HDR_FileParser.hdr or HDR_FileParser.f != fileName: # prevent class from fetching and parsing the *.hdr file multiple times. Use the class attribute "hdr" instead if available and check if a new file (not "f") is loaded.
-        # compile some regular expressions
-        self.MatchReStruct = re.compile('[\s\{\}\(\)=";]')
-        self.MatchReArray = re.compile('[,\s\{\(\);]')
-        self.__file = open(fileName)
-        # Parse the HDR file
-        HDR_FileParser.hdr = self.parseStructure()
-        HDR_FileParser.f = fileName
-        self.__file.close()
-    else:
-        None
-    self.hdr = HDR_FileParser.hdr
-    if 'ScanDefinition' in self.hdr:
-      self.num_regions = int(self.hdr['ScanDefinition']['Regions'][0])
-      self.num_channels = int(self.hdr['Channels'][0])
-      self.file_path, self.file_ext = splitext(fileName)
-      self.data_size = self.parse_DataSize()
-      self.data_names = self.parseDataNames()
-    else:
-      self.num_regions = 0
-      self.num_channels = 0
-
-
-
-#----------------------------------------------------------------------
-  def parseStructure(self):
-    """.hdr files consist of structures and arrays. This routine sorts through the structure parts."""
-    Structure = {}
-    BuildWord=''
-    BeforeEq=True
-    QuotedWord=False
-    raw = self.__file.read(1)
-    while len(raw) > 0:#until we reach the end of the file
-      matched = self.MatchReStruct.match(raw)
-      if matched == None:
-        BuildWord+=raw
-      elif matched.group() == '"':
-        QuotedWord= not QuotedWord
-      elif QuotedWord==True:
-        BuildWord+=raw
-      elif matched.group() == '=':
-        FieldName=BuildWord
-        BuildWord=''
-        BeforeEq=False
-      elif matched.group() == ';':
-        try:  # convert numbers into ints or floats or end up with a string
-            Structure[FieldName] = int(BuildWord)
-        except ValueError:
-            try:
-                Structure[FieldName] = float(BuildWord)
-            except ValueError:
-                Structure[FieldName] = BuildWord
-        except TypeError:
-            Structure[FieldName] = BuildWord
-        BuildWord=''
-        BeforeEq=True
-      elif matched.group() == '{':
-        #Must be after =
-        BuildWord = self.parseStructure()
-      elif matched.group() == '}':
-        #break loop and return dictionary
-        break
-      elif matched.group() == '(':
-        #Must be after =
-        BuildWord= self.parseArray()
-      elif matched.group() == ')':
-        #This should not happen
-        print(') in structure')
-      raw = self.__file.read(1)
-    return Structure
-
-#----------------------------------------------------------------------
-  def parseArray(self):
-    """.hdr files consist of structures and arrays. This rountine sorts through the array parts."""
-    Array = []
-    BuildWord=''
-    raw = self.__file.read(1)
-    while len(raw) > 0:#until we reach the end of the file
-      matched = self.MatchReArray.match(raw)
-      if matched == None:
-        BuildWord+=raw
-      elif matched.group() == ',':
-        if len(BuildWord) > 0:
-            try:    #convert numbers in array into ints or floats
-                Array.append(int(BuildWord))
-            except ValueError:
-                Array.append(float(BuildWord))
-            BuildWord=''
-      elif matched.group() == ';':
-        print('; in array')
-      elif matched.group() == '{':
-        Array.append(self.parseStructure())
-      elif matched.group() == '(':
-        Array.append(self.parseArray())
-      elif matched.group() == ')':
-        if len(BuildWord) > 0:
-            try:  #convert numbers in array into ints or floats
-                Array.append(int(BuildWord))
-            except ValueError:
-                try:
-                    Array.append(float(BuildWord))
-                except ValueError: # There is an error in the HDF5toSDF conversion script at the SLS/PolLux which appends arrays with a superfluous "}". Obviously, this char cannot be converted to int or float. We therefore just skip it here.
-                    pass
-        break
-      raw = self.__file.read(1)
-    return Array
-
-#----------------------------------------------------------------------
-  def parseDataNames(self): #ToDo: Assigning Scan types by DataFlags is prone to errors. Better detect automatically via (HDR.hdr['ScanDefinition']['Regions'][0]) etc.
-    """Figure out names for the .xsp or .xim files that contain the actual data, then check that the files actually exist, printing warnings if they don't."""
-    DataNames = []#Regions
-    DataNames2 = []#Channels
-    DataNames3 = []#Energies
-    Alphabet = 'abcdefghijklmnopqrstuvwxyz'
-    DataFlag = self.hdr['ScanDefinition']['Flags']
-    if DataFlag in ['Spectra','Multi-Region Spectra']:
-      for num_R in range(self.num_regions):
-        DataNames2 = []
-        for num_Ch in range(self.num_channels):
-          DataNames2.append([self.file_path+'_'+str(num_R)+'.xsp'])
-        DataNames.append(DataNames2)
-    elif DataFlag == 'Image':
-      DataNames2 = []
-      for num_Ch in range(self.num_channels):
-        DataNames2.append([self.file_path+'_'+Alphabet[num_Ch]+'.xim'])
-      DataNames.append(DataNames2)
-    elif DataFlag in ['Multi-Region Image', 'Multi-Region Image Stack']:
-      for num_R in range(self.num_regions):
-        DataNames2 = []
-        for num_Ch in range(self.num_channels):
-          DataNames2.append([self.file_path+'_'+Alphabet[num_Ch]+str(num_R)+'.xim'])
-        DataNames.append(DataNames2)
-    elif DataFlag == 'Image Stack':
-      DataNames2 = []
-      for num_Ch in range(self.num_channels):
-        DataNames3 = []
-        for num_E in range(self.data_size[0][2]):
-          DataNames3.append(self.file_path+'_'+Alphabet[num_Ch]+str(num_E).zfill(3)+'.xim')
-        DataNames2.append(DataNames3)
-      DataNames = [DataNames2]
-    else:
-      print("WARNING! Unknown flag:", DataFlag)
-    #for num_R in range(len(DataNames)):#Check that names correspond to existing files
-      #for num_Ch in range(len(DataNames[num_R])):
-        #for num_E in range(len(DataNames[num_R][num_Ch])):
-          #if exists(DataNames[num_R][num_Ch][num_E]) == False:
-            #print "WARNING! Data file doesn't exist:", DataNames[num_R][num_Ch][num_E]
-    return DataNames
-
-#----------------------------------------------------------------------
-  def parse_DataSize(self):
-    """Calculate data array size. This is useful for making sure all of the lists of data are the correct length."""
-    DataSize = []
-    for R_num in range(self.num_regions):
-      DataSize.append([1,1,1])# [PAxis,QAxis,StackAxis] (switch to [X1,X2,E] later)]
-      DataSize[R_num][0] = int(self.hdr['ScanDefinition']['Regions'][R_num+1]['PAxis']['Points'][0])
-      if 'QAxis' in self.hdr['ScanDefinition']['Regions'][R_num+1] and 'Points' in self.hdr['ScanDefinition']['Regions'][R_num+1]['QAxis']:
-        DataSize[R_num][1] = int(self.hdr['ScanDefinition']['Regions'][R_num+1]['QAxis']['Points'][0])
-      if 'StackAxis' in self.hdr['ScanDefinition'] and 'Points' in self.hdr['ScanDefinition']['StackAxis']:
-        DataSize[R_num][2] = int(self.hdr['ScanDefinition']['StackAxis']['Points'][0])
-      if self.hdr['ScanDefinition']['Type'] in ['NEXAFS Point Scan','NEXAFS Line Scan']:
-        DataSize[R_num] = [DataSize[R_num][1],1,DataSize[R_num][0]]#switch to [X1,X2,E] format
-#        DataSize[R_num] = [1,DataSize[R_num][1],DataSize[R_num][0]]#also works, but might be problematic for finding number of spatial points
-    return DataSize
-
-
-
-
-#----------------------------------------------------------------------
-#----------------------------------------------------------------------
-def read(filename, self, selection=None, JSONstatus=None):
-    HDR = HDR_FileParser(filename)
-    if JSONstatus:
-        with open(splitext(filename)[0] + '.json', 'w') as outfile:
-            json.dump(HDR.hdr, outfile, indent=4, sort_keys=True, ensure_ascii=True)
-            print("JSON-file written at "+ splitext(filename)[0] + '.json')
-    if HDR.hdr['ScanDefinition']['Flags'] == 'Image Stack':
-
-        self.x_dist = numpy.array([float(i) for i in HDR.hdr['ScanDefinition']['Regions'][selection[0]+1]['PAxis']['Points'][1:] ])
-        self.y_dist = numpy.array([float(i) for i in HDR.hdr['ScanDefinition']['Regions'][selection[0]+1]['QAxis']['Points'][1:] ])
-        self.ev = numpy.array([float(i) for i in HDR.hdr['ScanDefinition']['StackAxis']['Points'][1:] ])
-
-        self.n_cols = numpy.array(len(self.x_dist))
-        self.n_rows = numpy.array(len(self.y_dist))
-        self.n_ev = numpy.array(len(self.ev))
-
-        msec = float(HDR.hdr['ScanDefinition']['Dwell'])
-        self.data_dwell = numpy.ones((self.n_ev))*msec
-
-        imagestack = numpy.empty((self.n_cols,self.n_rows,self.n_ev), numpy.int32)
-        for i in range(len(HDR.data_names[selection[0]][selection[1]])):
-            try:
-                imagestack[:,:,i] = numpy.loadtxt(HDR.data_names[selection[0]][selection[1]][i], numpy.int32).T
-            except ValueError:
-                print("Aborted stack or XIMs with inconsistent dimensions.")
-                imagestack[:,:,i] = numpy.nan
-            except IOError:
-                print("Image file not found.")
-                imagestack[:,:,i] = numpy.nan
-        self.absdata = numpy.empty((self.n_cols,self.n_rows, self.n_ev))
-
-        self.absdata = numpy.reshape(imagestack, (self.n_cols,self.n_rows, self.n_ev), order='F')
-
-        self.fill_h5_struct_from_stk()
-
-    else:
-        print("Only Image Stack files are supported.") # ToDo: Urgent need to add support for multi-region image stacks and single images
-
-    return
-
-#----------------------------------------------------------------------
-def read_sdf_i0(self, filename):
-    HDR = HDR_FileParser(filename)
-
-    if 'ScanType' in HDR.hdr['ScanDefinition'] and HDR.hdr['ScanDefinition']['ScanType'] == 'Spectra':
-        Energies = HDR.hdr['ScanDefinition']['Regions'][1]['PAxis']['Points'][1:]
-        tempimage = numpy.loadtxt(HDR.data_names[0][0][0], numpy.float32)
-        Data = tempimage[:,1]
-    elif HDR.hdr['ScanDefinition']['Type'] == 'NEXAFS Line Scan':
-        Energies = HDR.hdr['ScanDefinition']['Regions'][1]['PAxis']['Points'][1:]
-        tempimage = numpy.loadtxt(HDR.data_names[0][0][0], numpy.int32)
-        Data = numpy.mean(tempimage,axis=0)
-    else:# Image Stack
-        Energies = HDR.hdr['ScanDefinition']['StackAxis']['Points'][1:]
-        tempimage = numpy.empty((HDR.data_size[0][0],HDR.data_size[0][1]), numpy.int32)
-        Data = numpy.empty((HDR.data_size[0][2]), numpy.int32)
-        for i in range(len(HDR.data_names[0][0])):
-            tempimage = numpy.loadtxt(HDR.data_names[0][0][i], numpy.int32)
-            Data[i] = numpy.mean(tempimage)
-
-    msec = float(HDR.hdr['ScanDefinition']['Dwell'])#shouldn't this be needed?
-    self.i0_dwell = msec
-    self.evi0 = numpy.array([float(i) for i in Energies])
-    self.i0data = Data
-    return
+# -*- coding: utf-8 -*-
+#
+#   This file is part of Mantis, a Multivariate ANalysis Tool for Spectromicroscopy.
+#
+#   Copyright (C) 2015 Benjamin Watts, Paul Scherrer Institut
+#   License: GNU GPL v3
+#
+#   Mantis 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
+#   any later version.
+#
+#   Mantis 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 <http://www.gnu.org/licenses/>.
+
+
+from __future__ import print_function
+import json
+import re, numpy, sys
+from os.path import splitext, join, dirname, isfile
+from collections import OrderedDict
+
+
+title = 'SDF'
+extension = ['*.hdr']
+read_types = ['spectrum','image','stack']
+write_types = []
+def identify(filename):
+    try:
+        if isfile(splitext(filename)[0] + '.json'):
+            print("JSON-file found. No need to fetch again.")
+            return False
+        else:
+            HDR = HDR_FileParser(filename)
+            return HDR.num_regions > 0  # return true if file contains at least one region
+    except:
+        return False
+
+def GetFileStructure(FileName):
+    HDR = HDR_FileParser(FileName)
+    if HDR.num_regions<2 and HDR.num_channels<2 and isfile(splitext(FileName)[0] + '.json'): #if json file exists, skip datachoicedialog
+        return None # exit if only one choice
+    D = OrderedDict()
+    for i,R in enumerate(['Region_'+str(r) for r in range(HDR.num_regions)]):
+        D[R] = OrderedDict()
+        D[R].definition = 'SDF'
+        D[R].scan_type = HDR.hdr['ScanDefinition']['Type']
+        D[R].data_shape = HDR.data_size[i]
+        D[R].data_axes = [HDR.hdr['ScanDefinition']['Regions'][1]['PAxis']['Name'],HDR.hdr['ScanDefinition']['Regions'][1]['QAxis']['Name'],HDR.hdr['ScanDefinition']['StackAxis']['Name']]
+        for ch in range(1,HDR.num_channels+1):
+            D[R][HDR.hdr['Channels'][ch]['Name']] = OrderedDict()
+    return D
+
+
+
+#----------------------------------------------------------------------
+class HDR_FileParser:
+  """Parse .hdr file for metadata."""
+  hdr = []
+  f = []
+  def __init__(self, fileName,identify=False):
+    if not HDR_FileParser.hdr or HDR_FileParser.f != fileName: # prevent class from fetching and parsing the *.hdr file multiple times. Use the class attribute "hdr" instead if available and check if a new file (not "f") is loaded.
+        # compile some regular expressions
+        self.MatchReStruct = re.compile('[\s\{\}\(\)=";]')
+        self.MatchReArray = re.compile('[,\s\{\(\);]')
+        self.__file = open(fileName)
+        # Parse the HDR file
+        HDR_FileParser.hdr = self.parseStructure()
+        HDR_FileParser.f = fileName
+        self.__file.close()
+    else:
+        None
+    self.hdr = HDR_FileParser.hdr
+    if 'ScanDefinition' in self.hdr:
+      self.num_regions = int(self.hdr['ScanDefinition']['Regions'][0])
+      self.num_channels = int(self.hdr['Channels'][0])
+      self.file_path, self.file_ext = splitext(fileName)
+      self.data_size = self.parse_DataSize()
+      self.data_names = self.parseDataNames()
+    else:
+      self.num_regions = 0
+      self.num_channels = 0
+
+
+
+#----------------------------------------------------------------------
+  def parseStructure(self):
+    """.hdr files consist of structures and arrays. This routine sorts through the structure parts."""
+    Structure = {}
+    BuildWord=''
+    BeforeEq=True
+    QuotedWord=False
+    raw = self.__file.read(1)
+    while len(raw) > 0:#until we reach the end of the file
+      matched = self.MatchReStruct.match(raw)
+      if matched == None:
+        BuildWord+=raw
+      elif matched.group() == '"':
+        QuotedWord= not QuotedWord
+      elif QuotedWord==True:
+        BuildWord+=raw
+      elif matched.group() == '=':
+        FieldName=BuildWord
+        BuildWord=''
+        BeforeEq=False
+      elif matched.group() == ';':
+        try:  # convert numbers into ints or floats or end up with a string
+            Structure[FieldName] = int(BuildWord)
+        except ValueError:
+            try:
+                Structure[FieldName] = float(BuildWord)
+            except ValueError:
+                Structure[FieldName] = BuildWord
+        except TypeError:
+            Structure[FieldName] = BuildWord
+        BuildWord=''
+        BeforeEq=True
+      elif matched.group() == '{':
+        #Must be after =
+        BuildWord = self.parseStructure()
+      elif matched.group() == '}':
+        #break loop and return dictionary
+        break
+      elif matched.group() == '(':
+        #Must be after =
+        BuildWord= self.parseArray()
+      elif matched.group() == ')':
+        #This should not happen
+        print(') in structure')
+      raw = self.__file.read(1)
+    return Structure
+
+#----------------------------------------------------------------------
+  def parseArray(self):
+    """.hdr files consist of structures and arrays. This rountine sorts through the array parts."""
+    Array = []
+    BuildWord=''
+    raw = self.__file.read(1)
+    while len(raw) > 0:#until we reach the end of the file
+      matched = self.MatchReArray.match(raw)
+      if matched == None:
+        BuildWord+=raw
+      elif matched.group() == ',':
+        if len(BuildWord) > 0:
+            try:    #convert numbers in array into ints or floats
+                Array.append(int(BuildWord))
+            except ValueError:
+                Array.append(float(BuildWord))
+            BuildWord=''
+      elif matched.group() == ';':
+        print('; in array')
+      elif matched.group() == '{':
+        Array.append(self.parseStructure())
+      elif matched.group() == '(':
+        Array.append(self.parseArray())
+      elif matched.group() == ')':
+        if len(BuildWord) > 0:
+            try:  #convert numbers in array into ints or floats
+                Array.append(int(BuildWord))
+            except ValueError:
+                try:
+                    Array.append(float(BuildWord))
+                except ValueError: # There is an error in the HDF5toSDF conversion script at the SLS/PolLux which appends arrays with a superfluous "}". Obviously, this char cannot be converted to int or float. We therefore just skip it here.
+                    pass
+        break
+      raw = self.__file.read(1)
+    return Array
+
+#----------------------------------------------------------------------
+  def parseDataNames(self): #ToDo: Assigning Scan types by DataFlags is prone to errors. Better detect automatically via (HDR.hdr['ScanDefinition']['Regions'][0]) etc.
+    """Figure out names for the .xsp or .xim files that contain the actual data, then check that the files actually exist, printing warnings if they don't."""
+    DataNames = []#Regions
+    DataNames2 = []#Channels
+    DataNames3 = []#Energies
+    Alphabet = 'abcdefghijklmnopqrstuvwxyz'
+    DataFlag = self.hdr['ScanDefinition']['Flags']
+    if DataFlag in ['Spectra','Multi-Region Spectra']:
+      for num_R in range(self.num_regions):
+        DataNames2 = []
+        for num_Ch in range(self.num_channels):
+          DataNames2.append([self.file_path+'_'+str(num_R)+'.xsp'])
+        DataNames.append(DataNames2)
+    elif DataFlag == 'Image':
+      DataNames2 = []
+      for num_Ch in range(self.num_channels):
+        DataNames2.append([self.file_path+'_'+Alphabet[num_Ch]+'.xim'])
+      DataNames.append(DataNames2)
+    elif DataFlag in ['Multi-Region Image']:
+      for num_R in range(self.num_regions):
+        DataNames2 = []
+        for num_Ch in range(self.num_channels):
+          DataNames2.append([self.file_path+'_'+Alphabet[num_Ch]+str(num_R)+'.xim'])
+        DataNames.append(DataNames2)
+    elif DataFlag in ['Multi-Region Image Stack']:
+      for num_Ch in range(self.num_channels):
+        DataNames2 = []
+        for num_R in range(self.num_regions):
+            DataNames3 = []
+            for num_E in range(self.data_size[0][2]):
+                DataNames3.append(self.file_path + '_' + Alphabet[num_Ch] + str(num_E).zfill(3)+str(num_R)+ '.xim')
+            DataNames2.append(DataNames3)
+        DataNames = [DataNames2]
+    elif DataFlag == 'Image Stack':
+      DataNames2 = []
+      for num_Ch in range(self.num_channels):
+        DataNames3 = []
+        for num_E in range(self.data_size[0][2]):
+          DataNames3.append(self.file_path+'_'+Alphabet[num_Ch]+str(num_E).zfill(3)+'.xim')
+        DataNames2.append(DataNames3)
+      DataNames = [DataNames2]
+    else:
+      print("WARNING! Unknown flag:", DataFlag)
+    #for num_R in range(len(DataNames)):#Check that names correspond to existing files
+      #for num_Ch in range(len(DataNames[num_R])):
+        #for num_E in range(len(DataNames[num_R][num_Ch])):
+          #if exists(DataNames[num_R][num_Ch][num_E]) == False:
+            #print "WARNING! Data file doesn't exist:", DataNames[num_R][num_Ch][num_E]
+    return DataNames
+
+#----------------------------------------------------------------------
+  def parse_DataSize(self):
+    """Calculate data array size. This is useful for making sure all of the lists of data are the correct length."""
+    DataSize = []
+    for R_num in range(self.num_regions):
+      DataSize.append([1,1,1])# [PAxis,QAxis,StackAxis] (switch to [X1,X2,E] later)]
+      DataSize[R_num][0] = int(self.hdr['ScanDefinition']['Regions'][R_num+1]['PAxis']['Points'][0])
+      if 'QAxis' in self.hdr['ScanDefinition']['Regions'][R_num+1] and 'Points' in self.hdr['ScanDefinition']['Regions'][R_num+1]['QAxis']:
+        DataSize[R_num][1] = int(self.hdr['ScanDefinition']['Regions'][R_num+1]['QAxis']['Points'][0])
+      if 'StackAxis' in self.hdr['ScanDefinition'] and 'Points' in self.hdr['ScanDefinition']['StackAxis']:
+        DataSize[R_num][2] = int(self.hdr['ScanDefinition']['StackAxis']['Points'][0])
+      if self.hdr['ScanDefinition']['Type'] in ['NEXAFS Point Scan','NEXAFS Line Scan']:
+        DataSize[R_num] = [DataSize[R_num][1],1,DataSize[R_num][0]]#switch to [X1,X2,E] format
+#        DataSize[R_num] = [1,DataSize[R_num][1],DataSize[R_num][0]]#also works, but might be problematic for finding number of spatial points
+    return DataSize
+
+
+
+
+#----------------------------------------------------------------------
+#----------------------------------------------------------------------
+def read(filename, self, selection=None, JSONstatus=None):
+    HDR = HDR_FileParser(filename)
+    if JSONstatus:
+        with open(splitext(filename)[0] + '.json', 'w') as outfile:
+            json.dump(HDR.hdr, outfile, indent=4, sort_keys=True, ensure_ascii=True)
+            print("JSON-file written at "+ splitext(filename)[0] + '.json')
+    allowed =['Image Stack','Image','Multi-Region Image Stack']
+    if HDR.hdr['ScanDefinition']['Flags'] in allowed:
+
+        self.x_dist = numpy.array([float(i) for i in HDR.hdr['ScanDefinition']['Regions'][selection[0]+1]['PAxis']['Points'][1:] ])
+        self.y_dist = numpy.array([float(i) for i in HDR.hdr['ScanDefinition']['Regions'][selection[0]+1]['QAxis']['Points'][1:] ])
+        self.ev = numpy.array([float(i) for i in HDR.hdr['ScanDefinition']['StackAxis']['Points'][1:] ])
+
+        self.n_cols = len(self.x_dist)
+        self.n_rows = len(self.y_dist)
+        self.n_ev = len(self.ev)
+
+        msec = float(HDR.hdr['ScanDefinition']['Dwell'])
+        self.data_dwell = numpy.ones((self.n_ev))*msec
+
+        imagestack = numpy.empty((self.n_cols,self.n_rows,self.n_ev), numpy.int32)
+        for i in range(len(HDR.data_names[selection[1]][selection[0]])):
+            try:
+                imagestack[:,:,i] = numpy.loadtxt(HDR.data_names[selection[1]][selection[0]][i], numpy.int32).T
+            except ValueError:
+                print("Aborted stack or XIMs with inconsistent dimensions.")
+                imagestack[:,:,i] = numpy.nan
+            except IOError:
+                print("Image file not found.")
+                imagestack[:,:,i] = numpy.nan
+        self.absdata = numpy.empty((self.n_cols,self.n_rows, self.n_ev))
+
+        self.absdata = numpy.reshape(imagestack, (self.n_cols,self.n_rows, self.n_ev), order='F')
+
+        self.fill_h5_struct_from_stk()
+
+    else:
+        print("Unknown Format")
+
+    return
+
+#----------------------------------------------------------------------
+def read_sdf_i0(self, filename):
+    HDR = HDR_FileParser(filename)
+
+    if 'ScanType' in HDR.hdr['ScanDefinition'] and HDR.hdr['ScanDefinition']['ScanType'] == 'Spectra':
+        Energies = HDR.hdr['ScanDefinition']['Regions'][1]['PAxis']['Points'][1:]
+        tempimage = numpy.loadtxt(HDR.data_names[0][0][0], numpy.float32)
+        Data = tempimage[:,1]
+    elif HDR.hdr['ScanDefinition']['Type'] == 'NEXAFS Line Scan':
+        Energies = HDR.hdr['ScanDefinition']['Regions'][1]['PAxis']['Points'][1:]
+        tempimage = numpy.loadtxt(HDR.data_names[0][0][0], numpy.int32)
+        Data = numpy.mean(tempimage,axis=0)
+    else:# Image Stack
+        Energies = HDR.hdr['ScanDefinition']['StackAxis']['Points'][1:]
+        tempimage = numpy.empty((HDR.data_size[0][0],HDR.data_size[0][1]), numpy.int32)
+        Data = numpy.empty((HDR.data_size[0][2]), numpy.int32)
+        for i in range(len(HDR.data_names[0][0])):
+            tempimage = numpy.loadtxt(HDR.data_names[0][0][i], numpy.int32)
+            Data[i] = numpy.mean(tempimage)
+
+    msec = float(HDR.hdr['ScanDefinition']['Dwell'])#shouldn't this be needed?
+    self.i0_dwell = msec
+    self.evi0 = numpy.array([float(i) for i in Energies])
+    self.i0data = Data
+    return
\ No newline at end of file
diff --git a/mantis_xray/helpers.py b/mantis_xray/helpers.py
index 75da405..be5fea2 100644
--- a/mantis_xray/helpers.py
+++ b/mantis_xray/helpers.py
@@ -2,5 +2,30 @@ def resource_path(relative_path):
     import os, sys
 
     """ Get absolute path to resource, works for dev and for PyInstaller """
-    base_path = getattr(sys, '_MEIPASS', os.getcwd())
+    base_path = getattr(sys, '_MEIPASS', os.path.dirname(__file__))
     return os.path.join(base_path, relative_path)
+
+
+def check_for_updates(current_version):
+    import urllib.request, re
+    # Scrape the version string from the PyPI:mantis-xray RSS feed
+    try:
+        with urllib.request.urlopen("https://pypi.org/rss/project/mantis_xray/releases.xml") as init_file:
+            pypi_rss = init_file.read()
+        #print(pypi_rss)
+        pypi_list = re.findall(r"(?:\<title\>\s*)([\d\.]+)(?:\s*\</title\>)", pypi_rss.decode())[0]
+        print("Latest package on PyPI is version {0}".format(pypi_list))
+    except:
+        pass
+    
+    # Scrape version string from the code in the github repository
+    try:
+        with urllib.request.urlopen("https://raw.githubusercontent.com/mlerotic/spectromicroscopy/master/mantis_xray/__init__.py") as init_file:
+            github_init = init_file.read()
+        #print(github_init)
+        github_latest = re.search(r"(?:__version__*\s=*\s)['|\"]+([\d\.]+)", github_init.decode()).group(1)
+        print("Current development code is version {0}".format(github_latest))
+    except:
+        pass
+    
+    
diff --git a/mantis_xray/images/mirror.png b/mantis_xray/images/mirror.png
new file mode 100644
index 0000000..09fe40c
Binary files /dev/null and b/mantis_xray/images/mirror.png differ
diff --git a/mantis_xray/images/rotate.png b/mantis_xray/images/rotate.png
new file mode 100644
index 0000000..119f624
Binary files /dev/null and b/mantis_xray/images/rotate.png differ
diff --git a/mantis_xray/mantis.py b/mantis_xray/mantis.py
index 7df7266..6fc99c2 100644
--- a/mantis_xray/mantis.py
+++ b/mantis_xray/mantis.py
@@ -18,28 +18,32 @@
 
 import sys
 import os
-import getopt
 import numpy as np
 import matplotlib
 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
 #from matplotlib.backends.backend_qt5agg import FigureCanvas
 from matplotlib.figure import Figure
-from mpl_toolkits.axes_grid1.axes_divider import make_axes_locatable
-from mpl_toolkits.axes_grid1.colorbar import colorbar
-#from mpl_toolkits.axes_grid1 import make_axes_locatable
-
-import data_struct
-import data_stack
-import analyze
-import henke
-
-import file_plugins
-from file_plugins import file_xrm
-from file_plugins import file_bim
-from file_plugins import file_dataexch_hdf5
-from file_plugins import file_ncb
-from file_plugins import file_tif
-from file_plugins import file_stk
+from mpl_toolkits.axes_grid1 import make_axes_locatable
+from matplotlib import colorbar
+
+#Internal imports
+from . import data_struct
+from . import data_stack
+from . import analyze
+from . import nnma
+from . import henke
+from . import tomo_reconstruction
+
+from . import file_plugins
+from .file_plugins import file_xrm
+from .file_plugins import file_bim
+from .file_plugins import file_dataexch_hdf5
+from .file_plugins import file_ncb
+from .file_plugins import file_json
+from .file_plugins import file_tif
+from .file_plugins import file_stk
+from .file_plugins import file_csv
+    
 
 PlotH = 4.0
 PlotW = PlotH*1.61803
@@ -768,27 +772,8 @@ def main():
 
     verbose = True
 
-    run_qt = 1
-    run_cl = 0
-    arguments = sys.argv[1:]
-    try:
-        options, extraParams = getopt.getopt(arguments, '', ['batch', 'nnma'])
-    except:
-        print('Error - wrong command line option used. Available options are --batch and --nnma')
-        return
-
-    for opt, arg in options:
-        if opt in '--batch':
-            run_qt = 0
-            run_cl = 1
-
-
-    if run_qt == 1:
-        import mantis_qt
-        m_qt = mantis_qt.main()
-    elif run_cl == 1:
-        print('Running Mantis in batch mode.')
-        batch_mode()
+    print('Running Mantis in batch mode.')
+    batch_mode()
 
     sys.exit()
 
diff --git a/mantis_xray/mantis_qt.py b/mantis_xray/mantis_qt.py
index a3bb56a..f5ce71b 100644
--- a/mantis_xray/mantis_qt.py
+++ b/mantis_xray/mantis_qt.py
@@ -22,17 +22,26 @@ from __future__ import absolute_import
 
 import sys
 import os
-import numpy as np
-from numpy import NAN
 import time
+import copy
+
+import numpy as np
 import getopt
 
 from PyQt5 import QtCore, QtGui, QtWidgets, uic
-from PyQt5.QtCore import Qt, QCoreApplication, pyqtSignal
+from PyQt5.QtCore import Qt, QCoreApplication, pyqtSignal, pyqtSlot
+
+QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
+QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
 
 from PIL import Image
 from scipy import ndimage
-
+from scipy.stats import linregress
+from scipy.interpolate import interp1d
+# from skimage.feature import register_translation ## deprecated
+from skimage.registration import phase_cross_correlation
+from queue import SimpleQueue, Empty
+import threading
 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
 from matplotlib.backends.backend_qt5agg import (
         NavigationToolbar2QT as NavigationToolbar)
@@ -47,6 +56,7 @@ import pyqtgraph as pg
 import pyqtgraph.exporters
 from lxml import etree
 
+
 #Internal imports
 from . import data_struct
 from . import data_stack
@@ -67,6 +77,16 @@ from .file_plugins import file_stk
 from .file_plugins import file_csv
 
 from .__init__ import __version__ as version
+welcome_string = "Welcome to MANTiS {0}".format(version)
+print("="*len(welcome_string))
+print(welcome_string)
+print("="*len(welcome_string))
+from .helpers import check_for_updates
+check_for_updates(version)
+print("\nPlease report issues to https://github.com/mlerotic/spectromicroscopy/issues \n")
+
+## Global Stylesheet
+qsspath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'stylesheet_global.qss')
 
 if sys.platform == 'win32':
     Winsizex = 1000
@@ -491,18 +511,18 @@ class PageTomo(QtWidgets.QWidget):
         #vboxt1.addWidget(sizer3)
         #vboxt1.addStretch (1)
 
-        hboxtop.addStretch (0.5)
+        hboxtop.addStretch (5)
         hboxtop.addLayout(vboxt1)
-        hboxtop.addStretch (0.5)
+        hboxtop.addStretch (5)
         hboxtop.addLayout(vbox5)
-        hboxtop.addStretch (0.5)
+        hboxtop.addStretch (5)
 
 
 
 
-        vboxtop.addStretch (0.5)
+        vboxtop.addStretch (5)
         vboxtop.addLayout(hboxtop)
-        vboxtop.addStretch (0.9)
+        vboxtop.addStretch (9)
 
         vboxtop.setContentsMargins(20,20,20,20)
         self.setLayout(vboxtop)
@@ -1649,7 +1669,7 @@ class File_GUI():
         dlg=QtWidgets.QFileDialog(None)
         dlg.setWindowTitle('Choose File')
         dlg.setViewMode(QtWidgets.QFileDialog.Detail)
-        dlg.setOption(QtWidgets.QFileDialog.DontUseNativeDialog)
+        #dlg.setOption(QtWidgets.QFileDialog.DontUseNativeDialog)
         if action == "write":
             dlg.setAcceptMode(QtWidgets.QFileDialog.AcceptSave)
         dlg.setDirectory(self.last_path[action][data_type])
@@ -1670,7 +1690,6 @@ class File_GUI():
                 self.last_filter[action][data_type] = i
             return (str(dlg.selectedFiles()[0]),chosen_plugin)
         else:
-            print("cancelled")
             return (None,None)
 
 
@@ -6799,7 +6818,8 @@ class PageCluster(QtWidgets.QWidget):
         frame.setFrameStyle(QtWidgets.QFrame.StyledPanel|QtWidgets.QFrame.Sunken)
         fbox = QtWidgets.QHBoxLayout()
 
-        self.clusterindvimgfig = Figure((PlotH*0.73, PlotH*0.73))
+        #self.clusterindvimgfig = Figure((PlotH*0.73, PlotH*0.73))
+        self.clusterindvimgfig = Figure((PlotH, PlotH))
         self.ClusterIndvImagePan = FigureCanvas(self.clusterindvimgfig)
         self.ClusterIndvImagePan.setParent(self)
         fbox.addWidget(self.ClusterIndvImagePan)
@@ -6820,7 +6840,7 @@ class PageCluster(QtWidgets.QWidget):
         frame = QtWidgets.QFrame()
         frame.setFrameStyle(QtWidgets.QFrame.StyledPanel|QtWidgets.QFrame.Sunken)
         fbox = QtWidgets.QHBoxLayout()
-        self.clusterdistmapfig = Figure((PlotH*0.73, PlotH*0.73))
+        self.clusterdistmapfig = Figure((PlotH, PlotH))
         self.ClusterDistMapPan = FigureCanvas(self.clusterdistmapfig)
         self.ClusterDistMapPan.setParent(self)
         fbox.addWidget(self.ClusterDistMapPan)
@@ -7082,10 +7102,8 @@ class PageCluster(QtWidgets.QWidget):
 #Show composite cluster image
     def showIndvClusterImage(self):
 
-        indvclusterimage = np.zeros((self.anlz.stack.n_cols, self.anlz.stack.n_rows))+20.
-        ind = np.where(self.anlz.cluster_indices == self.selcluster-1)
-        colorcl = min(self.selcluster-1,self.maxclcolors-1)
-        indvclusterimage[ind] = colorcl
+        indvclusterimage = self.anlz.cluster_indices.copy()
+        indvclusterimage[indvclusterimage!=self.selcluster-1] = 20.
 
         fig = self.clusterindvimgfig
         fig.clf()
@@ -7263,6 +7281,7 @@ class PageCluster(QtWidgets.QWidget):
             if img_tif:
                 fileName_caimg = self.SaveFileName+"_CAcimg.tif"
                 img1 = Image.fromarray(self.clusterimage)
+                #ToDo: Recently throws an error. Possible conflict in module PIL. "Cannot handle this data type: (1, 1), <i8"
                 img1.save(fileName_caimg)
 
 
@@ -7560,7 +7579,7 @@ class PageCluster(QtWidgets.QWidget):
                         x_comp = od_reduced[:,ip]
                         y_comp = od_reduced[:,jp]
                         if nplots > 1 :
-                            axes = fig.add_subplot(nplotsrows,2, pplot)
+                            axes = fig.add_subplot(int(nplotsrows),int(2), int(pplot))
                         else:
                             axes = fig.add_subplot(1,1,1)
 
@@ -8874,21 +8893,35 @@ class PageStack(QtWidgets.QWidget):
         vbox1.setSpacing(0)
 
         self.button_align = QtWidgets.QPushButton('Align stack...')
-        self.button_align.clicked.connect(self.OnAlignImgs)
+        self.button_align.clicked.connect(self.OnAlignImgsDialog)
         self.button_align.setEnabled(False)
         vbox1.addWidget(self.button_align)
 
+        # self.button_align2 = QtWidgets.QPushButton('Align stack v2...')
+        # self.button_align2.clicked.connect( self.OnAlignImgs2)
+        # self.button_align2.setEnabled(False)
+        # vbox1.addWidget(self.button_align2)
 
+        self.button_multicrop = QtWidgets.QPushButton('Crop stack 3D/4D...')
+        self.button_multicrop.clicked.connect( self.OnMultiCrop)
+        self.button_multicrop.setEnabled(False)
+        vbox1.addWidget(self.button_multicrop)
 
-        self.button_limitev = QtWidgets.QPushButton('Limit energy range...')
-        self.button_limitev.clicked.connect( self.OnLimitEv)
-        self.button_limitev.setEnabled(False)
-        vbox1.addWidget(self.button_limitev)
 
-        self.button_subregion = QtWidgets.QPushButton('Clip to subregion...')
-        self.button_subregion.clicked.connect(self.OnCliptoSubregion)
-        self.button_subregion.setEnabled(False)
-        vbox1.addWidget(self.button_subregion)
+        # self.button_limitev = QtWidgets.QPushButton('Limit energy range...')
+        # self.button_limitev.clicked.connect( self.OnLimitEv)
+        # self.button_limitev.setEnabled(False)
+        # vbox1.addWidget(self.button_limitev)
+
+        # self.button_subregion = QtWidgets.QPushButton('Clip to subregion...')
+        # self.button_subregion.clicked.connect(self.OnCliptoSubregion)
+        # self.button_subregion.setEnabled(False)
+        # vbox1.addWidget(self.button_subregion)
+
+        self.button_artefacts = QtWidgets.QPushButton('Artefacts && Leveling')
+        self.button_artefacts.clicked.connect( self.OnArtefacts)
+        self.button_artefacts.setEnabled(False)
+        vbox1.addWidget(self.button_artefacts)
 
         self.button_darksig = QtWidgets.QPushButton('Dark signal subtraction...')
         self.button_darksig.clicked.connect(self.OnDarkSignal)
@@ -9056,7 +9089,7 @@ class PageStack(QtWidgets.QWidget):
 
         self.slider_gamma = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
         self.slider_gamma.setRange(1,20)
-        self.slider_gamma.setValue(self.displaygamma)
+        self.slider_gamma.setValue(int(self.displaygamma))
         self.slider_gamma.setFocusPolicy(QtCore.Qt.StrongFocus)
         self.slider_gamma.valueChanged[int].connect(self.OnScrollGamma)
 
@@ -9105,12 +9138,6 @@ class PageStack(QtWidgets.QWidget):
         self.button_addROI.setEnabled(False)
         vbox3.addWidget(self.button_addROI)
 
-        self.button_acceptROI = QtWidgets.QPushButton('Accept ROI')
-        self.button_acceptROI.clicked.connect( self.OnAcceptROI)
-        self.button_acceptROI.setEnabled(False)
-        self.button_acceptROI.setVisible(False)
-        vbox3.addWidget(self.button_acceptROI)
-
         self.button_resetROI = QtWidgets.QPushButton('Reset ROI')
         self.button_resetROI.clicked.connect( self.OnResetROI)
         self.button_resetROI.setEnabled(False)
@@ -9257,7 +9284,7 @@ class PageStack(QtWidgets.QWidget):
                 self.iy = int(y/2)
                 self.stk.read_sdf_i0(filepath)
                 self.com.i0_loaded = 1
-                self.loadSpectrum(self.ix, self.iy)
+                self.showSpectrum(self.ix, self.iy)
                 self.loadImage()
 
                 QtWidgets.QApplication.restoreOverrideCursor()
@@ -9276,7 +9303,7 @@ class PageStack(QtWidgets.QWidget):
                 self.stk.read_stk_i0(filepath, extension)
 
                 self.com.i0_loaded = 1
-                self.loadSpectrum(self.ix, self.iy)
+                self.showSpectrum(self.ix, self.iy)
                 self.loadImage()
 
                 QtWidgets.QApplication.restoreOverrideCursor()
@@ -9294,7 +9321,7 @@ class PageStack(QtWidgets.QWidget):
                 self.stk.read_stk_i0(filepath, extension)
 
                 self.com.i0_loaded = 1
-                self.loadSpectrum(self.ix, self.iy)
+                self.showSpectrum(self.ix, self.iy)
                 self.loadImage()
 
                 QtWidgets.QApplication.restoreOverrideCursor()
@@ -9329,7 +9356,7 @@ class PageStack(QtWidgets.QWidget):
             self.stk.od = self.stk.od3d.copy()
             self.stk.od = np.reshape(self.stk.od, (self.stk.n_cols*self.stk.n_rows, self.stk.n_ev), order='F')
 
-        self.loadSpectrum(self.ix, self.iy)
+        self.showSpectrum(self.ix, self.iy)
         self.loadImage()
 
         self.window().refresh_widgets()
@@ -9341,12 +9368,18 @@ class PageStack(QtWidgets.QWidget):
         plot.show()
 
 #----------------------------------------------------------------------
+    def OnArtefacts(self, event):
+        # self.window().Hide()
+        artefacts = ShowArtefacts(self.window(), self.com, self.stk)
+        artefacts.show()
+
+    # ----------------------------------------------------------------------
     def OnPreNormalizedData(self, event):
 
         self.stk.UsePreNormalizedData()
 
         self.com.i0_loaded = 1
-        self.loadSpectrum(self.ix, self.iy)
+        self.showSpectrum(self.ix, self.iy)
         self.loadImage()
 
         self.window().refresh_widgets()
@@ -9377,7 +9410,7 @@ class PageStack(QtWidgets.QWidget):
             self.ix = int(x/2)
             self.iy = int(y/2)
 
-            self.loadSpectrum(self.ix, self.iy)
+            self.showSpectrum(self.ix, self.iy)
             self.loadImage()
             self.com.i0_loaded = 1
             QtWidgets.QApplication.restoreOverrideCursor()
@@ -9404,7 +9437,7 @@ class PageStack(QtWidgets.QWidget):
         self.showflux = True
         self.rb_flux.setChecked(True)
 
-        self.loadSpectrum(self.ix, self.iy)
+        self.showSpectrum(self.ix, self.iy)
         self.loadImage()
         self.window().refresh_widgets()
 
@@ -9420,16 +9453,20 @@ class PageStack(QtWidgets.QWidget):
         savewin = SaveWinP1(self.window())
         savewin.show()
 
+# ----------------------------------------------------------------------
+    def OnMultiCrop(self, evt):
+        multicropwin = MultiCrop(self.window(), self.com, self.stk)
+        multicropwin.show()
 #----------------------------------------------------------------------
-    def OnLimitEv(self, evt):
-
-        limitevwin = LimitEv(self.window(), self.com, self.stk)
-        limitevwin.show()
-
-#----------------------------------------------------------------------
-    def OnCliptoSubregion(self, evt):
-        clipwin = CliptoSubregion(self.window(), self.com, self.stk)
-        clipwin.show()
+#     def OnLimitEv(self, evt):
+#
+#         limitevwin = LimitEv(self.window(), self.com, self.stk)
+#         limitevwin.show()
+#
+# #----------------------------------------------------------------------
+#     def OnCliptoSubregion(self, evt):
+#         clipwin = CliptoSubregion(self.window(), self.com, self.stk)
+#         clipwin.show()
 
 #----------------------------------------------------------------------
     def Save(self, filename, path, spec_png = True, spec_pdf = False, spec_svg = False, sp_csv = False,
@@ -9587,13 +9624,25 @@ class PageStack(QtWidgets.QWidget):
 
         return
 
+# ----------------------------------------------------------------------
+    def OnAlignImgsDialog(self, event):
+
+        # self.window().Hide()
+        imgregwin = ImageRegistrationDialog(self.window(),self.com)
+        imgregwin.show()
 #----------------------------------------------------------------------
     def OnAlignImgs(self, event):
 
         #self.window().Hide()
-        imgregwin = ImageRegistration(self.window(), self.com, self.stk)
+        imgregwin = ImageRegistrationManual(self.window(), self.com, self.stk)
         imgregwin.show()
 
+# ----------------------------------------------------------------------
+    def OnAlignImgs2(self, event):
+
+        imgreg2 = ImageRegistrationFFT(self.window(), self.com, self.stk)
+        imgreg2.show()
+
 #----------------------------------------------------------------------
     def OnDarkSignal(self, event):
 
@@ -9621,13 +9670,13 @@ class PageStack(QtWidgets.QWidget):
                 self.iev = i
                 self.loadImage()
                 self.slider_eng.setValue(self.iev)
-                self.loadSpectrum(self.ix, self.iy)
+                self.showSpectrum(self.ix, self.iy)
 
 
             self.iev = old_iev
             self.loadImage()
             self.slider_eng.setValue(self.iev)
-            self.loadSpectrum(self.ix, self.iy)
+            self.showSpectrum(self.ix, self.iy)
             self.button_slideshow.setText("Play stack movie")
             self.movie_playing = 0
 
@@ -9640,7 +9689,7 @@ class PageStack(QtWidgets.QWidget):
 
         if self.com.stack_loaded == 1:
             self.loadImage()
-            self.loadSpectrum(self.ix, self.iy)
+            self.showSpectrum(self.ix, self.iy)
 
 #----------------------------------------------------------------------
     def OnScrollTheta(self, value):
@@ -9659,7 +9708,7 @@ class PageStack(QtWidgets.QWidget):
 
         if self.com.stack_loaded == 1:
             self.loadImage()
-            self.loadSpectrum(self.ix, self.iy)
+            self.showSpectrum(self.ix, self.iy)
 
 
         self.window().page0.itheta = self.itheta
@@ -9684,7 +9733,7 @@ class PageStack(QtWidgets.QWidget):
 
             self.iev = sel_ev
 
-            self.loadSpectrum(self.ix, self.iy)
+            self.showSpectrum(self.ix, self.iy)
             self.loadImage()
 
             self.slider_eng.setValue(self.iev)
@@ -9692,12 +9741,9 @@ class PageStack(QtWidgets.QWidget):
 
 #----------------------------------------------------------------------
     def OnPointAbsimage(self, evt):
-
-
         x = evt.xdata
         y = evt.ydata
 
-
         if (x == None) or (y == None):
             return
 
@@ -9715,28 +9761,9 @@ class PageStack(QtWidgets.QWidget):
                 self.iy=self.stk.n_rows-1
 
 
-            self.loadSpectrum(self.ix, self.iy)
+            self.showSpectrum(self.ix, self.iy)
             self.loadImage()
 
-
-        if (self.com.stack_loaded == 1) and (self.addroi == 1):
-            if self.line == None: # if there is no line, create a line
-                self.line = matplotlib.lines.Line2D([x,  x], [y, y], marker = '.', color = 'red')
-                self.start_point = [x,y]
-                self.previous_point =  self.start_point
-                self.roixdata.append(x)
-                self.roiydata.append(y)
-                self.loadImage()
-            # add a segment
-            else: # if there is a line, create a segment
-                self.roixdata.append(x)
-                self.roiydata.append(y)
-                self.line.set_data(self.roixdata,self.roiydata)
-                self.previous_point = [x,y]
-                if len(self.roixdata) == 3:
-                    self.button_acceptROI.setEnabled(True)
-                self.loadImage()
-
 #----------------------------------------------------------------------
     def OnRb_fluxod(self, enabled):
 
@@ -9775,7 +9802,7 @@ class PageStack(QtWidgets.QWidget):
 
         if self.com.stack_loaded == 1:
             self.loadImage()
-            self.window().page0.ShowImage()
+            #self.window().page0.ShowImage()
 
 #----------------------------------------------------------------------
     def OnShowColBar(self, state):
@@ -9860,7 +9887,7 @@ class PageStack(QtWidgets.QWidget):
     def loadImage(self):
 
 
-        if (self.defaultdisplay == 1.0):
+        if self.defaultdisplay == 1.0:
             #use a pointer to the data not a copy
             if self.showflux:
                 #Show flux image
@@ -9950,7 +9977,7 @@ class PageStack(QtWidgets.QWidget):
 
 
 #----------------------------------------------------------------------
-    def loadSpectrum(self, xpos, ypos):
+    def showSpectrum(self, xpos, ypos):
 
 
         fig = self.specfig
@@ -9959,19 +9986,23 @@ class PageStack(QtWidgets.QWidget):
         axes = fig.gca()
 
 
+        axes.set_xlabel('Photon Energy [eV]')
         if self.com.i0_loaded == 1:
             self.spectrum = self.stk.od3d[int(xpos),int(ypos), :]
-
-            axes.set_xlabel('Photon Energy [eV]')
             axes.set_ylabel('Optical Density')
         else:
-
             self.spectrum = self.stk.absdata[int(xpos),int(ypos), :]
-            axes.set_xlabel('Photon Energy [eV]')
             axes.set_ylabel('Flux')
 
+        if self.addroi == 0:
+            self.tc_spec.setText('Spectrum at pixel [{0}, {1}] or position [{2:5.2f}, {3:5.2f}]'.format(str(xpos),  str(ypos), np.float(self.stk.x_dist[int(xpos)]), np.float(self.stk.y_dist[int(ypos)])))
+            specplot = axes.plot(self.stk.ev,self.spectrum)
+        else:
+            self.tc_spec.setText("Average ROI Spectrum: ")
+            self.CalcROISpectrum()
+            specplot = axes.plot(self.stk.ev,self.ROIspectrum)
 
-        specplot = axes.plot(self.stk.ev,self.spectrum)
+        
 
         axes.axvline(x=self.stk.ev[self.iev], color = 'g', alpha=0.5)
 
@@ -9979,8 +10010,6 @@ class PageStack(QtWidgets.QWidget):
         self.SpectrumPanel.draw()
 
 
-        self.tc_spec.setText('Spectrum at pixel [{0}, {1}] or position [{2:5.2f}, {3:5.2f}]'.format(str(xpos),  str(ypos), np.float(self.stk.x_dist[int(xpos)]), np.float(self.stk.y_dist[int(ypos)])))
-
 #----------------------------------------------------------------------
     def ResetDisplaySettings(self):
 
@@ -9998,66 +10027,26 @@ class PageStack(QtWidgets.QWidget):
 
         self.slider_brightness_max.setValue(self.dispbrightness_max)
         self.slider_brightness_min.setValue(self.dispbrightness_min)
-        self.slider_gamma.setValue(self.displaygamma)
+        self.slider_gamma.setValue(int(self.displaygamma))
 
         self.tc_min.setText('Minimum: \t{0:5d}%'.format(int(100*self.brightness_min)))
         self.tc_max.setText('Maximum:{0:5d}%'.format(int(100*self.brightness_max)))
         self.tc_gamma.setText('Gamma:  \t{0:5.2f}'.format(self.gamma))
 
 
-
-#----------------------------------------------------------------------
-# Determine if a point is inside a given polygon or not. The algorithm is called
-# "Ray Casting Method".
-    def point_in_poly(self, x, y, polyx, polyy):
-
-        n = len(polyx)
-        inside = False
-
-        p1x = polyx[0]
-        p1y = polyy[0]
-        for i in range(n+1):
-            p2x = polyx[i % n]
-            p2y = polyy[i % n]
-            if y > min(p1y,p2y):
-                if y <= max(p1y,p2y):
-                    if x <= max(p1x,p2x):
-                        if p1y != p2y:
-                            xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
-                            if p1x == p2x or x <= xinters:
-                                inside = not inside
-            p1x,p1y = p2x,p2y
-
-        return inside
-
 #----------------------------------------------------------------------
     def OnAddROI(self, evt):
-#         self.addroi = 1
-#         self.previous_point = []
-#         self.start_point = []
-#         self.end_point = []
-#         self.line = None
-#         self.roixdata = []
-#         self.roiydata = []
 
         self.addroi = 1
-
         self.AbsImagePanel.mpl_disconnect(self.cid1)
 
-
-
         lineprops = dict(color='red', linestyle='-', linewidth = 1, alpha=1)
 
-
         self.lasso = LassoSelector(self.axes, onselect=self.OnSelectLasso, useblit=False, lineprops=lineprops)
 
-
         fig = self.specfig
         fig.clf()
-        self.SpectrumPanel.draw()
-        self.tc_spec.setText("Average ROI Spectrum: ")
 
-        self.button_acceptROI.setEnabled(False)
         self.button_resetROI.setEnabled(True)
         self.button_ROIdosecalc.setEnabled(False)
         self.window().refresh_widgets()
@@ -10076,86 +10065,20 @@ class PageStack(QtWidgets.QWidget):
 
 
 
-
-        for ie in range(self.stk.n_ev):
-            thiseng_od = self.stk.od3d[:,:,ie]
-            self.ROIspectrum[ie] = np.sum(thiseng_od[indices])/numroipix
-
-#----------------------------------------------------------------------
-    def ShowROISpectrum(self):
-
-        self.CalcROISpectrum()
-
-        fig = self.specfig
-        fig.clf()
-        fig.add_axes((0.15,0.15,0.75,0.75))
-        axes = fig.gca()
-
-
-        specplot = axes.plot(self.stk.ev,self.ROIspectrum)
-
-        axes.set_xlabel('Photon Energy [eV]')
-        axes.set_ylabel('Optical Density')
-
-        self.SpectrumPanel.draw()
-
-        self.tc_spec.setText("Average ROI Spectrum: ")
-
-#----------------------------------------------------------------------
-    def OnAcceptROI(self, evt):
-        QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(Qt.WaitCursor))
-        self.roixdata.append(self.start_point[0])
-        self.roiydata.append(self.start_point[1])
-        self.line.set_data(self.roixdata,self.roiydata)
-        #self.loadImage()
-
-        #find pixels inside the polygon
-        if self.ROIpix == None:
-            self.ROIpix = np.zeros((self.stk.n_cols,self.stk.n_rows))
-
-
-        print(self.stk.n_cols, self.stk.n_rows)
-
-        for i in range(self.stk.n_cols):
-            for j in range(self.stk.n_rows):
-                Pinside = self.point_in_poly(i, j, self.roixdata, self.stk.n_rows-1-self.roiydata)
-                if Pinside == True:
-                    self.ROIpix[i, j] = 255
-
-
-
-        self.ROIpix = np.ma.array(self.ROIpix)
-
-
-        self.ROIpix_masked =  np.ma.masked_values(self.ROIpix, 0)
-
-
-        self.showROImask = 1
-        self.line = None
-        self.previous_point = []
-        self.start_point = []
-        self.end_point = []
-        self.roixdata = []
-        self.roiydata = []
-
-        self.button_saveROIspectr.setEnabled(True)
-        self.button_setROII0.setEnabled(True)
-        self.button_ROIdosecalc.setEnabled(True)
-        self.window().refresh_widgets()
-
-        self.loadImage()
-        if (self.com.i0_loaded == 1):
-            self.ShowROISpectrum()
-
-        QtWidgets.QApplication.restoreOverrideCursor()
-
-
+        if self.com.i0_loaded == 1:
+            for ie in range(self.stk.n_ev):
+                thiseng_od = self.stk.od3d[:,:,ie]
+                self.ROIspectrum[ie] = np.sum(thiseng_od[indices])/numroipix
+        else:
+            for ie in range(self.stk.n_ev):
+                thiseng_abs = self.stk.absdata[:,:,ie]
+                self.ROIspectrum[ie] = np.sum(thiseng_abs[indices])/numroipix
+            
 
 #----------------------------------------------------------------------
 
     def OnSelectLasso(self,verts):
 
-
         path = matplotlib.path.Path(verts)
         #find pixels inside the polygon
 
@@ -10190,8 +10113,7 @@ class PageStack(QtWidgets.QWidget):
         self.window().refresh_widgets()
 
         self.loadImage()
-        if (self.com.i0_loaded == 1):
-            self.ShowROISpectrum()
+        self.showSpectrum(0, 0)
 
         QtWidgets.QApplication.restoreOverrideCursor()
 
@@ -10208,17 +10130,17 @@ class PageStack(QtWidgets.QWidget):
         self.showROImask = 0
         self.ROIpix = None
 
-        self.button_acceptROI.setEnabled(False)
+        #self.button_acceptROI.setEnabled(False)
         self.button_setROII0.setEnabled(False)
         self.button_resetROI.setEnabled(False)
         self.button_saveROIspectr.setEnabled(False)
         self.button_ROIdosecalc.setEnabled(False)
+        self.cid1 = self.AbsImagePanel.mpl_connect('button_press_event', self.OnPointAbsimage)
+        self.AbsImagePanel.draw()
         self.window().refresh_widgets()
 
-        if (self.com.i0_loaded == 1):
-            self.loadImage()
-            self.loadSpectrum(self.ix, self.iy)
-        pass
+        self.loadImage()
+        self.showSpectrum(self.ix, self.iy)
 
 #----------------------------------------------------------------------
     def CalcROI_I0Spectrum(self):
@@ -10254,7 +10176,7 @@ class PageStack(QtWidgets.QWidget):
         self.showROImask = 0
         self.ROIpix = None
 
-        self.loadSpectrum(self.ix, self.iy)
+        self.showSpectrum(self.ix, self.iy)
         self.loadImage()
 
         self.button_acceptROI.setEnabled(False)
@@ -10525,7 +10447,7 @@ class SaveWinP1(QtWidgets.QDialog):
                                          img_all_tif = im_all_tif)
 
 #----------------------------------------------------------------------
-class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
+class ShowHistogram(QtWidgets.QDialog, QtWidgets.QGraphicsScene):
     def __init__(self, parent, stack):
         QtWidgets.QWidget.__init__(self, parent)
         dir_path = os.path.dirname(os.path.realpath(__file__))
@@ -10548,7 +10470,7 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         self.AbsImage = pg.ImageItem(border="k",parent= self)
         self.lassopoints= []
         self.vb.setMouseEnabled(x=False, y=False)
-        self.vb.addItem(self.AbsImage, ignoreBounds=True)
+        self.vb.addItem(self.AbsImage, ignoreBounds=False)
         self.MaskImage = pg.ImageItem(border="k")
         self.vb.addItem(self.MaskImage)
         self.redpix = np.zeros([self.stack.n_cols, self.stack.n_rows, 4], dtype=np.uint8)
@@ -10560,7 +10482,7 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         self.draw_image(self.histmin,self.histmax)
 
         self.I0box = pg.PolyLineROI([[1, 1], [0, 1], [0, 0], [1, 0]], pen=(5, 8), closed=True)
-        self.vb.addItem(self.I0box, ignoreBounds=True)
+        self.vb.addItem(self.I0box, ignoreBounds=False)
         self.I0box.clearPoints()
 
         self.clickdetector = QtCore.QTimer()
@@ -10576,11 +10498,12 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         if self.radioLassoROI.isChecked():
             self.proxy = pg.SignalProxy(self.vb.scene().sigMouseMoved, rateLimit=15, slot=self.OnMouseHover) # rate limit to avoid too many handles
             self.I0box.handlePen = QtGui.QPen(QtGui.QColor(255, 0, 128, 0))
-        elif self.radioPolyROI.isChecked():
-            self.proxy = pg.SignalProxy(self.vb.scene().sigMouseMoved, rateLimit=30, slot=self.OnMouseHover)
-            self.I0box.handlePen = QtGui.QPen(QtGui.QColor(255, 0, 128, 255))
+        ##Polygon is currently broken
+        # elif self.radioPolyROI.isChecked():
+        #     self.proxy = pg.SignalProxy(self.vb.scene().sigMouseMoved, rateLimit=30, slot=self.OnMouseHover)
+        #     self.I0box.handlePen = QtGui.QPen(QtGui.QColor(255, 0, 128, 255))
         try:
-            self.I0box.sigRegionChangeFinished.disconnect(self.DrawROI)
+            self.I0box.sigRegionChangeFinished.disconnect()
             self.I0box.clearPoints()
             self.proxy.block = False
         except:
@@ -10589,6 +10512,7 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
 #----------------------------------------------------------------------
     def draw_histogram(self):
         histogram_data =  np.reshape(self.stack.histogram, (self.stack.n_cols*self.stack.n_rows), order='F')
+        histogram_data = histogram_data[~np.isnan(histogram_data)] #remove non-finite values
 
         y, x = np.histogram(histogram_data, bins=100)
 
@@ -10597,9 +10521,8 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         self.region.setZValue(10)
 
         plot = self.HistoWidget
-        plot.addItem(self.region, ignoreBounds=True)
+        plot.addItem(self.region, ignoreBounds=False)
         plot.setMouseEnabled(x=False, y=False)
-        plot.setLogMode(x=False, y=True)
         plot.showGrid(y=True)
 
         plot.showAxis("top", show=True)
@@ -10610,9 +10533,15 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         bx.setStyle(showValues=False,tickLength=0)
         ay = plot.getAxis("left")
         ax = plot.getAxis("bottom")
-        ay.setLabel(text="Number of pixels")
-        ax.setLabel(text="Average Flux")
 
+        ax.setLabel(text="Average Flux")
+        ## Little hack to display vertical axis as log.
+        plot.getViewBox().setLimits(yMin=0,yMax=np.max(y))
+        ay.setLabel(text="log<sub>10</sub> (Number of pixels)")
+        y[y < 1] = 1
+        y = np.log10(y)
+        plot.setLogMode(x=False, y=False) ## Log mode is not working correctly at the moment.
+        ##
         plot.plot(x, y, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150))
         def update(region):
             self.region.setZValue(10)
@@ -10628,7 +10557,7 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         if not self.vb.scene().clickEvents:
             self.proxy.block = True
             self.DrawROI()
-            self.I0instructions.setText("Drag the polygon or the handles. Add handles by clicking on a line segment.")
+            #self.I0instructions.setText("Drag the polygon or the handles. Add handles by clicking on a line segment.")
             if self.radioLassoROI.isChecked():
                 self.lassopoints= []
                 self.I0instructions.setText("")
@@ -10678,28 +10607,28 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
                 self.MaskImage.setZValue(-10)
                 self.I0box.setZValue(10)
                 self.clickdetector.start(10)
-                if self.radioPolyROI.isChecked():
-                    origin = self.vb.mapSceneToView(self.vb.scene().clickEvents[0].scenePos())
-                    if origin.x() < 0:
-                        x0 = 0-roipos.x()
-                    elif origin.x() > self.stack.n_cols:
-                        x0 = self.stack.n_cols - roipos.x()
-                    else:
-                        x0 = np.round(origin.x()-roipos.x(),0)
-                    if origin.y() < 0:
-                        y0 = 0-roipos.y()
-                    elif origin.y() > self.stack.n_rows:
-                        y0 = self.stack.n_rows - roipos.y()
-                    else:
-                        y0 = np.round(origin.y()-roipos.y(),0)
-                    self.I0box.setPoints([(np.round(pos.x()-roipos.x(),0),np.round(pos.y()-roipos.y(),0)), (x0,np.round(pos.y()-roipos.y(),0)),(x0,y0),(np.round(pos.x()-roipos.x(),0),y0)], closed=True)
-
-                elif self.radioLassoROI.isChecked():
+                if self.radioLassoROI.isChecked():
                     handle = self.I0box.addFreeHandle((np.round(pos.x()-roipos.x(),0),np.round(pos.y()-roipos.y(),0)))
                     self.lassopoints.append(handle)
                     if len(self.lassopoints) > 1:
                         self.I0box.addSegment(self.lassopoints[0], self.lassopoints[1])
                         self.lassopoints.pop(0)
+                ## Polygon ROI is currently broken in recent pyqtgraph version
+                # elif self.radioPolyROI.isChecked():
+                #     origin = self.vb.mapSceneToView(self.vb.scene().clickEvents[0].scenePos())
+                #     if origin.x() < 0:
+                #         x0 = 0-roipos.x()
+                #     elif origin.x() > self.stack.n_cols:
+                #         x0 = self.stack.n_cols - roipos.x()
+                #     else:
+                #         x0 = np.round(origin.x()-roipos.x(),0)
+                #     if origin.y() < 0:
+                #         y0 = 0-roipos.y()
+                #     elif origin.y() > self.stack.n_rows:
+                #         y0 = self.stack.n_rows - roipos.y()
+                #     else:
+                #         y0 = np.round(origin.y()-roipos.y(),0)
+                #     self.I0box.setPoints([(np.round(pos.x()-roipos.x(),0),np.round(pos.y()-roipos.y(),0)), (x0,np.round(pos.y()-roipos.y(),0)),(x0,y0),(np.round(pos.x()-roipos.x(),0),y0)], closed=True)
 
     def draw_image(self,fluxmin, fluxmax):
         self.I0instructions.setText(
@@ -10715,443 +10644,590 @@ class ShowHistogram(QtWidgets.QDialog, QtGui.QGraphicsScene):
         if self.MaskImage.zValue() > 0 and np.any(self.i0_indices[0]):
             self.stack.i0_from_histogram(self.i0_indices)
             self.parent.I0histogramCalculated()
+            self.stack.i0_mask = self.redpix
+            self.stack.i0_mask[:, :] = False
+            self.stack.i0_mask[self.i0_indices] = True
             self.close()
         else:
             self.i0_indices = []
             QtWidgets.QMessageBox.warning(self, 'Error', 'I0 region is empty!')
 
 #----------------------------------------------------------------------
-class LimitEv(QtWidgets.QDialog):
-
-    def __init__(self, parent,  common, stack):
+class ShowArtefacts(QtWidgets.QDialog):
+    def __init__(self, parent, common, stack):
         QtWidgets.QWidget.__init__(self, parent)
-
+        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'showartefacts.ui'), self)
         self.parent = parent
-
-        self.stack = stack
         self.com = common
+        self.stack = stack
+        self.i0_h_warnflag = False
+        self.i0_v_warnflag = False
+        self.pglayout = pg.GraphicsLayout(border=None)
+        self.canvas.setBackground("w") # canvas is a pg.GraphicsView widget
+        self.canvas.setCentralWidget(self.pglayout)
 
-        self.resize(630, 450)
-        self.setWindowTitle('Limit energy range')
-
-        pal = QtGui.QPalette()
-        self.setAutoFillBackground(True)
-        pal.setColor(QtGui.QPalette.Window,QtGui.QColor('white'))
-        self.setPalette(pal)
-
+        self.vb = self.pglayout.addViewBox()
+        self.vb.setAspectLocked()
+        self.i_item = pg.ImageItem(border="k",parent= self)
 
-        self.evlimited = 0
-        self.limitevmin = 0
-        self.limitevmax = self.stack.n_ev-1
 
-        self.patch = None
+        self.button_ok.clicked.connect(self.OnAccept)
+        self.button_cancel.clicked.connect(self.close)
+        self.cb_h.stateChanged.connect(self.ShowImage)
+        self.cb_v.stateChanged.connect(self.ShowImage)
+        #ToDo: I initially wanted to use Qt.QueuedConnection to create a non-blocking Slider.
+        self.weight_slider.valueChanged.connect(self.ShowCalcImage)
+        self.slider_eng.sliderPressed.connect(self.ShowImage)
+        self.slider_eng.sliderReleased.connect(self.ShowImage)
+        self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
 
-        vbox = QtWidgets.QVBoxLayout()
+        self.setWindowTitle('Artefacts & Leveling')
+        self.slider_eng.setRange(0, self.stack.n_ev - 1)
 
+        self.vb.setMouseEnabled(x=False, y=False)
+        self.vb.addItem(self.i_item, ignoreBounds=False)
 
-        frame = QtWidgets.QFrame()
-        frame.setFrameStyle(QtWidgets.QFrame.StyledPanel|QtWidgets.QFrame.Sunken)
-        fbox = QtWidgets.QHBoxLayout()
+        self.stack.absdata_level = self.stack.absdata.copy()
+        if self.com.i0_loaded:
+            self.rb_median_i0.setCheckable(True)
+            self.rb_median_i0.setChecked(True)
+            self.label_4.setText('I0 mask contribution:')
+        else:
+            self.sliderWidget.hide()
+        self.rb_median.toggled.connect(self.ShowImage)
+        self.OnScrollEng(0)
+
+    def ShowCalcImage(self):
+        if any([self.cb_h.isChecked(),self.cb_v.isChecked()]):
+            a = self.stack.absdata[:, :, self.slider_eng.value()].astype('float64')
+            a, wf = self.LevelCalc(a)
+            if self.rb_median_i0.isChecked():
+                self.label_3.setText(str('{:d}').format(int(wf))+' %')
+            self.i_item.setImage(a)
+
+    def CorrectionArray(self,array,axis,wf,mask = None,):
+        # calculate median along given axis, ignoring nans if present
+        array_i = np.nanmedian(array, axis=axis, keepdims=False)
+        if mask is not None and wf != 0.0:
+            array = np.where(mask, array, np.nan) # replace masked pixels by nans
+            # calculate median along given axis, ignoring nans if present
+            array = np.nanmedian(array, axis=axis, keepdims=False)
+            bg_median = np.nanmedian(array, axis=0, keepdims=False)
+        if mask is None or wf == 0.0:
+            # returns the median filtered array neglecting the i0 mask
+            return (np.nanmedian(array_i, axis=0, keepdims=False) - array_i)
+        elif wf == 1:
+            return ((bg_median - array)*(wf))
+        else:
+            return ((bg_median - array)*(wf) + (bg_median - array_i)*(1-wf))
+
+    def LevelCalc(self,a,final=False):
+        wf = 0.0
+        mask = None
+        diff_v = 0
+        diff_h = 0
+        if self.cb_h.isChecked():
+            wf = (self.weight_slider.value()) / 100
+            if self.rb_median_i0.isChecked():
+                mask = self.stack.i0_mask[:, :, 0]
+                if final:
+                    mask = mask[:, :, None]
+            diff_h = self.CorrectionArray(a, 0, float(wf), mask)[None, :]
+            #a += diff[None, :]
+        if self.cb_v.isChecked():
+            wf = (self.weight_slider.value()) / 100
+            if self.rb_median_i0.isChecked():
+                mask = self.stack.i0_mask[:, :, 0]
+                if final:
+                    mask = mask[:, :, None]
+            diff_v = self.CorrectionArray(a, 1, float(wf), mask)[: ,None]
+        a = a + diff_v + diff_h
+        return(a,int(wf*100))
+# ----------------------------------------------------------------------
+    def OnScrollEng(self, value):
+        self.slider_eng.setValue(value)
+        self.iev = value
 
-        self.specfig = Figure((6.0, 4.2))
-        self.SpectrumPanel = FigureCanvas(self.specfig)
-        self.SpectrumPanel.setParent(self)
-        self.SpectrumPanel.mpl_connect('button_press_event', self.OnSelection1)
-        self.SpectrumPanel.mpl_connect('button_release_event', self.OnSelection2)
+        self.ShowImage()
+    def ShowImage(self):
+        if (self.slider_eng.isSliderDown()):
+            self.i_item.setImage(self.stack.absdata[:, :, int(self.iev)])
+        elif any([self.cb_h.isChecked(), self.cb_v.isChecked()]):
+            self.ShowCalcImage()
+        else:
+            self.i_item.setImage(self.stack.absdata[:, :, int(self.iev)])
 
+            self.label_3.setText(str(''))
+        self.groupBox.setTitle(str('Stack Browser | Image at {0:5.2f} eV').format(float(self.stack.ev[self.iev])))
+#----------------------------------------------------------------------
+    def OnAccept(self, evt):
+        a, wf = self.LevelCalc(self.stack.absdata.astype('float64'),final=True)
+        self.stack.absdata = a
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        self.parent.page1.loadImage()
+        self.parent.page0.Clear()
+        self.parent.page0.LoadEntries()
 
-        fbox.addWidget(self.SpectrumPanel)
-        frame.setLayout(fbox)
-        vbox.addWidget(frame)
+        if showmaptab:
+            self.parent.page9.Clear()
+            self.parent.page9.LoadEntries()
 
+        self.close()
+#----------------------------------------------------------------------
+class MultiCrop(QtWidgets.QDialog, QtWidgets.QGraphicsScene):
+    evlistchanged = pyqtSignal([object])
+    thetalistchanged = pyqtSignal([object])
+    def __init__(self, parent, common, stack):
+        QtWidgets.QWidget.__init__(self, parent)
+        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'showmulticrop.ui'), self)
+        self.parent = parent
+        self.stack = stack
+        self.com = common
+        self.iev = 0
+        self.itheta = 0
+        #self.stack.absdata_shifted_cropped = self.stack.absdata_shifted.copy()
 
-        hbox2 = QtWidgets.QHBoxLayout()
-        sizer2 = QtWidgets.QGroupBox('Energy')
-        self.textctrl = QtWidgets.QLabel(self)
-        self.textctrl.setText(' ')
-        hbox2.addWidget(self.textctrl, 0)
-        sizer2.setLayout(hbox2)
-        vbox.addWidget(sizer2)
+        self.poolthread = QtCore.QThread()
+        self.aligned = False
+        self.button_ok.setEnabled(True)
 
-        hbox = QtWidgets.QHBoxLayout()
+        self.setWindowTitle('Stack Cropping')
+        self.pglayout = pg.GraphicsLayout(border=None)
+        self.canvas.setBackground("w") # canvas is a pg.GraphicsView widget
+        self.canvas.setCentralWidget(self.pglayout)
+        self.vb = self.pglayout.addViewBox()
+        self.vb.setAspectLocked()
+        self.i_item = pg.ImageItem(border="k",parent= self)
 
+        self.vb.setMouseEnabled(x=False, y=False)
+        self.vb.addItem(self.i_item, ignoreBounds=False)
 
-        button_ok = QtWidgets.QPushButton('Accept')
-        button_ok.clicked.connect(self.OnAccept)
-        hbox.addWidget(button_ok)
+        self.button_ok.clicked.connect(self.OnAccept)
+        self.button_cancel.clicked.connect(self.OnCancel)
 
-        button_cancel = QtWidgets.QPushButton('Cancel')
-        button_cancel.clicked.connect(self.close)
-        hbox.addWidget(button_cancel)
+        if self.com.stack_loaded == 1:
+            self.label_theta_range.setVisible(False)
+            self.slider_theta.setVisible(False)
+            self.cb_remove_theta.setVisible(False)
+            self.groupBox_theta.setVisible(False)
+            if self.com.stack_4d == 1:
+                self.label_theta_range.setVisible(True)
+                self.slider_theta.setVisible(True)
+                self.cb_remove_theta.setVisible(True)
+                self.groupBox_theta.setVisible(True)
+                self.slider_theta.setRange(0, self.stack.n_theta - 1)
+                self.slider_theta.valueChanged[int].connect(self.OnScrollTheta)
+                self.SetupListTheta()
+            # self.maskedvals = [True] * int(self.stack.n_ev)
+            # self.spinBoxError.setEnabled(False)
+            self.slider_eng.sliderPressed.connect(self.ShowImage)
+            self.slider_eng.sliderReleased.connect(self.ShowImage)
+            self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
+            self.slider_eng.setRange(0, self.stack.n_ev - 1)
+            self.pb_selectall.clicked.connect(self.OnSelectAll)
+            self.pb_clearall.clicked.connect(self.OnClearAll)
+            self.evlistchanged.connect(lambda row: self.qListChangeHandler(row, "energy"))
+            self.thetalistchanged.connect(lambda row: self.qListChangeHandler(row, "theta"))
+            #self.ev_widget.itemClicked.connect(lambda item: self.OnItemClicked(item))
+            self.ev_widget.mousePressEvent = self.mouseEventOnEVList
+            self.ev_widget.mouseMoveEvent = self.mouseEventOnEVList
+            self.theta_widget.mousePressEvent = self.mouseEventOnThetaList
+            self.theta_widget.mouseMoveEvent = self.mouseEventOnThetaList
+            #self.ev_widget.itemSelectionChanged.connect(lambda item: self.OnItemClicked(item))
+            self.SetupListEV()
+            self.OnScrollEng(0)
+            self.SetupROI()
+            self.SetupPlot()
 
-        vbox.addLayout(hbox)
+    def mouseEventOnEVList(self, e):
+        if e.type() == QtCore.QEvent.MouseMove or e.type() == QtCore.QEvent.MouseButtonPress:
+            qlist = self.ev_widget
+            pos = qlist.mapFromGlobal(QtGui.QCursor.pos())
+            row = qlist.indexAt(pos).row()
+            item = qlist.itemAt(pos)
+            #print(row,self.latest_row)
+            if row >= 0:
+                if e.type() != QtCore.QEvent.MouseMove or row != self.latest_row:
+                    if e.buttons() == QtCore.Qt.LeftButton:
+                        qlist.setCurrentRow(row)
+                        self.evlistchanged.emit(item)
+                        self.latest_row = row
+        return
+    def mouseEventOnThetaList(self, e):
+        if e.type() == QtCore.QEvent.MouseMove or e.type() == QtCore.QEvent.MouseButtonPress:
+            qlist = self.theta_widget
+            pos = qlist.mapFromGlobal(QtGui.QCursor.pos())
+            row = qlist.indexAt(pos).row()
+            item = qlist.itemAt(pos)
+            #print(row,self.latest_row)
+            if row >= 0:
+                if e.type() != QtCore.QEvent.MouseMove or row != self.latest_row:
+                    if e.buttons() == QtCore.Qt.LeftButton:
+                        qlist.setCurrentRow(row)
+                        self.thetalistchanged.emit(item)
+                        self.latest_row = row
+        return
+    def OnSelectionChanged(self):
+        self.RedrawNewPlot()
+        #self.UpdateIndices()
+        self.region.blockSignals(True)
+        if self.idx_selected:
+            self.region.setRegion([self.stack.ev[min(self.idx_selected)], self.stack.ev[max(self.idx_selected)]])
+            self.region.blockSignals(False)
+            self.spectrum_plotwidget.setXRange(*self.region.getRegion())
+            self.spectrum_plotwidget.setYRange(np.min(self.plotitem_new.yData),np.max(self.plotitem_new.yData))
+        return
+    def UpdateIndices(self):
+        self.idx_selected = sorted([self.ev_widget.row(i) for i in self.ev_selected])
+        if self.com.stack_4d:
+            self.thetaidx_selected = sorted([self.theta_widget.row(i) for i in self.theta_selected])
+    def RedrawPlots(self):
+        x,y = self.GenerateSpectrum(list(range(self.stack.n_ev)))
+        self.plotitem.setData(x,y)
+        self.OnSelectionChanged()
+    def RedrawNewPlot(self):
+        self.UpdateIndices()
+        x,y = self.GenerateSpectrum(self.idx_selected)
+        self.plotitem_new.setData(x,y)
+        if self.idx_selected:
+            self.region.show()
+    def qListChangeHandler(self,row, dimension):
+        if dimension == "theta":
+            selection = self.theta_selected
+            widget = self.theta_widget
+        elif dimension == "energy":
+            selection = self.ev_selected
+            widget = self.ev_widget
+
+        if row in selection:
+            selection.remove(row)
+            row.setBackground(QtGui.QColor(0, 0, 0, 0))
+        else:
+            selection.append(row)
+            row.setBackground(QtGui.QColor('#beaed4'))
+        if dimension == "theta":
+            self.OnScrollTheta(widget.row(row))
+        elif dimension == "energy":
+            self.OnScrollEng(widget.row(row))
+        self.OnSelectionChanged()
 
-        self.setLayout(vbox)
+    def SetupPlot(self):
+        x,y = self.GenerateSpectrum(list(range(self.stack.n_ev)))
+        self.spectrum_plotwidget.setBackground("w")
 
-        self.draw_limitev_plot()
+        self.region = pg.LinearRegionItem(brush=[255,0,0,45],bounds=[np.min(x),np.max(x)])
 
+        self.region.setZValue(10)
+        plot = self.spectrum_plotwidget
+        plot.setBackground("w")
+        plot.addItem(self.region, ignoreBounds=False)
+        plot.setMouseEnabled(x=False, y=False)
+        plot.showGrid(y=True)
 
-#----------------------------------------------------------------------
-    def draw_limitev_plot(self):
+        plot.showAxis("top", show=True)
+        plot.showAxis("right", show=True)
+        by = plot.getAxis("right")
+        bx = plot.getAxis("top")
+        by.setStyle(showValues=False,tickLength=0)
+        bx.setStyle(showValues=False,tickLength=0)
+        ay = plot.getAxis("left")
+        ax = plot.getAxis("bottom")
 
+        ax.setLabel(text="Photon energy [eV]")
+        if self.com.i0_loaded:
+            ay.setLabel(text="Optical density")
+        else:
+            ay.setLabel(text="Photon flux [cps]")
+
+        self.plotitem = plot.plot(x, y, pen=pg.mkPen(color=0.8, width=2))
+        self.plotitem_new = plot.plot(x, y, pen=pg.mkPen(color="b", width=2))
+        self.refmarker = pg.InfiniteLine(angle=90, movable=False,
+                                         pen=pg.mkPen(color="b", width=2, style=QtCore.Qt.DashLine))
+        plot.addItem(self.refmarker, ignoreBounds=True)
+        self.region.setRegion((min(x),max(x)))
+        self.region.sigRegionChangeFinished.connect(lambda region: self.UpdateEVRegion(region))
+    # ----------------------------------------------------------------------
+    def getDataClosestToRegion(self,region,plotitem,snapregion=False):
+        minidx, maxidx = region.getRegion()
+        data = plotitem.getData()[0]
+        index = lambda x: np.argmin(np.abs(data - x))
+        minidx = index(minidx)
+        maxidx = index(maxidx)
+        if minidx == maxidx:
+            minidx = 0
+            maxidx = np.argmax(data)
+        mindata = data[minidx]
+        maxdata = data[maxidx]
+        if snapregion:
+            region.blockSignals(True)
+            region.setRegion([mindata, maxdata])  # snap region to data points
+            region.blockSignals(False)
+        return minidx, maxidx, mindata, maxdata
+    
+    def UpdateEVRegion(self, region):
+        min_idx, max_idx,*_  = self.getDataClosestToRegion(region,self.plotitem, True)
+        y_vals = self.plotitem.yData[min_idx:max_idx + 1]
+        x_vals = self.plotitem.xData[min_idx:max_idx + 1]
+        self.spectrum_plotwidget.setRange(yRange=[np.min(y_vals), np.max(y_vals)], xRange=[np.min(x_vals), np.max(x_vals)], disableAutoRange=True, padding=0.05)
+        if min_idx not in self.idx_selected:
+            for idx in range(int(min_idx),np.min(self.idx_selected)):
+                self.ev_selected.append(self.ev_widget.item(idx))
+                self.ev_widget.item(idx).setBackground(QtGui.QColor('#beaed4'))
+        else:
+            for idx in range(np.min(self.idx_selected),int(min_idx)):
+                try:
+                    self.ev_selected.remove(self.ev_widget.item(idx))
+                except ValueError:
+                    pass
+                self.ev_widget.item(idx).setBackground(QtGui.QColor(0, 0, 0, 0))
+        if max_idx not in self.idx_selected:
+            for idx in range(np.max(self.idx_selected)+1,int(max_idx)+1):
+                try:
+                    self.ev_selected.append(self.ev_widget.item(idx))
+                except ValueError:
+                    pass
+                self.ev_widget.item(idx).setBackground(QtGui.QColor('#beaed4'))
+        else:
+            for idx in range(int(max_idx)+1,np.max(self.idx_selected)+1):
+                try:
+                    self.ev_selected.remove(self.ev_widget.item(idx))
+                except ValueError:
+                    pass
+                self.ev_widget.item(idx).setBackground(QtGui.QColor(0, 0, 0, 0))
+        self.RedrawNewPlot()
+    def OnSelectAll(self):
+        self.ev_widget.clear()
+        self.SetupListEV()
+        if self.com.stack_4d:
+            self.theta_widget.clear()
+            self.SetupListTheta()
+        self.region.setRegion((min(self.stack.ev), max(self.stack.ev)))
+        self.region.show()
+        self.RedrawNewPlot()
+    def OnClearAll(self):
+        #self.ev_widget.clear()
+        #self.SetupListEV()
+        self.region.hide()
+        for idx in self.idx_selected:
+            self.ev_widget.item(idx).setBackground(QtGui.QColor(0, 0, 0, 0))
+        self.ev_selected = []
+        self.idx_selected = []
+        if self.com.stack_4d:
+            for idx in self.thetaidx_selected:
+                self.theta_widget.item(idx).setBackground(QtGui.QColor(0, 0, 0, 0))
+            self.theta_selected = []
+            self.thetaidx_selected = []
+        self.RedrawNewPlot()
+    def SetupListTheta(self):
+        self.theta_selected = []
+        self.thetaidx_selected = []
+        for i,e in enumerate(self.stack.theta): # Fill QList with energies
+            #self.stk.shifts.append([1,0,(0.0,0.0)]) #checked [0,1]; pre, post, undefined state for map [-1,1,0],(xshift [float],yshift [float])
+            item = QtWidgets.QListWidgetItem(str(int(i)).zfill(3)+"     at     " + format(e, '.1f') + "°")
+            self.theta_widget.addItem(item)
+            self.theta_selected.append(item)
+            self.thetaidx_selected.append(i)
+            item.setBackground(QtGui.QColor('#beaed4'))
+            item.setForeground(QtGui.QColor(0, 0, 0, 128))
+    def SetupListEV(self):
+        self.ev_selected = []
+        self.idx_selected = []
+        for i,e in enumerate(self.stack.ev): # Fill QList with energies
+            #self.stk.shifts.append([1,0,(0.0,0.0)]) #checked [0,1]; pre, post, undefined state for map [-1,1,0],(xshift [float],yshift [float])
+            item = QtWidgets.QListWidgetItem(str(int(i)).zfill(3)+"     at     " + format(e, '.2f') + " eV")
+            self.ev_widget.addItem(item)
+            self.ev_selected.append(item)
+            self.idx_selected.append(i)
+            item.setBackground(QtGui.QColor('#beaed4'))
+            item.setForeground(QtGui.QColor(0, 0, 0, 128))
 
-        if self.com.i0_loaded == 1:
-            odtotal = self.stack.od3d.sum(axis=0)
+    def OnScrollTheta(self, value):
+        self.slider_theta.setValue(value)
+        self.ResetAllItems(self.theta_widget)
+        self.itheta = value
+        #self.stack.absdata = self.stack.stack4D[:,:,:,self.itheta].copy()
+        self.ShowImage()
+        self.theta_widget.setCurrentRow(self.itheta)
+        if self.com.stack_loaded == 1:
+            self.theta_widget.item(value).setForeground(QtGui.QColor(0, 0, 0, 255))
+        self.RedrawPlots()
+    def OnScrollEng(self, value):
+        self.slider_eng.setValue(value)
+        self.ResetAllItems(self.ev_widget)
+        self.iev = value
+        self.ShowImage()
+        try:
+            self.refmarker.setValue(self.stack.ev[self.iev])
+        except:
+            pass
+        self.ev_widget.setCurrentRow(self.iev)
+        if self.com.stack_loaded == 1:
+            self.ev_widget.item(value).setForeground(QtGui.QColor(0, 0, 0, 255))
+    def ShowImage(self):
+        if self.com.stack_4d == 1:
+            self.i_item.setImage(self.stack.stack4D[:, :, int(self.iev),int(self.itheta)])
+            self.groupBox.setTitle(str('Stack Browser | Image at {0:5.2f} eV and {1:5.1f}°').format(float(self.stack.ev[self.iev]),float(self.stack.theta[self.itheta]), ))
         else:
-            odtotal = self.stack.absdata.sum(axis=0)
+            if self.com.i0_loaded:
+                self.i_item.setImage(self.stack.od3d[:, :, int(self.iev)])
+            else:
+                self.i_item.setImage(self.stack.absdata[:, :, int(self.iev)])
+            self.groupBox.setTitle(str('Stack Browser | Image at {0:5.2f} eV').format(float(self.stack.ev[self.iev])))
 
-        odtotal = odtotal.sum(axis=0)/(self.stack.n_rows*self.stack.n_cols)
+    ## Setup a ROI for an alignment rectangle. By default the whole image area is used.
+    def SetupROI(self):
+        #self.stack.absdata = self.stack.absdata.copy()
+        self.box = pg.RectROI(self.i_item.boundingRect().topLeft(), self.i_item.boundingRect().bottomRight(),
+                              pen=(5, 8), handlePen=QtGui.QPen(QtGui.QColor(255, 0, 128, 255)), centered=False,
+                              sideScalers=False, removable=False, scaleSnap=True, translateSnap=True,
+                              maxBounds=self.i_item.boundingRect())
+        self.vb.addItem(self.box, ignoreBounds=False)
+        self.box.sigRegionChangeFinished.connect(self.RedrawPlots)
+        self.box.sigRegionChangeStarted.connect(self.OnBoxChanging)
+        self.button_rstroi.clicked.connect(self.OnResetROI)
+    ## The ROI is limited to the visible image area. OnMouseMoveOutside handles the behavior when
+    def OnResetROI(self):
+        self.box.setPos(0, 0, update=False, finish=False)
+        self.box.setSize(self.i_item.boundingRect().bottomRight() - self.box.pos(), update=True, snap=True, finish=True)
+        self.box.show()
+    def OnBoxChanging(self):
+        self.boxsize = self.box.size()
+        self.proxy = pg.SignalProxy(self.vb.scene().sigMouseMoved, rateLimit=30, slot=self.OnMouseMoveOutside)
+    def GetRegion(self):
+        try:
+            self.proxy.disconnect()
+        except AttributeError:
+            pass
+        left = int(self.box.pos().x())
+        right = left + int(self.box.size().x())
+        bottom = int(self.box.pos().y())
+        top = bottom + int(self.box.size().y())
+        return (left,right,top,bottom)
+
+    def GenerateSpectrum(self, evselection):
+        left,right,top,bottom = self.GetRegion()
+        if self.com.i0_loaded == 1:
+            if self.com.stack_4d == 1:
+                total = self.stack.od4d[left:right, bottom:top, :, int(self.itheta)].copy()
+            else:
+                total = self.stack.od3d[left:right, bottom:top, :].copy()
 
-        fig = self.specfig
-        fig.clf()
-        fig.add_axes((0.15,0.15,0.75,0.75))
-        self.axes = fig.gca()
-
-
-        specplot = self.axes.plot(self.stack.ev,odtotal)
-
-        self.axes.set_xlabel('Photon Energy [eV]')
-        self.axes.set_ylabel('Optical Density')
-
-        if self.evlimited == 1:
-            self.patch = self.axes.axvspan(self.stack.ev[self.limitevmin], self.stack.ev[self.limitevmax], facecolor='g', alpha=0.5)
-
-
-        self.SpectrumPanel.draw()
-
-        self.textctrl.setText('Min energy {0:5.2f} eV\n'.format(float(self.stack.ev[self.limitevmin]))
-                              + 'Max energy {0:5.2f} eV'.format(float(self.stack.ev[self.limitevmax])))
-
-#----------------------------------------------------------------------
-    def OnSelection1(self, evt):
-
-
-        x1 = evt.xdata
-
-        self.button_pressed = True
-        self.conn = self.SpectrumPanel.mpl_connect('motion_notify_event', self.OnSelectionMotion)
-
-        if x1 == None:
-            return
-
-
-        self.limitevmin = np.abs(self.stack.ev-x1).argmin()
-
-
-
-#----------------------------------------------------------------------
-    def OnSelection2(self, evt):
-
-        x2 = evt.xdata
-
-
-        self.button_pressed = False
-        self.SpectrumPanel.mpl_disconnect(self.conn)
-
-        if x2 == None:
-            return
-
-
-        #self.limitevmin = np.abs(self.stack.ev-x1).argmin()
-        self.limitevmax = np.abs(self.stack.ev-x2).argmin()
-
-        self.evlimited = 1
-
-        self.draw_limitev_plot()
-
-
-#----------------------------------------------------------------------
-    def OnSelectionMotion(self, event):
-
-        x2 = event.xdata
-
-        if x2 == None:
-            return
-
-        self.limitevmax = np.abs(self.stack.ev-x2).argmin()
-
-        fig = self.specfig
-
-        axes = fig.gca()
-
-        if self.patch != None:
-            self.patch.remove()
-        self.patch = self.axes.axvspan(self.stack.ev[self.limitevmin], self.stack.ev[self.limitevmax], facecolor='w', alpha=0.5)
-
-        self.SpectrumPanel.draw()
-
-
-#----------------------------------------------------------------------
+        else:
+            if self.com.stack_4d == 1:
+                t = [self.stack.theta[i] for i in self.thetaidx_selected]
+                self.label_theta_range.setText(
+                    "Theta range: [ " + str(min(t, default=0)) + "° .. " + str(
+                        max(t, default=0)) + "° ], # values: " + str(
+                        len(t)))
+                total = self.stack.stack4D[left:right, bottom:top, :, int(self.itheta)].copy()
+            else:
+                total = self.stack.absdata[left:right, bottom:top, :].copy()
+        total = total.sum(axis=(0,1)) / (int(self.box.size().x()) * int(self.box.size().y()))
+        x = [self.stack.ev[i] for i in evselection]
+        y = [total[i] for i in evselection]
+        self.label_spatial_range.setText("Stack size: [ "+str(int(self.box.size().x()))+" x "+str(int(self.box.size().y()))+" ] px²")
+        self.label_ev_range.setText(
+            "Energy range: [ " + str(min(x, default=0)) + " .. " + str(max(x, default=0)) + " ] eV, # values: "+ str(len(x)))
+        return (x, y)
+
+    def ResetAllItems(self,widget):
+        for i in range(widget.count()):
+            widget.item(i).setForeground(QtGui.QColor(0, 0, 0, 128))
+
+    def OnMouseMoveOutside(self, ev):
+        mousepos = self.vb.mapSceneToView(ev[0])
+        if not self.vb.itemBoundingRect(self.i_item).contains(mousepos):
+            maxrect = self.i_item.boundingRect().bottomRight()
+            # if bounds exceeded
+            out_x = max((mousepos-maxrect).x(),0)
+            out_y = max((mousepos-maxrect).y(), 0)
+            if self.box.size() != self.boxsize: # prevents taking action when the box is just dragged and not resized
+                if out_x and out_y:
+                    self.box.setSize(self.i_item.boundingRect().bottomRight()-self.box.pos(), update=True, snap=True, finish=False)
+                elif out_x:
+                    self.box.setSize([self.i_item.boundingRect().right()-self.box.pos().x(),mousepos.y()-self.box.pos().y()], update=True, snap=True, finish=False)
+                elif out_y:
+                    self.box.setSize([mousepos.x()-self.box.pos().x(),self.i_item.boundingRect().bottom()-self.box.pos().y()], update=True, snap=True, finish=False)
+    # ----------------------------------------------------------------------
+    def OnCancel(self, evt):
+        self.close()
+    # ----------------------------------------------------------------------
     def OnAccept(self, evt):
-        #change the energy range to limitevmin-limitev-max
-        #print self.stack.n_ev, self.stack.ev.shape
-        self.stack.n_ev = self.limitevmax+1-self.limitevmin
-        self.stack.ev = self.stack.ev[self.limitevmin:self.limitevmax+1]
-        self.stack.data_dwell = self.stack.data_dwell[self.limitevmin:self.limitevmax+1]
-
-        #print self.stack.n_ev, self.stack.ev.shape
+        if self.cb_croptoroi.isChecked():
+            left, right, top, bottom = self.GetRegion()
+        else:
+            left, right, top, bottom = (None,None,None,None)
 
+        if self.cb_remove_evs.isChecked():
+            selection = self.idx_selected
+            if len(selection) == 0:
+                QtWidgets.QMessageBox.warning(self, 'Error', 'Please select at least one energy value!')
+                return
+            self.stack.n_ev = np.array(len(selection))
+            self.stack.ev = self.stack.ev[selection]
+            self.stack.data_dwell = self.stack.data_dwell[selection]
+        else:
+            selection = list(range(self.stack.n_ev))
 
-        self.stack.absdata = self.stack.absdata[:,:,self.limitevmin:self.limitevmax+1]
 
-        if self.com.i0_loaded == 1:
-            self.stack.od3d = self.stack.od3d[:,:,self.limitevmin:self.limitevmax+1]
+        self.stack.absdata = self.stack.absdata[left:right,bottom:top,selection]
+        self.stack.n_cols = self.stack.absdata.shape[0]
+        self.stack.n_rows = self.stack.absdata.shape[1]
+        self.parent.page1.ix = int(self.stack.n_cols/2)
+        self.parent.page1.iy = int(self.stack.n_rows/2)
 
-            self.stack.od = self.stack.od3d.copy()
+        if self.com.stack_4d:
+            if self.cb_remove_theta.isChecked():
+                thetas = self.thetaidx_selected
+                if len(thetas) == 0:
+                    QtWidgets.QMessageBox.warning(self, 'Error', 'Please select at least one theta value!')
+                    return
+                self.stack.n_theta = len(thetas)
+                self.stack.theta = self.stack.theta[thetas]
 
-            self.stack.od = np.reshape(self.stack.od, (self.stack.n_rows*self.stack.n_cols, self.stack.n_ev), order='F')
+            else:
+                thetas = list(range(self.stack.n_theta))
+            self.stack.stack4D = self.stack.stack4D[left:right, bottom:top, selection, :]
+            self.stack.stack4D = self.stack.stack4D[:,:, :, thetas]
+        if self.com.i0_loaded:
+            if self.com.stack_4d:
+                self.stack.od4D = self.stack.od4D[left:right,bottom:top,selection, thetas]
+            else:
+                self.stack.od3d =  self.stack.od3d[left:right,bottom:top,selection]
+                self.stack.od = self.stack.od3d.copy()
+                self.stack.od = np.reshape(self.stack.od, (self.stack.n_rows * self.stack.n_cols, self.stack.n_ev),
+                                       order='F')
 
         self.stack.fill_h5_struct_from_stk()
         if self.com.i0_loaded == 1:
             self.stack.fill_h5_struct_normalization()
 
-
-        if self.com.stack_4d == 1:
-            self.stack.stack4D = self.stack.stack4D[:,:,self.limitevmin:self.limitevmax+1,:]
-            if self.com.i0_loaded == 1:
-                self.stack.od4D = self.stack.od4D[:,:,self.limitevmin:self.limitevmax+1,:]
-
-
-        #Fix the slider on Page 1!
-        self.parent.page1.slider_eng.setRange(0,self.stack.n_ev-1)
-        self.parent.page1.iev = int(self.stack.n_ev/2)
-        self.parent.page1.slider_eng.setValue(self.parent.page1.iev)
-
-        self.parent.page0.slider_eng.setRange(0,self.stack.n_ev-1)
-        self.parent.page0.iev = int(self.stack.n_ev/2)
-        self.parent.page0.slider_eng.setValue(self.parent.page1.iev)
-
-        self.parent.page1.loadSpectrum(self.parent.page1.ix, self.parent.page1.iy)
-        self.parent.page1.loadImage()
-
-        self.close()
-
-
-#----------------------------------------------------------------------
-class CliptoSubregion(QtWidgets.QDialog):
-
-    def __init__(self, parent,  common, stack):
-        QtWidgets.QWidget.__init__(self, parent)
-
-        self.parent = parent
-
-        self.stack = stack
-        self.com = common
-
-        self.resize(500, 470)
-        self.setWindowTitle('Clip to Subregion')
-
-        pal = QtGui.QPalette()
-        self.setAutoFillBackground(True)
-        pal.setColor(QtGui.QPalette.Window,QtGui.QColor('white'))
-        self.setPalette(pal)
-
-        self.new_x1 = int(self.stack.n_cols*0.10)
-        self.new_x2 = int(self.stack.n_cols*0.90)
-        self.new_y2 = self.stack.n_rows-1-int(self.stack.n_rows*0.10)
-        self.new_y1 = self.stack.n_rows-1-int(self.stack.n_rows*0.90)
-
-        self.new_ncols = self.new_x2 - self.new_x1
-        self.new_nrows = self.new_y2 - self.new_y1
-
-        vbox = QtWidgets.QVBoxLayout()
-
-        sizer = QtWidgets.QGroupBox('Select new stack size')
-        vbox1 = QtWidgets.QVBoxLayout()
-        self.textctrl1 = QtWidgets.QLabel(self)
-        self.textctrl1.setText('Original stack size:\t{0:5d}   x{1:5d} '.format(self.stack.n_cols, self.stack.n_rows))
-        vbox1.addWidget(self.textctrl1)
-
-        self.textctrl2 = QtWidgets.QLabel(self)
-        self.textctrl2.setText('New stack size:\t{0:5d}   x{1:5d} '.format(self.new_ncols, self.new_nrows))
-        vbox1.addWidget(self.textctrl2)
-
-        self.textctrl3 = QtWidgets.QLabel(self)
-        self.textctrl3.setText('Clip coordinates [[x1, x2], [y1, y2]] : [[{0:5d},{1:5d}], [{2:5d},{3:5d}]]'.format(
-                                    self.new_x1, self.new_x2, self.new_y1, self.new_y2))
-        vbox1.addWidget(self.textctrl3)
-
-        self.absimgfig = Figure((PlotH,PlotH))
-        self.AbsImagePanel = FigureCanvas(self.absimgfig)
-        self.AbsImagePanel.setParent(self)
-        self.AbsImagePanel.mpl_connect('button_press_event', self.OnSelection1)
-        self.AbsImagePanel.mpl_connect('button_release_event', self.OnSelection2)
-
-        vbox1.addWidget(self.AbsImagePanel)
-        sizer.setLayout(vbox1)
-        vbox.addWidget(sizer)
-
-        hbox = QtWidgets.QHBoxLayout()
-
-        button_ok = QtWidgets.QPushButton('Accept')
-        button_ok.clicked.connect(self.OnAccept)
-        hbox.addWidget(button_ok)
-
-        button_cancel = QtWidgets.QPushButton('Cancel')
-        button_cancel.clicked.connect(self.close)
-        hbox.addWidget(button_cancel)
-
-        vbox.addLayout(hbox)
-
-        self.setLayout(vbox)
-
-        self.draw_image()
-
-
-#----------------------------------------------------------------------
-    def draw_image(self):
-
-        image = self.stack.absdata[:,:,int(self.stack.n_ev/2)].copy()
-
-        fig = self.absimgfig
-        fig.clf()
-        fig.add_axes((0.02,0.02,0.96,0.96))
-
-        axes = fig.gca()
-        fig.patch.set_alpha(1.0)
-
-        im = axes.imshow(np.rot90(image), cmap=matplotlib.cm.get_cmap("gray"))
-
-        # Draw the rectangle
-        line1=matplotlib.lines.Line2D([self.new_x1,self.new_x2], [self.new_y1,self.new_y1] ,color="red")
-        line1.set_clip_on(False)
-        self.l1 = axes.add_line(line1)
-
-        line2=matplotlib.lines.Line2D([self.new_x1,self.new_x2], [self.new_y2,self.new_y2] ,color="red")
-        line2.set_clip_on(False)
-        self.l2 = axes.add_line(line2)
-
-        line3=matplotlib.lines.Line2D([self.new_x1,self.new_x1], [self.new_y1,self.new_y2] ,color="red")
-        line3.set_clip_on(False)
-        self.l3 = axes.add_line(line3)
-
-        line4=matplotlib.lines.Line2D([self.new_x2,self.new_x2], [self.new_y1,self.new_y2] ,color="red")
-        line4.set_clip_on(False)
-        self.l4 = axes.add_line(line4)
-
-        axes.axis("off")
-        self.AbsImagePanel.draw()
-
-
-#----------------------------------------------------------------------
-    def OnSelection1(self, evt):
-
-        x1, y1 = evt.xdata, evt.ydata
-
-        self.button_pressed = True
-        self.conn = self.AbsImagePanel.mpl_connect('motion_notify_event', self.OnSelectionMotion)
-
-        if (x1 == None) or (y1 == None):
-            return
-
-        self.new_y1 = int(y1)
-        self.new_x1 = int(x1)
-
-        self.new_ncols = self.new_x2 - self.new_x1 + 1
-        self.new_nrows = self.new_y1 - self.new_y2 + 1
-
-#         self.textctrl2.SetValue('New stack size:\t{0:5d}   x{1:5d} '.format(self.new_ncols, self.new_nrows))
-#         self.textctrl3.SetValue('Clip coordinates [[x1, x2], [y1, y2]]:[[{0:5d},{1:5d}], [{2:5d},{3:5d}]]'.format(
-#                                     self.new_x1, self.new_x2, self.new_y1, self.new_y2))
-#
-#         self.draw_image()
-
-#----------------------------------------------------------------------
-    def OnSelection2(self, evt):
-
-        x2, y2 = evt.xdata, evt.ydata
-
-        self.button_pressed = False
-        self.AbsImagePanel.mpl_disconnect(self.conn)
-
-        if (x2 == None) or (y2 == None):
-            return
-
-        self.new_y2 = int(y2)
-        self.new_x2 = int(x2)
-
-        if self.new_x1 > self.new_x2:
-            temp = self.new_x1
-            self.new_x1 = self.new_x2
-            self.new_x2 = temp
-
-        if self.new_y1 > self.new_y2:
-            temp = self.new_y1
-            self.new_y1 = self.new_y2
-            self.new_y2 = temp
-
-        self.new_ncols = self.new_x2 - self.new_x1 + 1
-        self.new_nrows = self.new_y2 - self.new_y1 + 1
-
-        self.textctrl2.setText('New stack size:\t{0:5d}   x{1:5d} '.format(self.new_ncols, self.new_nrows))
-        self.textctrl3.setText('Clip coordinates [[x1, x2], [y1, y2]]:[[{0:5d},{1:5d}], [{2:5d},{3:5d}]]'.format(
-                                    self.new_x1, self.new_x2, self.new_y1, self.new_y2))
-
-        self.draw_image()
-
-#----------------------------------------------------------------------
-    def OnSelectionMotion(self, event):
-
-        x2, y2 = event.xdata, event.ydata
-
-        if x2 == None:
-            return
-
-        self.new_y2 = int(y2)
-        self.new_x2 = int(x2)
-
-        fig = self.absimgfig
-
-        axes = fig.gca()
-
-        self.l1.remove()
-        self.l2.remove()
-        self.l3.remove()
-        self.l4.remove()
-
-        line1=matplotlib.lines.Line2D([self.new_x1,self.new_x2], [self.new_y1,self.new_y1] ,color="red")
-        line1.set_clip_on(False)
-        self.l1 = axes.add_line(line1)
-
-        line2=matplotlib.lines.Line2D([self.new_x1,self.new_x2], [self.new_y2,self.new_y2] ,color="red")
-        line2.set_clip_on(False)
-        self.l2 = axes.add_line(line2)
-
-        line3=matplotlib.lines.Line2D([self.new_x1,self.new_x1], [self.new_y1,self.new_y2] ,color="red")
-        line3.set_clip_on(False)
-        self.l3 = axes.add_line(line3)
-
-        line4=matplotlib.lines.Line2D([self.new_x2,self.new_x2], [self.new_y1,self.new_y2] ,color="red")
-        line4.set_clip_on(False)
-        self.l4 = axes.add_line(line4)
-
-
-        self.AbsImagePanel.draw()
-
-
-#----------------------------------------------------------------------
-    def OnAccept(self, evt):
-
-        #change the stack size to [x1,x2], [y1,y2]
-        self.stack.absdata = self.stack.absdata[ self.new_x1:self.new_x2+1, self.stack.n_rows-self.new_y2-1:self.stack.n_rows-self.new_y1, :]
-        if self.com.i0_loaded == 1:
-            self.stack.od3d = self.stack.od3d[ self.new_x1:self.new_x2+1, self.stack.n_rows-self.new_y2-1:self.stack.n_rows-self.new_y1, :]
-            self.stack.od = self.stack.od3d.copy()
-
-        self.stack.n_cols = self.stack.absdata.shape[0]
-        self.stack.n_rows = self.stack.absdata.shape[1]
-
-        if self.com.i0_loaded == 1:
-            self.stack.od = np.reshape(self.stack.od, (self.stack.n_rows * self.stack.n_cols, self.stack.n_ev), order='F')
-
-        #Fix the slider on Page 1!
-        self.parent.page1.ix = int(self.stack.n_cols/2)
-        self.parent.page1.iy = int(self.stack.n_rows/2)
-
-        self.stack.fill_h5_struct_from_stk()
-        self.parent.page1.loadSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        # Fix the slider on Page 1!
+        if self.com.stack_4d:
+            self.parent.page1.slider_theta.setRange(0, self.stack.n_theta - 1)
+            self.parent.page1.itheta = 0
+            self.parent.page1.slider_theta.blockSignals(True)
+            self.parent.page1.slider_theta.setValue(int(self.parent.page1.itheta))
+            self.parent.page1.slider_theta.blockSignals(False)
+
+            self.parent.page0.slider_theta.setRange(0, self.stack.n_theta - 1)
+            self.parent.page0.itheta = 0
+            self.parent.page0.slider_theta.blockSignals(True)
+            self.parent.page0.slider_theta.setValue(int(self.parent.page1.itheta))
+            self.parent.page0.slider_theta.blockSignals(False)
+
+        self.parent.page1.slider_eng.setRange(0, self.stack.n_ev - 1)
+        self.parent.page1.iev = 0
+        self.parent.page1.slider_eng.setValue(int(self.parent.page1.iev))
+
+        self.parent.page0.slider_eng.setRange(0, self.stack.n_ev - 1)
+        self.parent.page0.iev = 0
+        self.parent.page0.slider_eng.setValue(int(self.parent.page1.iev))
+
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
         self.parent.page1.loadImage()
-        self.parent.page0.ShowImage()
+        self.parent.page0.Clear()
+        self.parent.page0.LoadEntries()
 
         if showmaptab:
             self.parent.page9.Clear()
@@ -11159,9 +11235,24 @@ class CliptoSubregion(QtWidgets.QDialog):
 
         self.close()
 
+class ImageRegistrationDialog(QtWidgets.QDialog):
 
-#----------------------------------------------------------------------
-class ImageRegistration(QtWidgets.QDialog):
+    def __init__(self, parent, common):
+        QtWidgets.QWidget.__init__(self, parent)
+        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'dialogalign.ui'), self)
+        self.parent = parent
+        self.com = common
+        # Currently disabled for Tomo data
+        # if self.com.stack_4d == 1:
+        #     self.bt_align2.setEnabled(True)
+        # else:
+        #     self.bt_align2.setEnabled(True)
+        self.bt_align.clicked.connect(self.parent.page1.OnAlignImgs)
+        self.bt_align2.clicked.connect(self.parent.page1.OnAlignImgs2)
+        self.bt_align.clicked.connect(self.done)
+        self.bt_align2.clicked.connect(self.done)
+#----------------------------------------------------------------------
+class ImageRegistrationManual(QtWidgets.QDialog):
 
     def __init__(self, parent,  common, stack):
         QtWidgets.QWidget.__init__(self, parent)
@@ -11914,7 +12005,7 @@ class ImageRegistration(QtWidgets.QDialog):
         self.parent.page1.iev = self.stack.n_ev/2
         self.parent.page1.slider_eng.setValue(self.parent.page1.iev)
 
-        self.parent.page1.loadSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
         self.parent.page1.loadImage()
 
         self.ShowImage()
@@ -12365,7 +12456,7 @@ class ImageRegistration(QtWidgets.QDialog):
         self.parent.page1.ix = int(self.stack.n_cols/2)
         self.parent.page1.iy = int(self.stack.n_rows/2)
 
-        self.parent.page1.loadSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
         self.parent.page1.loadImage()
         #self.parent.page9.loadImage()
 
@@ -12736,20 +12827,1146 @@ class ImageRegistration(QtWidgets.QDialog):
             elif self.man_align == 2:
                 self.button_applyman.setEnabled(True)
 
+class GeneralPurposeSignals(QtCore.QObject):
+    finished = pyqtSignal()
+    ithetaprogress = pyqtSignal(int)
+# ----------------------------------------------------------------------
+class GeneralPurposeProcessor(QtCore.QRunnable):
+    def __init__(self, parent, queue):
+        super(GeneralPurposeProcessor, self).__init__()
+        self.signals = GeneralPurposeSignals()
+        self.funcdict = {"ShiftImg": self.ShiftImg, "AlignReferenced": self.AlignReferenced}
+        self.parent = parent
+        self.queue = queue
+        self.current_itheta = 0
+
+    @pyqtSlot()
+    def run(self):
+        #print('worker', threading.get_ident())
+        while True:
+            #print(self.parent.pool.pool.activeThreadCount())
+            #print(QtCore.QThreadPool.activeThreadCount())
+            try:
+                workerfunc, *args = self.queue.get(False)
+                self.funcdict[workerfunc](*args[0])
+                #print("busy with task {}".format(workerfunc))
+            except Empty: # if queue empty
+                break
 
+    def AlignReferenced(self, data, itheta):
+        if self.current_itheta != itheta:
+            self.current_itheta = itheta
+            self.signals.ithetaprogress.emit(itheta)
+        drift_x = [0,0]
+        drift_y = [0,0]
+        drift, error, _ = phase_cross_correlation(self.Gauss(self.parent.stack.absdata_cropped[:, :, data[0],itheta]),
+                                                  self.Gauss(self.parent.stack.absdata_cropped[:, :, data[1],itheta]),upsample_factor=20) ## 20 means 0.05 px precision
+        self.parent.stack.shiftsdict[itheta]["errors"][data[0]] = round(error,4)
+        if data[0] - data[1] > 0:
+            drift_x[1] = round(drift[0],2)
+            drift_y[1] = round(drift[1],2)
+            self.parent.stack.shiftsdict[itheta]["xdots"][data[0]]= drift_x[1]
+            self.parent.stack.shiftsdict[itheta]["ydots"][data[0]]= drift_y[1]
+        else:
+            drift_x[0] = round(drift[0],2)
+            drift_y[0] = round(drift[1],2)
+            self.parent.stack.shiftsdict[itheta]["xdots"][data[0]]= drift_x[0]
+            self.parent.stack.shiftsdict[itheta]["ydots"][data[0]]= drift_y[0]
+
+    def ShiftImg(self, row,x,y,itheta):
+        shifted = ndimage.fourier_shift(np.fft.fft2(self.parent.stack.absdata4d[:, :, row,itheta]), [float(-x),float(-y)])
+        shifted = np.fft.ifft2(shifted)
+        self.parent.stack.absdata4d_shifted[:, :, row, itheta] = shifted.real
+        return
 
+    def Gauss(self, im):
+        gaussed = ndimage.gaussian_filter(im, self.parent.spinBoxGauss.value())
+        return gaussed
 
-#----------------------------------------------------------------------
-class SpectralROI(QtWidgets.QDialog):
+class TaskDispatcher(QtCore.QObject):
+    def __init__(self,parent):
+        print("0 - dispatcher called, pool initiated")
+        super(TaskDispatcher, self).__init__()
+        try:
+            self.worker.signals.ithetaprogress.disconnect()
+            self.worker.signals.finished.disconnect()
+        except:
+            pass
+        self.pool = QtCore.QThreadPool.globalInstance()
+        try:
+            cpus = len(os.sched_getaffinity(0)) # number of cpu threads. not supported on some platforms.
+        except:
+            cpus = os.cpu_count()
+        self.pool.setMaxThreadCount(cpus)
+        self.queue = SimpleQueue()
+        self.parent = parent
 
-    def __init__(self, parent,  common, stack):
+    @pyqtSlot()
+    def run(self):
+        #print(self.queue.qsize())
+        #print('pool', threading.get_ident())
+        # if self.parent.com.stack_4d == 0:
+        qsize = int(self.queue.qsize())
+        maxthreads = self.pool.maxThreadCount()
+        preferred_thread_number = min(maxthreads, qsize)
+        print("1 - starting threads",preferred_thread_number, "threads needed, number of tasks:",qsize)
+        while int(self.queue.qsize()) and self.pool.activeThreadCount() < preferred_thread_number: #start as many threads as needed.
+            #print("active threads"+str(self.pool.activeThreadCount())+" qsize "+str(int(self.queue.qsize())))
+            worker = GeneralPurposeProcessor(self.parent,self.queue)
+            worker.signals.ithetaprogress.connect(self.parent.IThetaProgress)
+            self.pool.start(worker)
+            time.sleep(0.02) # artifical delay to start threads with a little time separation. Otherwise ShiftImgs freezes in Win10 and MacOS for small stacks!
+        self.pool.waitForDone()
+        print("2 - all threads dead")
+        worker.signals.finished.connect(self.parent.ThreadPoolComplete)
+        worker.signals.finished.emit()
+    #add a task to the queue
+    def enqueuetask(self, func, *args, **kargs):
+        self.queue.put((func, args, kargs))
+
+class ImageRegistrationFFT(QtWidgets.QDialog, QtWidgets.QGraphicsScene):
+    def __init__(self, parent, common, stack):
         QtWidgets.QWidget.__init__(self, parent)
-
+        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'showalign2.ui'), self)
         self.parent = parent
-
         self.stack = stack
         self.com = common
-
+        self.iev = 0
+        self.itheta = 0
+        if self.com.stack_loaded == 1:
+            if self.com.stack_4d:
+                self.stack.absdata4d = self.stack.stack4D.copy()
+                #self.button_alignbatch.setVisible(True)
+                self.button_align.setText("Align Batch")
+                self.thetathread = QtCore.QThread()
+            else:
+                self.stack.absdata4d = np.expand_dims(self.stack.absdata.copy(), axis=3)
+                #self.button_alignbatch.setVisible(False)
+                self.button_align.setText("Align")
+            self.stack.absdata_cropped = self.stack.absdata4d.copy() # This image stack is used by the alignment/shift routine and cropped to the ROI rectangle
+            self.stack.absdata4d_shifted = self.stack.absdata4d.copy() # This is the full-sized output of the alignment/shift routine
+            self.stack.absdata4d_shifted_cropped = self.stack.absdata4d.copy() # This is the output cropped to the common region
+        #self.stack.absdata_unaligned = self.stack.absdata_shifted_cropped
+        self.poolthread = QtCore.QThread()
+        self.aligned = False
+        self.SetupUI()
+
+    def SetupUI(self):
+        self.button_ok.setEnabled(False)
+        self.slider_theta.setVisible(False)
+        self.setWindowTitle('Align Stack v2')
+        self.pglayout = pg.GraphicsLayout(border=None)
+        self.canvas.setBackground("w") # canvas is a pg.GraphicsView widget
+        self.canvas.setCentralWidget(self.pglayout)
+        self.vb = self.pglayout.addViewBox()
+        self.vb.setAspectLocked()
+        self.i_item = pg.ImageItem(border="k",parent= self)
+
+        self.vb.setMouseEnabled(x=False, y=False)
+        self.vb.addItem(self.i_item, ignoreBounds=False)
+
+        self.DriftsWidget.setBackground("w")
+
+        self.py = self.DriftsWidget.addPlot(row=0, col=0, rowspan=1, colspan=1)
+        self.py.setMouseEnabled(x=False, y=True)
+        #self.i_item = pg.ImageItem(border="k")
+        #self.py.setAspectLocked(lock=True, ratio=1)
+        self.py.showAxis("top", show=True)
+        self.py.showAxis("bottom", show=True)
+        self.py.showAxis("left", show=True)
+        self.py.showAxis("right", show=True)
+        ay1 = self.py.getAxis("left")
+        by1 = self.py.getAxis("right")
+        ax1 = self.py.getAxis("bottom")
+        bx1 = self.py.getAxis("top")
+        ay1.setLabel(text="y-drift", units="px")
+        ay1.enableAutoSIPrefix(enable=True)
+        ay1.setWidth(w=60)
+        ax1.setLabel(text="Photon Energy",units="eV")
+        ax1.enableAutoSIPrefix(enable=True)
+        ay1.setStyle(tickLength=8)
+        ax1.setStyle(tickLength=0)
+        #ax1.setHeight(h=46.2)
+        ax1.setStyle(tickLength=8)
+        by1.setStyle(showValues=False, tickLength=0)
+        bx1.setStyle(showValues=False, tickLength=0)
+
+        self.px = self.DriftsWidget.addPlot(row=1, col=0, rowspan=1, colspan=1)
+        self.px.setXLink(self.py)
+        self.px.setMouseEnabled(x=False, y=True)
+        #self.i_item = pg.ImageItem(border="k")
+        #self.px.setAspectLocked(lock=True, ratio=1)
+        self.px.showAxis("top", show=True)
+        self.px.showAxis("bottom", show=True)
+        self.px.showAxis("left", show=True)
+        self.px.showAxis("right", show=True)
+        ay2 = self.px.getAxis("left")
+        by2 = self.px.getAxis("right")
+        ax2 = self.px.getAxis("bottom")
+        bx2 = self.px.getAxis("top")
+        ay2.setLabel(text="x-drift",units="px")
+        ay2.enableAutoSIPrefix(enable=True)
+        ay2.setWidth(w=60)
+        ax2.setLabel(text="Photon Energy",units="eV")
+        ax2.enableAutoSIPrefix(enable=True)
+        ay2.setStyle(tickLength=8)
+        ax2.setStyle(tickLength=8)
+        by2.setStyle(showValues=False,tickLength=0)
+        bx2.setStyle(showValues=False,tickLength=0)
+
+        self.button_ok.clicked.connect(self.OnAccept)
+        self.button_cancel.clicked.connect(self.OnCancel)
+
+        if self.com.stack_loaded == 1:
+            if self.com.stack_4d:
+                self.slider_theta.setVisible(True)
+                self.slider_theta.setRange(0, self.stack.n_theta - 1)
+                self.slider_theta.valueChanged[int].connect(self.OnScrollTheta)
+            #self.maskedvals = [True] * int(self.stack.n_ev)
+            self.spinBoxError.setEnabled(False)
+            self.slider_eng.sliderPressed.connect(self.ShowImage)
+            self.slider_eng.sliderReleased.connect(self.ShowImage)
+            self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
+            self.slider_eng.setRange(0, self.stack.n_ev - 1)
+            self.refmarkerx = pg.InfiniteLine(angle=90, movable=False, pen=pg.mkPen(color="b", width=2, style=QtCore.Qt.DashLine))
+            self.refmarkery = pg.InfiniteLine(angle=90, movable=False, pen=pg.mkPen(color="b", width=2, style=QtCore.Qt.DashLine))
+            self.px.addItem(self.refmarkerx, ignoreBounds=True)
+            self.py.addItem(self.refmarkery, ignoreBounds=True)
+
+            self.fit_x = pg.PlotCurveItem(pen=pg.mkPen(color="c", width=2))
+            self.fit_y = pg.PlotCurveItem(pen=pg.mkPen(color="c", width=2))
+            self.fit_x.setZValue(200)
+            self.fit_y.setZValue(200)
+            self.px.addItem(self.fit_x, ignoreBounds=True)
+            self.py.addItem(self.fit_y, ignoreBounds=True)
+
+            self.OnScrollEng(0)
+            self.SetupROI()
+            self.button_align.clicked.connect(self.ComposeAlignQueue)
+            self.xregion = pg.LinearRegionItem(brush=[255, 0, 0, 45], bounds=[self.stack.ev[0], self.stack.ev[-1]])
+            self.yregion = pg.LinearRegionItem(brush=[255, 0, 0, 45], bounds=[self.stack.ev[0], self.stack.ev[-1]])
+            self.xregion.setRegion([self.stack.ev[0], self.stack.ev[-1]])
+            self.yregion.setRegion([self.stack.ev[0], self.stack.ev[-1]])
+            self.yregion.setZValue(100)
+            self.xregion.setZValue(100)
+            self.px.addItem(self.xregion, ignoreBounds=False)
+            self.py.addItem(self.yregion, ignoreBounds=False)
+            self.xregion.sigRegionChangeFinished.connect(lambda region: self.OnLinRegion(region))
+            self.yregion.sigRegionChangeFinished.connect(lambda region: self.OnLinRegion(region))
+
+            self.xscatter = pg.ScatterPlotItem(pxMode=False)
+            self.yscatter = pg.ScatterPlotItem(pxMode=False)
+
+            self.InitShiftsDict()
+
+            self.px.addItem(self.xscatter)
+            self.py.addItem(self.yscatter)
+            self.MakeNewScatterPlots()
+            #self.shifts = self.stack.shifts.copy()
+            self.xscatter.sigClicked.connect(self.OnPointClicked)
+            self.yscatter.sigClicked.connect(self.OnPointClicked)
+            self.cb_autocrop.toggled.connect(self.OnAutoCrop)
+    def InitShiftsDict(self):
+        outer_keys = range(max(self.stack.n_theta,1))
+        inner_keys = ["xdots", "ydots", "xshifts", "yshifts", "errors", "errormaskedx","errormaskedy","manualmaskedx","manualmaskedy"]
+        self.stack.shiftsdict = {intkey : {key: [False] * int(self.stack.n_ev) for key in inner_keys} for intkey in outer_keys}
+        single_keys = ["filter", "method", "autoquality", "extrapolation", "threshold", "regionlimitx", "regionlimity"]
+        for intkey in outer_keys:
+            self.stack.shiftsdict[intkey].update({key: False for key in single_keys})
+    def CreateScatterDots(self,shifts,mask):
+        scatterdots = [{'pos': tup[0:2], 'size': 10,
+                           #'pen': {'color': 'w', 'width': 2},
+                           'brush': QtGui.QColor('red')} if tup[2] else {'pos': tup[0:2], 'size': 10,
+                           #'pen': {'color': 'w', 'width': 2},
+                           'brush': QtGui.QColor('blue')} for tup in list(zip(self.stack.ev, shifts, mask))]
+        return scatterdots
+
+    def OnPointClicked(self, obj, points): # Manually add/remove points to/from fit if in selected region
+        selectscatter = {self.xscatter: ["errormaskedx","manualmaskedx",self.xregion], self.yscatter: ["errormaskedy","manualmaskedy",self.yregion]}
+        idx = points[0].index()
+        mask1 = self.stack.shiftsdict[self.itheta][selectscatter[obj][1]]
+        mask2 = self.stack.shiftsdict[self.itheta][selectscatter[obj][0]]
+        min_idx, max_idx, *_ = self.getDataClosestToRegion(selectscatter[obj][2], obj)
+        if min_idx <= idx <= max_idx :
+            mask1[idx] = not np.logical_or(mask1[idx],mask2[idx])
+            mask2[idx] = mask1[idx]
+            self.ColorizeScatterDots()
+            self.OnScrollEng(points[0].index())
+            if self.aligned:
+                self.ComposeShiftQueue()
+    def OnAligned(self):
+        self.aligned = True
+        print("aligned")
+        self.cb_autoerror.stateChanged.disconnect()
+        self.cb_extrapolate.stateChanged.disconnect()
+        self.spinBoxFiltersize.valueChanged.disconnect()
+        self.spinBoxError.valueChanged.disconnect()
+        self.comboBox_approx.currentIndexChanged.disconnect()
+        self.MakeNewScatterPlots()
+        self.OnLinRegion(self.xregion, update=False)
+        self.OnLinRegion(self.yregion, update=False)
+        self.ComposeShiftQueue(init=True)
+
+    # ----------------------------------------------------------------------
+    def MaskedScatterDotsArray(self,region):
+        selection = {self.xregion : ["errormaskedx","manualmaskedx"], self.yregion : ["errormaskedy","manualmaskedy"]}
+        array = np.logical_or(self.stack.shiftsdict[self.itheta][selection[region][0]], self.stack.shiftsdict[self.itheta][selection[region][1]])
+        return array
+    def MakeNewScatterPlots(self):
+        print("makenewscatte")
+        errorthreshold = self.stack.shiftsdict[self.itheta]["threshold"]
+        errors = self.stack.shiftsdict[self.itheta]["errors"]
+        self.MaskScatterDotsAboveErrorThreshold((errors,errorthreshold,self.itheta))
+        maskedx = self.MaskedScatterDotsArray(self.xregion)
+        maskedy = self.MaskedScatterDotsArray(self.yregion)
+
+        self.cb_autoerror.stateChanged.connect(self.OnAutoError)
+        self.cb_extrapolate.stateChanged.connect(self.OnExtrapolate)
+        self.spinBoxFiltersize.valueChanged.connect(self.OnFilter)
+        self.spinBoxError.valueChanged.connect(lambda value: self.OnSpinBoxError(value))
+        self.comboBox_approx.currentIndexChanged.connect(lambda: self.ComposeShiftQueue(init=False))
+
+        self.spinBoxError.blockSignals(True)
+        self.spinBoxError.setDecimals(4)
+        self.spinBoxError.setMinimum(np.partition(errors, 1)[1])  # makes sure that at least two elements are selected
+        self.spinBoxError.setStepType(QtWidgets.QAbstractSpinBox.AdaptiveDecimalStepType)
+        self.OnAutoError()
+        self.spinBoxError.blockSignals(False)
+
+
+        #self.spinBoxError.setValue(self.errormean)
+
+        #self.OnMaskScatterDotsAboveErrorThreshold(errorvals=(errors, round(np.mean(errors),4)))
+        #self.xscatter.addPoints(spots=self.CreateScatterDots(xdots), pxMode=True)
+        #self.yscatter.addPoints(spots=self.CreateScatterDots(ydots), pxMode=True)
+        xdots = self.stack.shiftsdict[self.itheta]["xdots"]
+        ydots = self.stack.shiftsdict[self.itheta]["ydots"]
+        self.xscatter.setData(spots=self.CreateScatterDots(xdots,maskedx), pxMode=True)
+        self.yscatter.setData(spots=self.CreateScatterDots(ydots,maskedy), pxMode=True)
+
+    def OnAutoError(self):
+        print("onautoerror",self.stack.shiftsdict[self.itheta]["threshold"])
+        self.stack.shiftsdict[self.itheta]["autoquality"] = self.cb_autoerror.isChecked()
+        self.stack.shiftsdict[self.itheta]["threshold"] = round(np.mean(self.stack.shiftsdict[self.itheta]["errors"]),
+                                                                4)
+        if self.cb_autoerror.isChecked() and self.aligned:
+            self.spinBoxError.setEnabled(True)
+            self.spinBoxError.setValue(self.stack.shiftsdict[self.itheta]["threshold"])
+        else:
+            self.spinBoxError.setEnabled(False)
+            self.spinBoxError.setValue(1)
+    def OnSpinBoxError(self,value):
+        print("onspinboxerror")
+        self.stack.shiftsdict[self.itheta]["threshold"] = value
+        print(self.stack.shiftsdict[self.itheta]["threshold"])
+        self.MaskScatterDotsAboveErrorThreshold((self.stack.shiftsdict[self.itheta]["errors"], value, self.itheta))
+        self.ColorizeScatterDots()
+        self.ComposeShiftQueue(init=False)
+    def OnExtrapolate(self):
+        self.ComposeShiftQueue(init=False)
+    def OnFilter(self):
+        self.ComposeShiftQueue(init=False)
+
+    def ColorizeScatterDots(self):
+        brushesx = [QtGui.QColor('red') if bool else QtGui.QColor('blue') for bool in self.MaskedScatterDotsArray(self.xregion)]
+        brushesy = [QtGui.QColor('red') if bool else QtGui.QColor('blue') for bool in self.MaskedScatterDotsArray(self.yregion)]
+        self.xscatter.setBrush(brushesx,update=True)
+        self.yscatter.setBrush(brushesy,update=True)
+
+    def MaskScatterDotsAboveErrorThreshold(self, errorvals=None):
+        errors, errorthreshold, itheta = errorvals
+        if self.cb_autoerror.isChecked():
+            self.stack.shiftsdict[itheta]["errormaskedx"] = (errors > np.float64(errorthreshold))
+            self.stack.shiftsdict[itheta]["errormaskedy"] = (errors > np.float64(errorthreshold))
+        else:
+            self.stack.shiftsdict[itheta]["errormaskedx"] = [False] * len(errors)
+            self.stack.shiftsdict[itheta]["errormaskedy"] = [False] * len(errors)
+
+    # ----------------------------------------------------------------------
+    def initParams(self, itheta):
+        self.stack.shiftsdict[itheta]["regionlimitx"] = self.getDataClosestToRegion(self.xregion,self.xscatter,False)[2:]
+        self.stack.shiftsdict[itheta]["regionlimity"] = self.getDataClosestToRegion(self.yregion,self.yscatter,False)[2:]
+        self.stack.shiftsdict[itheta]["filter"] = self.spinBoxFiltersize.value()
+        self.stack.shiftsdict[itheta]["method"] = self.comboBox_approx.currentIndex()
+        #print(self.stack.shiftsdict[itheta]["method"])
+        #self.stack.shiftsdict[itheta]["autoquality"] = self.cb_autoerror.isChecked()
+        self.stack.shiftsdict[itheta]["extrapolation"] = self.cb_extrapolate.isChecked()
+        self.stack.shiftsdict[itheta]["threshold"] = round(np.mean(self.stack.shiftsdict[itheta]["errors"]), 4)
+    def restoreParams(self,itheta):
+        self.xregion.blockSignals(True)
+        self.yregion.blockSignals(True)
+        self.cb_autoerror.blockSignals(True)
+        self.cb_extrapolate.blockSignals(True)
+        self.comboBox_approx.blockSignals(True)
+        self.spinBoxFiltersize.blockSignals(True)
+
+        self.xregion.setRegion(self.stack.shiftsdict[itheta]["regionlimitx"])
+        self.yregion.setRegion(self.stack.shiftsdict[itheta]["regionlimity"])
+        self.cb_autoerror.setChecked(self.stack.shiftsdict[itheta]["autoquality"])
+        self.spinBoxError.blockSignals(True)
+        #self.spinBoxError.setValue(self.stack.shiftsdict[self.itheta]["threshold"])
+        if self.cb_autoerror.isChecked() and self.aligned:
+            self.spinBoxError.setEnabled(True)
+            self.spinBoxError.setValue(self.stack.shiftsdict[self.itheta]["threshold"])
+        else:
+            self.spinBoxError.setEnabled(False)
+            self.spinBoxError.setValue(1)
+        self.spinBoxError.blockSignals(False)
+        self.cb_extrapolate.setChecked(self.stack.shiftsdict[itheta]["extrapolation"])
+        self.comboBox_approx.setCurrentIndex(self.stack.shiftsdict[itheta]["method"])
+        if self.comboBox_approx.currentIndex() == 0:
+            self.spinBoxFiltersize.setEnabled(True)
+        elif self.comboBox_approx.currentIndex() == 1: # linear regression
+            self.spinBoxFiltersize.setEnabled(False)
+        self.spinBoxFiltersize.setValue(self.stack.shiftsdict[itheta]["filter"])
+        # if limits:
+        #     region.setRegion(list(limits))
+        # else:
+        #     region.setRegion([self.stack.ev[0],self.stack.ev[-1]])
+        #self.spinBoxError.blockSignals(False)
+        self.xregion.blockSignals(False)
+        self.yregion.blockSignals(False)
+        self.cb_autoerror.blockSignals(False)
+        self.cb_extrapolate.blockSignals(False)
+        self.comboBox_approx.blockSignals(False)
+        self.spinBoxFiltersize.blockSignals(False)
+
+    def getDataClosestToRegion(self,region,plotitem,snapregion=False):
+        selectregion = {self.xregion : "regionlimitx", self.yregion : "regionlimity"}
+        limits = selectregion[region]
+        minidx, maxidx = region.getRegion()
+        data = plotitem.getData()[0]
+        index = lambda x: np.argmin(np.abs(data - x))
+        minidx = index(minidx)
+        maxidx = index(maxidx)
+        if minidx == maxidx:
+            minidx = 0
+            maxidx = np.argmax(data)
+        mindata = data[minidx]
+        maxdata = data[maxidx]
+        if snapregion:
+            self.stack.shiftsdict[self.itheta][limits] = (mindata,maxdata)  # snap region to data points
+            region.setRegion((mindata,maxdata))
+        return minidx, maxidx, mindata, maxdata
+    
+    def ApplyApproximationFunction(self,region):
+        boolarray = self.MaskedScatterDotsArray(region)
+        selectscatter = {self.xregion: [self.xscatter, "x"] , self.yregion: [self.yscatter, "y"]}
+        selectfit= {self.xregion : self.fit_x, self.yregion : self.fit_y}
+        scatter = selectscatter[region][0]
+        fit = selectfit[region]
+        #min_idx, max_idx, *_ = self.getDataClosestToRegion(region,scatter)
+        selected = np.count_nonzero(boolarray == False)
+        xdata, ydata = scatter.getData()
+        #xdata = xdata[min_idx:max_idx]
+        xdata = xdata[~boolarray]
+        #ydata = ydata[min_idx:max_idx]
+        ydata = ydata[~boolarray]
+        #print(selected)
+        if selected < 2:
+            QtWidgets.QMessageBox.warning(self, 'Error', 'Select at least two images in {}-direction!'.format(selectscatter[region][1]))
+            return []
+        if self.comboBox_approx.currentIndex() == 0: # moving average
+            self.spinBoxFiltersize.setEnabled(True)
+            approximated= ndimage.filters.uniform_filter1d(ydata,self.spinBoxFiltersize.value(),mode = "nearest")
+        elif self.comboBox_approx.currentIndex() == 1: # linear regression
+            self.spinBoxFiltersize.setEnabled(False)
+            reg = linregress([xdata,ydata])
+            approximated = [reg.slope * i + reg.intercept for i in xdata]
+
+        if self.cb_extrapolate.isChecked():
+            fillval= "extrapolate"
+        else:
+            fillval=(approximated[0],approximated[-1])
+
+        interpolate_func = interp1d(xdata, approximated,kind="linear",fill_value=fillval,bounds_error=False)
+        fitdata = [self.stack.ev,np.around(interpolate_func(self.stack.ev),1)] # round fit to a tenth of a px
+        fit.setData(x=fitdata[0], y=fitdata[1])
+        fit.show()
+        return fitdata[1]
+
+    def resetPoolThread(self):
+        try:
+            self.poolthread.started.disconnect()
+            self.poolthread.quit()
+            self.poolthread.wait()
+        except:
+            pass
+        self.pool = TaskDispatcher(self)
+        self.pool.moveToThread(self.poolthread) # GUI is not blocking during calculation due to this
+        self.poolthread.started.connect(self.pool.run)
+
+    def IThetaProgress(self,itheta):
+        #print("ithetaprogress")
+        # Each thread calls this function. The condition prevents multiple calls.
+        if self.slider_theta.value() != itheta:
+            #self.slider_theta.blockSignals(True)
+            self.slider_theta.setValue(itheta)
+            #self.slider_theta.blockSignals(False)
+        #print(self.pool.pool.activeThreadCount())
+
+    def ThreadPoolComplete(self):
+        #print(str(self.pool.pool.activeThreadCount())+" THREADS REMAINING FROM POOL.")
+        #self.slider_theta.setValue(0)
+        if not self.aligned and self.pool.pool.activeThreadCount() == 0:
+            self.OnAligned()
+
+        elif self.aligned and self.pool.pool.activeThreadCount() == 0:
+            self.OnAutoCrop()
+
+    def ComposeAlignQueue(self):
+        self.button_align.setEnabled(False)
+        ref_idx = self.iev
+        # Reset reference img:
+        self.resetPoolThread()
+
+        itheta = 0
+        ntheta = max(self.stack.n_theta,1) # necessary work around for 3d stacks and if 4d stack is loaded with LoadStack()
+        while itheta < ntheta:
+            idx = copy.copy(self.stack.n_ev)
+            while idx: # Generate pairs of indices starting at reference image index.
+                running = 2
+                if (ref_idx + (self.stack.n_ev-idx)) < self.stack.n_ev-1:
+                    self.pool.enqueuetask("AlignReferenced", (ref_idx + (self.stack.n_ev-idx) + 1, ref_idx), itheta)
+                    #q.put((ref_idx + (self.stack.n_ev-idx) + 1, ref_idx))
+                else:
+                    running -= 1
+                if ref_idx - (self.stack.n_ev-idx) > 0:
+                    self.pool.enqueuetask("AlignReferenced", (ref_idx - (self.stack.n_ev-idx) - 1, ref_idx), itheta)
+                    #q.put(((ref_idx - (self.stack.n_ev-idx) - 1),ref_idx))
+                else:
+                    running -= 1
+                if running:
+                    idx -= 1
+                else:
+                    break
+            itheta = itheta + 1
+        if not self.pool.queue.empty():
+            print("total alignqueue composed. starting poolthread")
+            self.poolthread.start()
+        
+    def ComposeShiftQueue(self, init=False):
+        print("composeshift initial?",str(init))
+        self.resetPoolThread()
+        #array = np.logical_or(self.MaskedScatterDotsArray(self.xregion),self.MaskedScatterDotsArray(self.yregion))
+        if not init:
+            ntheta = [self.itheta]
+        else:
+            ntheta = range(max(self.stack.n_theta,1)) # necessary work around for 3d stacks and if 4d stack is loaded with LoadStack()
+            for itheta in ntheta:
+                self.initParams(itheta)
+        for itheta in ntheta:
+            #print(itheta)
+            self.stack.shiftsdict[self.itheta]["filter"] = self.spinBoxFiltersize.value()
+            self.stack.shiftsdict[self.itheta]["method"] = self.comboBox_approx.currentIndex()
+            self.slider_theta.setValue(itheta)
+            #time.sleep(0.2)
+            xshifts = self.ApplyApproximationFunction(self.xregion)
+            yshifts = self.ApplyApproximationFunction(self.yregion)
+            # if empty arrays, i.e., if less than 2 dots selected, do nothing
+            if [] in (xshifts, yshifts):
+                return
+            for ev in range(self.stack.n_ev):
+                # Only enqueue if new shift val is different to previous shift
+                if (self.stack.shiftsdict[itheta]["xshifts"][ev],self.stack.shiftsdict[itheta]["yshifts"][ev]) != (xshifts[ev],yshifts[ev]):
+                    self.stack.shiftsdict[itheta]["xshifts"][ev] = xshifts[ev]
+                    self.stack.shiftsdict[itheta]["yshifts"][ev] = yshifts[ev]
+                    self.pool.enqueuetask("ShiftImg", ev, xshifts[ev], yshifts[ev],itheta)
+                    #print("ShiftImg", ev, xshifts[ev], yshifts[ev],itheta)
+        if not self.pool.queue.empty():
+            print("total shiftqueue composed. starting poolthread with queue size",self.pool.queue.qsize())
+            self.poolthread.start()
+
+    # ----------------------------------------------------------------------
+    def GetIndexPairs(self):
+        idxtuplelst = [(i+1,i) for i in range(self.stack.n_ev-1)]
+        return idxtuplelst
+    # ----------------------------------------------------------------------
+    def OnAutoCrop(self):
+        if self.aligned:
+            self.cb_autocrop.blockSignals(True)
+            self.CropStack4D()
+            self.cb_autocrop.blockSignals(False)
+            self.OnScrollEng(self.iev)
+            self.button_align.setEnabled(True)
+            self.button_ok.setEnabled(True)
+
+    def CropStack4D(self):
+        self.stack.absdata4d_shifted_cropped = self.stack.absdata4d_shifted.copy()
+        if self.cb_autocrop.isChecked():
+            ntheta = range(max(self.stack.n_theta,1)) # necessary work around for 3d stacks and if 4d stack is loaded with LoadStack()
+            #print(ntheta)
+            globalminx = min([j for i in [self.stack.shiftsdict[theta]["xshifts"] for theta in ntheta] for j in i])
+            globalmaxx = max([j for i in [self.stack.shiftsdict[theta]["xshifts"] for theta in ntheta] for j in i])
+            globalminy = min([j for i in [self.stack.shiftsdict[theta]["yshifts"] for theta in ntheta] for j in i])
+            globalmaxy = max([j for i in [self.stack.shiftsdict[theta]["yshifts"] for theta in ntheta] for j in i])
+            print("cropstack4d: ",globalminx,globalmaxx,globalminy,globalmaxy)
+            #if not self.com.stack_4d:
+            self.box.hide()
+            l = -int(np.floor(globalminx))
+            r = -int(np.ceil(globalmaxx))
+            cr = r if r < 0 else None
+            if l < 0:
+                l = 0
+                cr = cr - l
+            b = -int(np.floor(globalminy))
+            t = -int(np.ceil(globalmaxy))
+            ct = t if t < 0 else None
+            if b < 0:
+                b = 0
+                ct = ct - b
+            if 0 in self.stack.absdata4d_shifted_cropped[l:cr,b:ct,:,self.itheta].shape:
+                QtWidgets.QMessageBox.warning(self, 'Error', 'The alignment failed. Cropping would result in a zero-dimensional image. Please check your settings. Auto-crop has been disabled. You can re-enable it manually.')
+                self.cb_autocrop.setChecked(False)
+                self.OnResetROI()
+            else:
+                self.stack.absdata4d_shifted_cropped = self.stack.absdata4d_shifted_cropped[l:cr,b:ct,:,:]
+        else:
+            self.box.show()
+
+    def OnScrollEng(self, value):
+        self.slider_eng.setValue(value)
+        self.iev = value
+        self.ShowImage()
+        self.refmarkerx.setValue(self.stack.ev[self.iev])
+        self.refmarkery.setValue(self.stack.ev[self.iev])
+    def OnScrollTheta(self, value):
+        #if value != self.itheta:
+        #print("Theta slider" + str(value))
+        self.slider_theta.setValue(value)
+        self.itheta = value
+        #self.ClearShifts()
+        self.ShowImage()
+        if self.aligned:
+            #self.MakeNewScatterPlots()
+            errorthreshold = self.stack.shiftsdict[self.itheta]["threshold"]
+            errors = self.stack.shiftsdict[self.itheta]["errors"]
+            if not errorthreshold:
+                errorthreshold = round(np.mean(errors), 4)
+            self.restoreParams(self.itheta)
+            self.MaskScatterDotsAboveErrorThreshold((errors, errorthreshold, self.itheta))
+            # if self.cb_autoerror.isChecked():
+            #     self.spinBoxError.blockSignals(True)
+            #     self.spinBoxError.setValue(errorthreshold)
+            #     self.spinBoxError.blockSignals(False)
+            xdots = self.stack.shiftsdict[self.itheta]["xdots"]
+            ydots = self.stack.shiftsdict[self.itheta]["ydots"]
+            maskedx = self.MaskedScatterDotsArray(self.xregion)
+            maskedy = self.MaskedScatterDotsArray(self.yregion)
+            self.xscatter.setData(spots=self.CreateScatterDots(xdots, maskedx), pxMode=True)
+            self.yscatter.setData(spots=self.CreateScatterDots(ydots, maskedy), pxMode=True)
+            self.fit_x.setData(x=self.stack.ev, y=self.stack.shiftsdict[self.itheta]["xshifts"])
+            self.fit_y.setData(x=self.stack.ev, y=self.stack.shiftsdict[self.itheta]["yshifts"])
+
+            #min_idx, max_idx, min_ev, max_ev = self.getDataClosestToRegion(self.xregion, self.xscatter, True)
+            #min_idx, max_idx, min_ev, max_ev = self.getDataClosestToRegion(self.yregion, self.yscatter, True)
+
+            #self.fit_x.show()
+            self.OnLinRegion(self.xregion, update=False)
+            self.OnLinRegion(self.yregion, update=False)
+
+    def ShowImage(self):
+        self.stack.absdata_shifted_cropped = self.stack.absdata4d_shifted_cropped[:, :, :, int(self.itheta)]
+        self.i_item.setImage(self.stack.absdata_shifted_cropped[:, :, int(self.iev)])
+        if self.com.stack_4d == 1:
+            self.groupBox.setTitle(str('Stack Browser | Image at {0:5.2f} eV and {1:5.1f}°').format(float(self.stack.ev[self.iev]),float(self.stack.theta[self.itheta]), ))
+        else:
+            self.groupBox.setTitle(str('Stack Browser | Image at {0:5.2f} eV').format(float(self.stack.ev[self.iev])))
+
+    ## Setup a ROI for an alignment rectangle. By default the whole image area is used.
+    def SetupROI(self):
+        self.box = pg.RectROI(self.i_item.boundingRect().topLeft(), self.i_item.boundingRect().bottomRight(),
+                              pen=(5, 8), handlePen=QtGui.QPen(QtGui.QColor(255, 0, 128, 255)), centered=False,
+                              sideScalers=False, removable=False, scaleSnap=True, translateSnap=True,
+                              maxBounds=self.i_item.boundingRect())
+        self.vb.addItem(self.box, ignoreBounds=False)
+        self.box.sigRegionChangeFinished.connect(self.OnBoxChanged)
+        self.box.sigRegionChangeStarted.connect(self.OnBoxChanging)
+        self.button_rstroi.clicked.connect(self.OnResetROI)
+    ## The ROI is limited to the visible image area. OnMouseMoveOutside handles the behavior when
+    def ClearShifts(self):
+        self.aligned = False
+        self.cb_autoerror.stateChanged.disconnect()
+        self.fit_x.hide()
+        self.fit_y.hide()
+        self.InitShiftsDict()
+        self.button_align.setEnabled(True)
+        self.MakeNewScatterPlots()
+    def OnResetROI(self):
+        self.ClearShifts()
+        self.stack.absdata4d_shifted_cropped = self.stack.absdata4d.copy()
+        self.OnScrollEng(self.iev)
+        self.box.setPos(0, 0, update=False, finish=False)
+        self.box.setSize(self.i_item.boundingRect().bottomRight() - self.box.pos(), update=True, snap=True, finish=True)
+        self.box.show()
+    def OnBoxChanging(self):
+        self.boxsize = self.box.size()
+        self.proxy = pg.SignalProxy(self.vb.scene().sigMouseMoved, rateLimit=30, slot=self.OnMouseMoveOutside)
+    def OnBoxChanged(self):
+        try:
+            self.proxy.disconnect()
+        except AttributeError:
+            pass
+        left = int(self.box.pos().x())
+        right = left + int(self.box.size().x())
+        bottom = int(self.box.pos().y())
+        top = bottom + int(self.box.size().y())
+        self.stack.absdata_cropped = self.stack.absdata4d[left:right, bottom:top, :,:].copy()
+
+    def OnLinRegion(self, region, update=True):
+        #print("OnLinRegion", str(update))
+        selectregion= {self.xregion : "manualmaskedx", self.yregion : "manualmaskedy"}
+        selectscatter = {self.xregion : self.xscatter, self.yregion : self.yscatter}
+        selectregionlimit= {self.xregion : "regionlimitx", self.yregion : "regionlimity"}
+        selectplot = {self.xregion : self.px, self.yregion : self.py}
+        #print("onlinregion "+ selectregion[region])
+        scatter = selectscatter[region]
+        min_idx, max_idx, min_ev, max_ev = self.getDataClosestToRegion(region,scatter,update)
+        selection = [*range(min_idx, max_idx+1)]
+        for idx,val in enumerate(self.stack.shiftsdict[self.itheta]["manualmaskedx"]):
+            if idx not in selection:
+                self.stack.shiftsdict[self.itheta][selectregion[region]][idx] = True
+            else:
+                self.stack.shiftsdict[self.itheta][selectregion[region]][idx] = False
+        y_vals= selectscatter[region].data["y"][min_idx:max_idx + 1]
+        selectplot[region].setRange(yRange=[np.min(y_vals), np.max(y_vals)], disableAutoRange=True, padding=0.1)
+        self.ColorizeScatterDots()
+        #filter = [True if idx in selection else False for idx,bool in enumerate(self.stack.shiftsdict[self.itheta]["manualmaskedx"])]
+        #print(selection,filter)
+        #self.UpdateScatterPlots(region, id)
+        if not self.aligned:
+            for theta in range(self.stack.n_theta):
+                self.stack.shiftsdict[theta][selectregionlimit[region]] = (min_ev, max_ev)
+        if self.aligned and update:
+            self.stack.shiftsdict[self.itheta][selectregionlimit[region]] = (min_ev, max_ev)
+            #print("ComposeShiftQueue"+selectregion[region])
+            self.ComposeShiftQueue()
+
+    def OnMouseMoveOutside(self, ev):
+        mousepos = self.vb.mapSceneToView(ev[0])
+        if not self.vb.itemBoundingRect(self.i_item).contains(mousepos):
+            maxrect = self.i_item.boundingRect().bottomRight()
+            # if bounds exceeded
+            out_x = max((mousepos-maxrect).x(),0)
+            out_y = max((mousepos-maxrect).y(), 0)
+            if self.box.size() != self.boxsize: # prevents taking action when the box is just dragged and not resized
+                if out_x and out_y:
+                    self.box.setSize(self.i_item.boundingRect().bottomRight()-self.box.pos(), update=True, snap=True, finish=False)
+                elif out_x:
+                    self.box.setSize([self.i_item.boundingRect().right()-self.box.pos().x(),mousepos.y()-self.box.pos().y()], update=True, snap=True, finish=False)
+                elif out_y:
+                    self.box.setSize([mousepos.x()-self.box.pos().x(),self.i_item.boundingRect().bottom()-self.box.pos().y()], update=True, snap=True, finish=False)
+# ----------------------------------------------------------------------
+    def OnCancel(self, evt):
+        self.stack.absdata_shifted_cropped = self.stack.absdata
+        self.parent.page1.loadImage()
+
+        if showmaptab:
+            self.parent.page9.Clear()
+            self.parent.page9.LoadEntries()
+
+        self.close()
+    # ----------------------------------------------------------------------
+    def OnAccept(self, evt):
+        if self.com.stack_4d == 0:
+            self.stack.absdata = self.stack.absdata4d_shifted_cropped[:,:,:,0]
+            self.stack.data_struct.exchange.data = self.stack.absdata
+        else:
+            self.stack.stack4D = self.stack.absdata4d_shifted_cropped
+            self.stack.absdata = self.stack.stack4D[:, :, :, self.itheta]
+            self.stack.data_struct.exchange.data = self.stack.stack4D
+            #QtWidgets.QMessageBox.warning(self, 'Error', '4D stack not yet supported.')
+
+        datadim = np.int32(self.stack.absdata.shape)
+
+        self.stack.n_cols = datadim[0].copy()
+        self.stack.n_rows =  datadim[1].copy()
+        #ToDo: Handshake data
+        #self.stack.xshifts = self.x_shiftstemp
+        #self.stack.yshifts = self.y_shiftstemp
+
+        #ToDo: How to handle aligned i0 data?
+
+        # if self.com.i0_loaded == 1:
+        #     if self.com.stack_4d == 0:
+        #         #Resize optical density
+        #         for i in range(self.stack.n_ev):
+        #
+        #             img = self.stack.od3d[:,:,i]
+        #             shifted_img = self.stack.apply_image_registration(img, self.xshifts[i], self.yshifts[i])
+        #             self.stack.od3d[:,:,i] = shifted_img
+        #
+        #
+        #         self.stack.od3d = self.stack.od3d[self.xleft:self.xright, self.ybottom:self.ytop, :]
+        #
+        #         self.stack.od = self.stack.od3d.copy()
+        #         self.stack.od = np.reshape(self.stack.od, (self.stack.n_cols*self.stack.n_rows, self.stack.n_ev), order='F')
+        #
+        #     else:
+        #         #Resize optical density for 4D stack
+        #
+        #         for i in range(self.stack.n_ev):
+        #             for j in range(self.stack.n_theta):
+        #                 img = self.stack.od4D[:,:,i,j]
+        #                 shifted_img = self.stack.apply_image_registration(img, self.xshifts[i,j], self.yshifts[i,j])
+        #                 self.stack.od4D[:,:,i,j] = shifted_img
+        #
+        #         self.stack.od4D = self.stack.od4D[self.xleft:self.xright, self.ybottom:self.ytop, :, :]
+        #
+        #         self.stack.od3d = self.stack.od4D[:,:,:,self.itheta]
+        #         self.stack.od = self.stack.od3d.copy()
+        #         n_pixels = self.stack.n_cols*self.stack.n_rows
+        #         self.stack.od = np.reshape(self.stack.od, (n_pixels, self.stack.n_ev), order='F')
+        #
+        #     self.stack.data_struct.spectromicroscopy.optical_density = self.stack.od
+
+        self.stack.data_struct.exchange.energy = self.stack.ev
+        #ToDo: Handshake shift data
+        #self.stack.data_struct.spectromicroscopy.xshifts = self.x_shiftstemp
+        #self.stack.data_struct.spectromicroscopy.yshifts = self.y_shiftstemp
+
+        self.parent.page1.slider_eng.setRange(0,self.stack.n_ev-1)
+        self.parent.page1.iev = int(self.stack.n_ev/2)
+        self.parent.page1.slider_eng.setValue(self.parent.page1.iev)
+
+        self.parent.page1.ix = int(self.stack.n_cols/2)
+        self.parent.page1.iy = int(self.stack.n_rows/2)
+
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        self.parent.page1.loadImage()
+
+        if showmaptab:
+            self.parent.page9.Clear()
+            self.parent.page9.LoadEntries()
+
+        self.close()
+
+#----------------------------------------------------------------------
+class SpectralImageMap(QtWidgets.QDialog, QtWidgets.QGraphicsScene):
+    #evlistchanged = pyqtSignal([object])
+    #thetalistchanged = pyqtSignal([object])
+    def __init__(self, parent, common, stack):
+        QtWidgets.QWidget.__init__(self, parent)
+        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'showspectralroi.ui'), self)
+        self.parent = parent
+        self.stack = stack
+        self.com = common
+        self.iev = 0
+        self.itheta = 0
+        # self.stack.absdata_shifted_cropped = self.stack.absdata_shifted.copy()
+
+        # self.poolthread = QtCore.QThread()
+        # self.aligned = False
+        self.button_ok.setEnabled(True)
+
+        self.setWindowTitle('Spectral Image Map')
+        #self.pglayout = pg.GraphicsLayout(border=None)
+        #self.canvas.setBackground("w")  # canvas is a pg.GraphicsView widget
+        #self.canvas.setCentralWidget(self.pglayout)
+        #self.vb = self.pglayout.addViewBox()
+        #self.vb.setAspectLocked()
+        #self.i_item = pg.ImageItem(border="k", parent=self)
+
+        #self.vb.setMouseEnabled(x=False, y=False)
+        #self.vb.addItem(self.i_item, ignoreBounds=False)
+
+        self.button_ok.clicked.connect(self.OnAccept)
+        self.button_cancel.clicked.connect(self.OnCancel)
+
+        if self.com.stack_loaded == 1:
+        #     self.label_theta_range.setVisible(False)
+        #     self.slider_theta.setVisible(False)
+        #     self.cb_remove_theta.setVisible(False)
+        #     self.groupBox_theta.setVisible(False)
+        #     if self.com.stack_4d == 1:
+        #         self.label_theta_range.setVisible(True)
+        #         self.slider_theta.setVisible(True)
+        #         self.cb_remove_theta.setVisible(True)
+        #         self.groupBox_theta.setVisible(True)
+        #         self.slider_theta.setRange(0, self.stack.n_theta - 1)
+        #         self.slider_theta.valueChanged[int].connect(self.OnScrollTheta)
+        #         self.SetupListTheta()
+        #     # self.maskedvals = [True] * int(self.stack.n_ev)
+        #     # self.spinBoxError.setEnabled(False)
+        #     self.slider_eng.sliderPressed.connect(self.ShowImage)
+        #     self.slider_eng.sliderReleased.connect(self.ShowImage)
+        #     self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
+        #     self.slider_eng.setRange(0, self.stack.n_ev - 1)
+        #     self.pb_selectall.clicked.connect(self.OnSelectAll)
+        #     self.pb_clearall.clicked.connect(self.OnClearAll)
+        #     self.evlistchanged.connect(lambda row: self.qListChangeHandler(row, "energy"))
+        #     self.thetalistchanged.connect(lambda row: self.qListChangeHandler(row, "theta"))
+        #     # self.ev_widget.itemClicked.connect(lambda item: self.OnItemClicked(item))
+        #     self.ev_widget.mousePressEvent = self.mouseEventOnEVList
+        #     self.ev_widget.mouseMoveEvent = self.mouseEventOnEVList
+        #     self.theta_widget.mousePressEvent = self.mouseEventOnThetaList
+        #     self.theta_widget.mouseMoveEvent = self.mouseEventOnThetaList
+            # self.ev_widget.itemSelectionChanged.connect(lambda item: self.OnItemClicked(item))
+            #self.SetupListEV()
+            #self.OnScrollEng(0)
+            #self.SetupROI()
+            self.SetupPlot()
+
+    def OnSelectionChanged(self):
+        #self.RedrawNewPlot()
+        # self.UpdateIndices()
+        self.region_i0.blockSignals(True)
+        if self.idx_selected:
+            self.region_i0.setRegion([self.stack.ev[min(self.idx_selected)], self.stack.ev[max(self.idx_selected)]])
+            self.region_i0.blockSignals(False)
+            #self.spectrum_plotwidget.setXRange(*self.region_i0.getRegion())
+            #self.spectrum_plotwidget.setYRange(np.min(self.plotitem_new.yData), np.max(self.plotitem_new.yData))
+        return
+
+    def GenerateSpectrum(self, evselection):
+        #left,right,top,bottom = self.GetRegion()
+        if self.com.i0_loaded == 1:
+            if self.com.stack_4d == 1:
+                total = self.stack.od4d[:, :, :, int(self.itheta)].copy()
+            else:
+                total = self.stack.od3d[:, :, :].copy()
+
+        else:
+            if self.com.stack_4d == 1:
+                # t = [self.stack.theta[i] for i in self.thetaidx_selected]
+                # self.label_theta_range.setText(
+                #     "Theta range: [ " + str(min(t, default=0)) + "° .. " + str(
+                #         max(t, default=0)) + "° ], # values: " + str(
+                #         len(t)))
+                total = self.stack.stack4D[:, :, :, int(self.itheta)].copy()
+            else:
+                total = self.stack.absdata[:, :, :].copy()
+        total = total.sum(axis=(0,1)) #/ (int(self.box.size().x()) * int(self.box.size().y()))
+        x = self.stack.ev
+        y = total
+        #self.label_spatial_range.setText("Stack size: [ "+str(int(self.box.size().x()))+" x "+str(int(self.box.size().y()))+" ] px²")
+        #self.label_ev_range.setText(
+        #    "Energy range: [ " + str(min(x, default=0)) + " .. " + str(max(x, default=0)) + " ] eV, # values: "+ str(len(x)))
+        return (x, y)
+    # def UpdateIndices(self):
+    #     self.idx_selected = sorted([self.ev_widget.row(i) for i in self.ev_selected])
+    #     if self.com.stack_4d:
+    #         self.thetaidx_selected = sorted([self.theta_widget.row(i) for i in self.theta_selected])
+    #
+    # def RedrawPlots(self):
+    #     x, y = self.GenerateSpectrum(list(range(self.stack.n_ev)))
+    #     self.plotitem.setData(x, y)
+    #     self.OnSelectionChanged()
+    #
+    # def RedrawNewPlot(self):
+    #     #self.UpdateIndices()
+    #     x, y = self.GenerateSpectrum(self.idx_selected)
+    #     self.plotitem_new.setData(x, y)
+    #     if self.idx_selected:
+    #         self.region_i0.show()
+    #
+    # def qListChangeHandler(self, row, dimension):
+    #     if dimension == "theta":
+    #         selection = self.theta_selected
+    #         widget = self.theta_widget
+    #     elif dimension == "energy":
+    #         selection = self.ev_selected
+    #         widget = self.ev_widget
+    #
+    #     if row in selection:
+    #         selection.remove(row)
+    #         row.setBackground(QtGui.QColor(0, 0, 0, 0))
+    #     else:
+    #         selection.append(row)
+    #         row.setBackground(QtGui.QColor('#beaed4'))
+    #     if dimension == "theta":
+    #         self.OnScrollTheta(widget.row(row))
+    #     elif dimension == "energy":
+    #         self.OnScrollEng(widget.row(row))
+    #     self.OnSelectionChanged()
+
+    def SetupPlot(self):
+        x, y = self.GenerateSpectrum(list(range(self.stack.n_ev)))
+        self.spectrum_plotwidget.setBackground("w")
+
+        self.region_i0 = pg.LinearRegionItem(brush=QtGui.QColor('#88beaed4'),hoverBrush=QtGui.QColor('#ccbeaed4'), bounds=[np.min(x), np.max(x)])
+        self.region_i0.setZValue(10)
+        self.region_i = pg.LinearRegionItem(brush=QtGui.QColor('#887fc97f'),hoverBrush=QtGui.QColor('#cc7fc97f'), bounds=[np.min(x), np.max(x)])
+        self.region_i.setZValue(10)
+
+        plot = self.spectrum_plotwidget
+        plot.setBackground("w")
+        plot.addItem(self.region_i0, ignoreBounds=False)
+        plot.addItem(self.region_i, ignoreBounds=False)
+        plot.setMouseEnabled(x=False, y=False)
+        plot.showGrid(y=True)
+
+        plot.showAxis("top", show=True)
+        plot.showAxis("right", show=True)
+        by = plot.getAxis("right")
+        bx = plot.getAxis("top")
+        by.setStyle(showValues=False, tickLength=0)
+        bx.setStyle(showValues=False, tickLength=0)
+        ay = plot.getAxis("left")
+        ax = plot.getAxis("bottom")
+
+        ax.setLabel(text="Photon energy [eV]")
+        if self.com.i0_loaded:
+            ay.setLabel(text="Optical density")
+        else:
+            ay.setLabel(text="Photon flux [cps]")
+
+        self.plotitem = plot.plot(x, y, pen=pg.mkPen(color="b", width=2))
+        self.plotitem.setZValue(100)
+        # self.plotitem_new = plot.plot(x, y, pen=pg.mkPen(color="b", width=2))
+        # self.refmarker = pg.InfiniteLine(angle=90, movable=False,
+        #                                  pen=pg.mkPen(color="b", width=2, style=QtCore.Qt.DashLine))
+        #plot.addItem(self.refmarker, ignoreBounds=True)
+        self.region_i0.setRegion((min(x), min(x)+0.25*(max(x)-min(x))))
+        self.region_i.setRegion(((max(x)-0.25*(max(x)-min(x))), max(x)))
+        #self.region_i0.sigRegionChange.connect(self.UpdateSelection)
+        #self.region_i.sigRegionChange.connect(self.UpdateSelection)
+        self.region_i0.sigRegionChangeFinished.connect(self.UpdateSelection)
+        self.region_i.sigRegionChangeFinished.connect(self.UpdateSelection)
+    # ----------------------------------------------------------------------
+    def getDataClosestToRegion(self, region, plotitem, snapregion=True):
+        #otherregion = {self.region_i : self.region_i0, self.region_i0: self.region_i}
+        minidx, maxidx = region.getRegion()
+        data = plotitem.getData()[0]
+        index = lambda x: np.argmin(np.abs(data - x))
+        minidx = index(minidx)
+        maxidx = index(maxidx)
+        if minidx == maxidx:
+            minidx = 0
+            maxidx = np.argmax(data)
+        mindata = data[minidx]
+        maxdata = data[maxidx]
+        if region == self.region_i:
+            self.region_i0.setBounds((min(data), data[minidx]))
+        elif region == self.region_i0:
+            self.region_i.setBounds((data[maxidx], max(data)))
+        if snapregion:
+            region.blockSignals(True)
+            region.setRegion([mindata, maxdata])  # snap region to data points
+            region.blockSignals(False)
+            #self.parent.OnSelectionChanged()
+        return minidx, maxidx, mindata, maxdata
+
+    def UpdateSelection(self):
+        mini0, maxi0, mindi0, maxdi0 = self.getDataClosestToRegion(self.region_i0,self.plotitem)
+        mini, maxi, mindi, maxdi = self.getDataClosestToRegion(self.region_i,self.plotitem)
+        #self.region_i0.blockSignals(True)
+        #self.region_i.blockSignals(True)
+        #self.region_i0.setBounds((min(self.plotitem.getData()[0]),mindi))
+        #self.region_i.setBounds((maxdi0,max(self.plotitem.getData()[0])))
+        #self.region_i0.blockSignals(False)
+        #self.region_i.blockSignals(False)
+
+        qlist = self.parent.MapSelectWidget1
+        for row in range(qlist.count()):
+            if row in range(mini0, maxi0):
+                self.stack.shifts[row][1]= -1
+                qlist.item(row).setBackground(QtGui.QColor('#beaed4'))
+            elif row in range(mini, maxi):
+                self.stack.shifts[row][1]= 1
+                qlist.item(row).setBackground(QtGui.QColor('#7fc97f'))
+            else:
+                self.stack.shifts[row][1]= 0
+                qlist.item(row).setBackground(QtGui.QColor(0, 0, 0, 0))
+        self.parent.OnSelectionChanged()
+    # ----------------------------------------------------------------------
+    def OnCancel(self, evt):
+        self.close()
+
+    # # ----------------------------------------------------------------------
+    def OnAccept(self, evt):
+        pass
+    #     if self.cb_croptoroi.isChecked():
+    #         left, right, top, bottom = self.GetRegion()
+    #     else:
+    #         left, right, top, bottom = (None, None, None, None)
+    #
+    #     if self.cb_remove_evs.isChecked():
+    #         selection = self.idx_selected
+    #         if len(selection) == 0:
+    #             QtWidgets.QMessageBox.warning(self, 'Error', 'Please select at least one energy value!')
+    #             return
+    #         self.stack.n_ev = np.array(len(selection))
+    #         self.stack.ev = self.stack.ev[selection]
+    #         self.stack.data_dwell = self.stack.data_dwell[selection]
+    #     else:
+    #         selection = list(range(self.stack.n_ev))
+    #
+    #     self.stack.absdata = self.stack.absdata[left:right, bottom:top, selection]
+    #     self.stack.n_cols = self.stack.absdata.shape[0]
+    #     self.stack.n_rows = self.stack.absdata.shape[1]
+    #     self.parent.page1.ix = int(self.stack.n_cols / 2)
+    #     self.parent.page1.iy = int(self.stack.n_rows / 2)
+    #
+    #     if self.com.stack_4d:
+    #         if self.cb_remove_theta.isChecked():
+    #             thetas = self.thetaidx_selected
+    #             if len(thetas) == 0:
+    #                 QtWidgets.QMessageBox.warning(self, 'Error', 'Please select at least one theta value!')
+    #                 return
+    #             self.stack.n_theta = len(thetas)
+    #             self.stack.theta = self.stack.theta[thetas]
+    #
+    #         else:
+    #             thetas = list(range(self.stack.n_theta))
+    #         self.stack.stack4D = self.stack.stack4D[left:right, bottom:top, selection, :]
+    #         self.stack.stack4D = self.stack.stack4D[:, :, :, thetas]
+    #     if self.com.i0_loaded:
+    #         if self.com.stack_4d:
+    #             self.stack.od4D = self.stack.od4D[left:right, bottom:top, selection, thetas]
+    #         else:
+    #             self.stack.od3d = self.stack.od3d[left:right, bottom:top, selection]
+    #             self.stack.od = self.stack.od3d.copy()
+    #             self.stack.od = np.reshape(self.stack.od, (self.stack.n_rows * self.stack.n_cols, self.stack.n_ev),
+    #                                        order='F')
+    #
+    #     self.stack.fill_h5_struct_from_stk()
+    #     if self.com.i0_loaded == 1:
+    #         self.stack.fill_h5_struct_normalization()
+    #
+    #     # Fix the slider on Page 1!
+    #     if self.com.stack_4d:
+    #         self.parent.page1.slider_theta.setRange(0, self.stack.n_theta - 1)
+    #         self.parent.page1.itheta = 0
+    #         self.parent.page1.slider_theta.blockSignals(True)
+    #         self.parent.page1.slider_theta.setValue(int(self.parent.page1.itheta))
+    #         self.parent.page1.slider_theta.blockSignals(False)
+    #
+    #         self.parent.page0.slider_theta.setRange(0, self.stack.n_theta - 1)
+    #         self.parent.page0.itheta = 0
+    #         self.parent.page0.slider_theta.blockSignals(True)
+    #         self.parent.page0.slider_theta.setValue(int(self.parent.page1.itheta))
+    #         self.parent.page0.slider_theta.blockSignals(False)
+    #
+    #     self.parent.page1.slider_eng.setRange(0, self.stack.n_ev - 1)
+    #     self.parent.page1.iev = 0
+    #     self.parent.page1.slider_eng.setValue(int(self.parent.page1.iev))
+    #
+    #     self.parent.page0.slider_eng.setRange(0, self.stack.n_ev - 1)
+    #     self.parent.page0.iev = 0
+    #     self.parent.page0.slider_eng.setValue(int(self.parent.page1.iev))
+    #
+    #     self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+    #     self.parent.page1.loadImage()
+    #     self.parent.page0.Clear()
+    #     self.parent.page0.LoadEntries()
+    #
+    #     if showmaptab:
+    #         self.parent.page9.Clear()
+    #         self.parent.page9.LoadEntries()
+    #
+    #     self.close()
+
+class SpectralROI(QtWidgets.QDialog):
+
+    def __init__(self, parent,  common, stack):
+        QtWidgets.QWidget.__init__(self, parent)
+
+        self.parent = parent
+
+        self.stack = stack
+        self.com = common
+
         self.resize(630, 700)
         self.setWindowTitle('Spectral Regions of Interest')
 
@@ -13264,7 +14481,7 @@ class DarkSignal(QtWidgets.QDialog):
             self.stack.fill_h5_struct_normalization()
 
 
-        self.parent.page1.loadSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
         self.parent.page1.loadImage()
 
 
@@ -13546,171 +14763,285 @@ class ColorTableFrame(QtWidgets.QDialog):
 
 
 """ ------------------------------------------------------------------------------------------------"""
+
 class PageLoadData(QtWidgets.QWidget):
     def __init__(self, common, data_struct, stack):
         super(PageLoadData, self).__init__()
+        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pageloaddata.ui'), self)
+        self.show()
+        self.cmaps = [('Perceptually Uniform Sequential', [
+            'viridis', 'plasma', 'inferno', 'magma']),
+                      ('Sequential', [
+                          'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
+                          'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
+                          'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
+                      ('Sequential (2)', [
+                          'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
+                          'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
+                          'hot', 'afmhot', 'gist_heat', 'copper']),
+                      ('Diverging', [
+                          'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
+                          'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']),
+                      ('Qualitative', [
+                          'Pastel1', 'Pastel2', 'Paired', 'Accent',
+                          'Dark2', 'Set1', 'Set2', 'Set3',
+                          'tab10', 'tab20', 'tab20b', 'tab20c']),
+                      ('Miscellaneous', [
+                          'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
+                          'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'hsv',
+                          'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar'])]
 
         self.initUI(common, data_struct, stack)
 
 #----------------------------------------------------------------------
     def initUI(self, common, data_struct, stack):
-
+        self.scale = 0.000001
         self.data_struct = data_struct
         self.stk = stack
         self.com = common
 
         self.filename = " "
-
+        self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
+        self.slider_theta.valueChanged[int].connect(self.OnScrollTheta)
         self.iev = 0
         self.itheta = 0
 
-        self.initMatplotlib()
-
-        #panel 1
-        sizer1 = QtWidgets.QGroupBox('Load Data Stack')
-        vbox1 = QtWidgets.QVBoxLayout()
-
-        self.button_multiload = QtWidgets.QPushButton('  Load XANES Stack  ')
         self.button_multiload.clicked.connect( self.OnLoadMulti)
         self.button_multiload.setToolTip('Supported Formats .hdf .hdf5 .ncb .nxs .hdr .stk .tif .tiff .txrm')
-        vbox1.addWidget(self.button_multiload)
 
-
-        self.button_4d = QtWidgets.QPushButton( 'Load 4D stack TOMO-XANES')
         self.button_4d.setToolTip('Supported Formats .hdf5 .ncb')
         self.button_4d.clicked.connect( self.OnLoad4D)
-        vbox1.addWidget(self.button_4d)
 
-        sizer1.setLayout(vbox1)
-
-        #panel 2
-        sizer2 = QtWidgets.QGroupBox('Build a stack from a set of files')
-        vbox2 = QtWidgets.QVBoxLayout()
+        #ToDo: Repair Stack Builder
+        #ToDo: Repair Scaling/scalebar for HDF5 files.
+        self.button_sm.setToolTip('Supported Formats .sm, .xrm')
+        self.button_sm.clicked.connect( self.OnBuildStack)
 
-        button_sm = QtWidgets.QPushButton( ' Select a directory with stack files  [.sm, .xrm] ')
-        button_sm.setToolTip('Supported Formats .sm, .xrm')
-        button_sm.clicked.connect( self.OnBuildStack)
-        vbox2.addWidget(button_sm)
-
-        sizer2.setLayout(vbox2)
+        self.MetricCheckBox.toggled.connect(lambda:     self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),self.SquarePxCheckBox.isChecked()))
+        self.ZeroOriginCheckBox.toggled.connect(lambda: self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),self.SquarePxCheckBox.isChecked()))
+        self.SquarePxCheckBox.toggled.connect(lambda:   self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),self.SquarePxCheckBox.isChecked()))
+        self.SquarePxCheckBox.setVisible(False)
 
+        self.CMCatBox.addItems([self.cmaps[0][0],self.cmaps[1][0],self.cmaps[2][0],self.cmaps[3][0],self.cmaps[4][0],self.cmaps[5][0]])
+        self.CMMapBox.addItems(self.cmaps[2][1])
+        self.CMCatBox.setCurrentIndex(2)
+        self.CMMapBox.setCurrentIndex(3)
+        self.CMCatBox.currentIndexChanged.connect(self.OnCatChanged)
+        self.CMMapBox.currentIndexChanged.connect(lambda: self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value()))
+        self.StepSpin.valueChanged.connect(lambda:        self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value()))
 
-        #panel 3
-        sizer3 = QtWidgets.QGroupBox('File')
-        vbox3 = QtWidgets.QVBoxLayout()
+        self.pb_rotate.clicked.connect(self.OnRotate)
+        self.pb_mirror.clicked.connect(self.OnMirror)
+        self.pb_copy.clicked.connect(self.OnCopy)
+        self.pglayout = pg.GraphicsLayout(border=None)
+        self.canvas.setBackground("w") # canvas is a pg.GraphicsView widget
+        self.canvas.setCentralWidget(self.pglayout)
 
+        self.p1 = self.pglayout.addPlot(row=0, col=0, rowspan=1, colspan=1)
+        self.p1.setMouseEnabled(x=False, y=False)
+        self.i_item = pg.ImageItem(border="k")
+        self.p1.setAspectLocked(lock=True, ratio=1)
+        self.p1.showAxis("top", show=True)
+        self.p1.showAxis("bottom", show=True)
+        self.p1.showAxis("left", show=True)
+        self.p1.showAxis("right", show=True)
+        self.ay1 = self.p1.getAxis("left")
+        by1 = self.p1.getAxis("right")
+        self.ax1 = self.p1.getAxis("bottom")
+        bx1 = self.p1.getAxis("top")
+        self.ay1.setLabel(text="y",units="px")
+        self.ay1.enableAutoSIPrefix(enable=True)
+        self.ax1.setLabel(text="x",units="px")
+        self.ax1.enableAutoSIPrefix(enable=True)
+        self.ay1.setStyle(tickLength=8)
+        self.ax1.setStyle(tickLength=8)
+        by1.setStyle(showValues=False,tickLength=0)
+        bx1.setStyle(showValues=False,tickLength=0)
+        self.p1.setTitle("No data loaded")
 
-        self.tc_file = QtWidgets.QLabel(self)
-        vbox3.addWidget(self.tc_file)
-        self.tc_file.setText('File name')
+        self.cmimg = pg.ImageItem(border=None)
+        self.cm = self.pglayout.addPlot(row=0, col=1, rowspan=1, colspan=1)
+        self.cm.addItem(self.cmimg)
+        self.cm.setMouseEnabled(x=False, y=False)
+        self.cm.getViewBox().autoRange(padding=0)
+        self.cm.showAxis("top", show=True)
+        self.cm.showAxis("bottom", show=True)
+        self.cm.showAxis("left", show=True)
+        self.cm.showAxis("right", show=True)
+        self.cm.setTitle("")
+        ay3 = self.cm.getAxis("left")
+        ay3.setZValue(1000)
+        by3 = self.cm.getAxis("right")
+        by3.setZValue(1000)
+        bx3 = self.cm.getAxis("top")
+        bx3.setZValue(1000)
+        ax3 = self.cm.getAxis("bottom")
+        ax3.setHeight(h=46.2) #workaround for overly long colorbar in linux
+        by3.setWidth(w=60)
+        ax3.setZValue(1000)
+        ax3.setTicks([])
+        ax3.setLabel(text="", units="")
+        by3 = self.cm.getAxis("right")
+        by3.setLabel(text="counts", units="")
+        by3.setStyle(tickLength=8)
+        ay3.setStyle(showValues=False,tickLength=0)
+        bx3.setStyle(showValues=False,tickLength=0)
 
-        vbox3.setContentsMargins(20,20,20,30)
-        sizer3.setLayout(vbox3)
 
+        self.pglayout.layout.setColumnMinimumWidth(1, 80)
+        self.pglayout.layout.setColumnMaximumWidth(1, 80)
 
-        #panel 4
-        sizer4 = QtWidgets.QGroupBox('Path')
-        vbox4 = QtWidgets.QVBoxLayout()
+        self.tc_file.setText('File name')
 
-        self.tc_path = QtWidgets.QLabel(self)
-        vbox4.addWidget(self.tc_path)
         self.tc_path.setText('D:/')
+        self.slider_theta.setVisible(False)
 
-        vbox4.setContentsMargins(20,20,20,30)
-        sizer4.setLayout(vbox4)
-
-
-        #panel 5
-        vbox5 = QtWidgets.QVBoxLayout()
-
-        self.tc_imageeng = QtWidgets.QLabel(self)
-        self.tc_imageeng.setText("Image at energy: ")
-        vbox5.addWidget(self.tc_imageeng)
-
-
-
-        gridsizertop = QtWidgets.QGridLayout()
-
-        frame = QtWidgets.QFrame()
-        frame.setFrameStyle(QtWidgets.QFrame.StyledPanel|QtWidgets.QFrame.Sunken)
-        fbox = QtWidgets.QHBoxLayout()
-
-        self.absimgfig = Figure((PlotH, PlotH))
-
-        self.AbsImagePanel = FigureCanvas(self.absimgfig)
-        self.AbsImagePanel.setParent(self)
-        self.AbsImagePanel.setMinimumSize(300,300)
-
-
-        fbox.addWidget(self.AbsImagePanel)
-        frame.setLayout(fbox)
-        gridsizertop.addWidget(frame, 0, 0, QtCore .Qt. AlignLeft)
-
-
-        self.slider_eng = QtWidgets.QScrollBar(QtCore.Qt.Vertical)
-        self.slider_eng.setFocusPolicy(QtCore.Qt.StrongFocus)
-        self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
-        self.slider_eng.setRange(0, 100)
-
-        gridsizertop.addWidget(self.slider_eng, 0, 1, QtCore .Qt. AlignLeft)
-
+    def Clear(self):
+        self.p1.clear()
 
-        self.slider_theta = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
-        self.slider_theta.setFocusPolicy(QtCore.Qt.StrongFocus)
-        self.slider_theta.valueChanged[int].connect(self.OnScrollTheta)
-        self.slider_theta.setRange(0, 100)
-        self.slider_theta.setVisible(False)
-        self.tc_imagetheta = QtWidgets.QLabel(self)
-        self.tc_imagetheta.setText("4D Data Angle: ")
-        self.tc_imagetheta.setVisible(False)
-        hbox51 = QtWidgets.QHBoxLayout()
-        hbox51.addWidget(self.tc_imagetheta)
-        hbox51.addWidget(self.slider_theta)
-        gridsizertop.addLayout(hbox51, 1, 0)
+    def LoadEntries(self): # Called when fresh data are loaded.
+        self.p1.addItem(self.i_item)
+        self.OnScrollEng(0) # Plot first image & set Scrollbar
+        self.OnMetricScale(self.MetricCheckBox.isChecked(), True, False)
 
+    def keyPressEvent(self, e):
+        if e.key() == 67 and (e.modifiers() & QtCore.Qt.ControlModifier):
+            self.OnCopy()
 
-        vbox5.addLayout(gridsizertop)
-        vbox5.addStretch(1)
+    def OnMetricScale(self, setmetric= True, zeroorigin= True, square= False):
+        if self.com.stack_loaded == 1:
+            if setmetric==True:
+                self.SquarePxCheckBox.setVisible(False)
+                self.ZeroOriginCheckBox.setVisible(True)
+                self.p1.setAspectLocked(lock=True, ratio=1)
+                #self.p2.setAspectLocked(lock=True, ratio=1)
+                if not zeroorigin:
+                    x_start = self.stk.x_start*self.scale
+                    y_start = self.stk.y_start*self.scale
+                else:
+                    x_start = 0
+                    y_start = 0
+                self.ay1.setLabel(text="y", units="m")
+                self.ax1.setLabel(text="x", units="m")
+                #self.ay2.setLabel(text="y", units="m")
+                #self.ax2.setLabel(text="x", units="m")
 
+                self.i_item.setRect(QtCore.QRectF(x_start, y_start, self.scale*self.stk.n_cols*self.stk.x_pxsize, self.scale*self.stk.n_rows*self.stk.y_pxsize))
+                #if hasattr(self, "OD"):
+                #    self.m_item.setRect(QtCore.QRectF(x_start, y_start, self.scale*np.shape(self.OD)[0]*self.stk.x_pxsize, self.scale*np.shape(self.OD)[1]*self.stk.y_pxsize))
+                #    self.setCrosshair()
+            else:
+                self.ZeroOriginCheckBox.setVisible(False)
+                self.SquarePxCheckBox.setVisible(True)
+                if square == True or self.stk.x_pxsize == 0 or self.stk.y_pxsize == 0:
+                    aspect = 1
+                else:
+                    aspect = self.stk.x_pxsize/self.stk.y_pxsize
+                    #print(aspect)
+                self.p1.setAspectLocked(lock=True, ratio=aspect)
+                self.ay1.setLabel(text="y", units="px")
+                self.ax1.setLabel(text="x", units="px")
+                self.i_item.setRect(QtCore.QRectF(0, 0, self.stk.n_cols, self.stk.n_rows))
+# ----------------------------------------------------------------------
+    def OnCatChanged(self):
+        self.CMMapBox.blockSignals(True)
+        self.CMMapBox.clear()
+        self.CMMapBox.blockSignals(False)
+        self.CMMapBox.addItems(self.cmaps[self.CMCatBox.currentIndex()][1])
 
-        vboxtop = QtWidgets.QVBoxLayout()
+    def calcBinSize(self,i,N):
+        return int(round(256*(i+1)/N) - round(256*i/N))
 
-        hboxtop = QtWidgets.QHBoxLayout()
-        vboxt1 = QtWidgets.QVBoxLayout()
-        vboxt1.addStretch (1)
-        vboxt1.addWidget(sizer1)
-        vboxt1.addStretch (1)
-        vboxt1.addWidget(sizer2)
-        vboxt1.addStretch (1)
+    def OnCopy(self):
+        self.exp = pg.exporters.ImageExporter(self.pglayout)
+        self.exp.export(copy=True)
+        return
 
-        hboxtop.addStretch (0.5)
-        hboxtop.addLayout(vboxt1)
-        hboxtop.addStretch (0.5)
-        hboxtop.addLayout(vbox5)
-        hboxtop.addStretch (0.5)
+    def OnMirror(self):
+        if self.com.stack_loaded == 1:
+            if self.com.stack_4d == 1:
+                self.stk.stack4D = np.flip(self.stk.stack4D, axis=0)
+                self.stk.absdata = self.stk.stack4D[:, :, :, self.itheta].copy()
+            else:
+                self.stk.absdata = np.flip(self.stk.absdata, axis=0)
 
-        vboxtop.addStretch (0.5)
-        vboxtop.addLayout(hboxtop)
-        vboxtop.addStretch (0.5)
-        vboxtop.addWidget(sizer3)
-        vboxtop.addStretch (0.5)
-        vboxtop.addWidget(sizer4)
-        vboxtop.addStretch (0.5)
+            if self.com.i0_loaded:
+                if self.com.stack_4d:
+                    self.stk.od4D = np.flip(self.stk.od4D, axis=0)
+                else:
+                    self.stk.od3d = np.flip(self.stk.od3d, axis=0)
+                    self.stk.od = self.stk.od3d.copy()
+                    self.stk.od = np.reshape(self.stk.od, (self.stk.n_rows * self.stk.n_cols, self.stk.n_ev),
+                                           order='F')
 
-        vboxtop.setContentsMargins(50,50,50,50)
-        self.setLayout(vboxtop)
+            self.stk.fill_h5_struct_from_stk()
+            if self.com.i0_loaded == 1:
+                self.stk.fill_h5_struct_normalization()
 
+            self.OnScrollEng(self.iev)
+            # Update/Refresh widgets:
+            if showmaptab:
+                self.window().page9.Clear()
+                self.window().page9.LoadEntries()
+            self.window().page1.loadImage()
+        return
 
+    def OnRotate(self):
+        if self.com.stack_loaded == 1:
+            if self.com.stack_4d == 1:
+                self.stk.stack4D = np.rot90(self.stk.stack4D, 3)
+                self.stk.absdata = self.stk.stack4D[:, :, :, self.itheta].copy()
+            else:
+                self.stk.absdata = np.rot90(self.stk.absdata, 3)
 
-#----------------------------------------------------------------------
-    def initMatplotlib(self):
+            # Swap x/y constants:
+            self.stk.n_cols, self.stk.n_rows = self.stk.n_rows, self.stk.n_cols
+            self.stk.x_pxsize, self.stk.y_pxsize = self.stk.y_pxsize, self.stk.x_pxsize
+            self.stk.x_start, self.stk.y_start = self.stk.y_start, self.stk.x_start
+            self.stk.x_dist, self.stk.y_dist = self.stk.y_dist, self.stk.x_dist
 
+            if self.com.i0_loaded:
+                if self.com.stack_4d:
+                    self.stk.od4D = np.rot90(self.stk.od4D, 3)
+                else:
+                    self.stk.od3d =  np.rot90(self.stk.od3d, 3)
+                    self.stk.od = self.stk.od3d.copy()
+                    self.stk.od = np.reshape(self.stk.od, (self.stk.n_rows * self.stk.n_cols, self.stk.n_ev),
+                                           order='F')
 
-        matplotlib.rcParams['figure.facecolor'] = 'white'
+            self.stk.fill_h5_struct_from_stk()
+            if self.com.i0_loaded == 1:
+                self.stk.fill_h5_struct_normalization()
 
-        matplotlib.rcParams['font.size'] = 10.0
+            # Update/Refresh widgets:
+            self.OnScrollEng(self.iev)
+            self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),self.SquarePxCheckBox.isChecked())
+            if showmaptab:
+                self.window().page9.Clear()
+                self.window().page9.LoadEntries()
+            self.window().page1.ix = int(self.stk.n_cols / 2)
+            self.window().page1.iy = int(self.stk.n_rows / 2)
+            self.window().page1.showSpectrum(self.window().page1.ix, self.window().page1.iy)
+            self.window().page1.loadImage()
+        return
 
+    def OnColormap(self,map="gray", colors=256):
+        if self.com.stack_loaded == 1:
+            colormap = cm.get_cmap(map, colors)
+            colormap = colormap(np.arange(colors))
+            cm_lst = [[colormap[idx][0], colormap[idx][1], colormap[idx][2], colormap[idx][3]] for idx in range(np.shape(colormap)[0])] #convert to r,g,b,a list
+            cm_lst = [item for sub in [[cm_lst[i]]*self.calcBinSize(i,colors) for i in range(colors)] for item in sub] #fills 256 bins as equal as possible with n colors
+            cm_array = np.array([np.asarray(cm_lst)]) #vertical colorbar
+            cm_lst.extend((cm_lst[-1],cm_lst[-1],cm_lst[-1]))
+            lut = np.asarray(cm_lst)
+            lut = (lut * 255).view(np.ndarray)
+            self.cmimg.setImage(cm_array)
+            self.i_item.setLookupTable(lut)
+            self.setODbar(self.ODmin, self.ODmax)
 
+    def setODbar(self,min=None,max=None):
+        self.cm.setRange(xRange=[0,1], yRange=[min,max], update=False, disableAutoRange=True,padding=0)
+        self.cmimg.setRect(QtCore.QRectF(0,min,1,max-min))
 #----------------------------------------------------------------------
     def OnLoadMulti(self, event):
 
@@ -13729,71 +15060,46 @@ class PageLoadData(QtWidgets.QWidget):
 
 #----------------------------------------------------------------------
     def OnScrollEng(self, value):
+        self.slider_eng.setValue(value)
+        #self.MapSelectWidget1.setCurrentRow(value)
         self.iev = value
         if self.com.stack_loaded == 1:
-            self.ShowImage()
-
+            image = self.stk.absdata[:, :, int(self.iev)].copy()
+            if self.com.stack_4d == 1:
+                self.p1.setTitle("<center>Image at {0:5.2f} eV and {1:5.1f}°</center>".format(float(self.stk.ev[self.iev]),
+                                                                             float(self.stk.theta[self.itheta])))
+            else:
+                self.p1.setTitle("<center>Image at energy {0:5.2f} eV</center>".format(float(self.stk.ev[self.iev])))
+            self.ODmin = np.min(image)
+            self.ODmax = np.max(image)
+            self.i_item.setImage(image)
+            if np.isfinite(self.ODmin) or np.isfinite(self.ODmax): #incomplete stacks can contain NAN values that mess up the function on the next line
+                self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value())
 #----------------------------------------------------------------------
     def OnScrollTheta(self, value):
+        self.slider_theta.setValue(value)
         self.itheta = value
 
-        self.stk.absdata = self.stk.stack4D[:,:,:,self.itheta]
-        self.tc_imagetheta.setText("4D Data Angle: "+str(self.stk.theta[self.itheta]))
+        self.stk.absdata = self.stk.stack4D[:,:,:,self.itheta].copy()
+        image = self.stk.absdata[:, :, int(self.slider_eng.value())].copy()
+        #self.tc_imagetheta.setText("4D Data Angle: "+str(self.stk.theta[self.itheta]))
 
         if self.com.stack_loaded == 1:
-            self.ShowImage()
-
-        self.window().page1.itheta = self.itheta
-        self.window().page1.slider_theta.setValue(self.itheta)
-
-        self.window().page2.itheta = self.itheta
-        self.window().page2.slider_theta.setValue(self.itheta)
-
-
-#----------------------------------------------------------------------
-    def ShowImage(self):
-
-
-        image = self.stk.absdata[:,:,int(self.iev)].copy()
-
-        fig = self.absimgfig
-        fig.clf()
-        fig.add_axes(((0.0,0.0,1.0,1.0)))
-        axes = fig.gca()
-        fig.patch.set_alpha(1.0)
-
-        im = axes.imshow(np.rot90( image ), cmap=matplotlib.cm.get_cmap("gray"))
-
-        if self.window().page1.show_scale_bar == 1:
-            #Show Scale Bar
-            if self.com.white_scale_bar == 1:
-                sbcolor = 'white'
-            else:
-                sbcolor = 'black'
-            startx = int(self.stk.n_cols*0.05)
-            starty = self.stk.n_rows-int(self.stk.n_rows*0.05)-self.stk.scale_bar_pixels_y
-            um_string = ' $\mathrm{\mu m}$'
-            microns = '$'+self.stk.scale_bar_string+' $'+um_string
-            axes.text(self.stk.scale_bar_pixels_x+startx+1,starty+1, microns, horizontalalignment='left', verticalalignment='center',
-                      color = sbcolor, fontsize=14)
-            #Matplotlib has flipped scales so I'm using rows instead of cols!
-            p = matplotlib.patches.Rectangle((startx,starty), self.stk.scale_bar_pixels_x, self.stk.scale_bar_pixels_y,
-                                   color = sbcolor, fill = True)
-            axes.add_patch(p)
-
-
-        axes.axis("off")
-        self.AbsImagePanel.draw()
-
-        self.tc_imageeng.setText('Image at energy: {0:5.2f} eV'.format(float(self.stk.ev[self.iev])))
-
+            self.p1.setTitle("<center>Image at {0:5.2f} eV and {1:5.1f}°</center>".format(float(self.stk.ev[self.iev]),
+                                                                         float(self.stk.theta[self.itheta])))
+            self.ODmin = np.min(image)
+            self.ODmax = np.max(image)
+            self.i_item.setImage(image)
+            self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value())
+        #self.window().page1.itheta = self.itheta
+        #self.window().page1.slider_theta.setValue(self.itheta)
 
+        #self.window().page2.itheta = self.itheta
+        #self.window().page2.slider_theta.setValue(self.itheta)
 
 #----------------------------------------------------------------------
     def ShowInfo(self, filename, filepath):
 
-        self.ShowImage()
-
         self.tc_file.setText(filename)
         self.tc_path.setText(filepath)
 
@@ -13805,31 +15111,13 @@ class PageMap(QtWidgets.QWidget):
         dir_path = os.path.dirname(os.path.realpath(__file__))
         uic.loadUi(os.path.join(dir_path,'pagemap.ui'), self)
         self.show()
-        # self.setStyleSheet(""" QListWidget:item:selected:active {
-        #                                      color:rgb(255, 255, 255);
-        #                                      background: rgb(0, 170, 255);
-        #                                 }
-        #                                 QListWidget:item:selected:!active {
-        #                                      color:rgb(255, 255, 255);
-        #                                      background: rgb(0, 170, 255);
-        #                                 }
-        #                                 QListWidget:item:selected:disabled {
-        #                                      color:rgb(255, 255, 255);
-        #                                      background: rgb(0, 170, 255);
-        #                                 }
-        #                                 QListWidget:item:selected:!disabled {
-        #                                      color:rgb(255, 255, 255);
-        #                                      background: rgb(0, 170, 255);
-        #                                 }
-        #                                 """
-        #                   )
         self.cmaps = [('Perceptually Uniform Sequential', [
             'viridis', 'plasma', 'inferno', 'magma']),
                       ('Sequential', [
                           'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
                           'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
                           'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']),
-                      ('Sequential (2)', [
+                                            ('Sequential (2)', [
                           'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
                           'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
                           'hot', 'afmhot', 'gist_heat', 'copper']),
@@ -13851,8 +15139,6 @@ class PageMap(QtWidgets.QWidget):
         self.xoffset = 0
         self.yoffset = 0
         self.scale = 0.000001
-        self.prelst = []
-        self.postlst =[]
         self.pbRST.clicked.connect(lambda: self.setShifts(0, 0))
         self.pbL.clicked.connect(lambda: self.setShifts(-0.2,0))
         self.pbR.clicked.connect(lambda: self.setShifts(0.2,0))
@@ -13873,6 +15159,7 @@ class PageMap(QtWidgets.QWidget):
 
         self.pbExpData.clicked.connect(self.OnSaveData)
         self.pbExpImg.clicked.connect(self.OnSaveImage)
+        self.pbCopy.clicked.connect(self.OnCopy)
 
         self.MetricCheckBox.toggled.connect(lambda: self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),self.SquarePxCheckBox.isChecked()))
         self.ZeroOriginCheckBox.toggled.connect(lambda: self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),self.SquarePxCheckBox.isChecked()))
@@ -13880,7 +15167,7 @@ class PageMap(QtWidgets.QWidget):
         self.SquarePxCheckBox.setVisible(False)
         self.CropCheckBox.toggled.connect(lambda: self.OnCropCB(self.CropCheckBox.isChecked()))
         self.cropflag = True
-        self.ShiftLabel.setText("x = %0.1f \ny = %0.1f" % (0, 0))
+        #self.ShiftLabel.setText("x = %0.1f \ny = %0.1f" % (0, 0))
         self.ODHighSpinBox.valueChanged.connect(lambda: self.setODlimits(self.ODLowSpinBox.value(),self.ODHighSpinBox.value()))
         self.ODLowSpinBox.valueChanged.connect(lambda: self.setODlimits(self.ODLowSpinBox.value(),self.ODHighSpinBox.value()))
         self.pbRSTOD.clicked.connect(lambda: self.ShowMap(self.prelst, self.postlst))
@@ -13894,12 +15181,10 @@ class PageMap(QtWidgets.QWidget):
         self.CMCatBox.currentIndexChanged.connect(self.OnCatChanged)
         self.CMMapBox.currentIndexChanged.connect(lambda: self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value()))
         self.StepSpin.valueChanged.connect(lambda: self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value()))
-
-        self.MapSelectWidget1.itemSelectionChanged.connect(self.OnFocusChanged)
+        self.filterSpinBox.valueChanged.connect(lambda: self.ShowMap(self.prelst, self.postlst))
+        self.filterSpinBox.setEnabled(False)
         self.MapSelectWidget1.mousePressEvent = self.mouseEventOnQList
         self.MapSelectWidget1.mouseMoveEvent = self.mouseEventOnQList
-        self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
-        self.qlistchanged.connect(self.qListChangeHandler)
         self.data_struct = data_struct
         self.stk = stack
         self.com = common
@@ -13907,10 +15192,10 @@ class PageMap(QtWidgets.QWidget):
         self.latest_row = -1
 
         self.pglayout = pg.GraphicsLayout(border=None)
-        self.canvas.setBackground("0000") # canvas is a pg.GraphicsView widget
+        self.canvas.setBackground("w") # canvas is a pg.GraphicsView widget
         self.canvas.setCentralWidget(self.pglayout)
-
-        self.p1 = self.pglayout.addPlot(row=1, col=1, rowspan=1, colspan=1)
+        #self.pglayout.addItem(pg.AxisItem('left',vPolicy =QtWidgets.QSizePolicy.Maximum), row=1, col=0, rowspan=1, colspan=3)
+        self.p1 = self.pglayout.addPlot(row=0, col=0, rowspan=1, colspan=1)
         self.p1.setMouseEnabled(x=False, y=False)
         self.i_item = pg.ImageItem(border="k")
         self.p1.setAspectLocked(lock=True, ratio=1)
@@ -13931,7 +15216,7 @@ class PageMap(QtWidgets.QWidget):
         by1.setStyle(showValues=False,tickLength=0)
         bx1.setStyle(showValues=False,tickLength=0)
 
-        self.p2 = self.pglayout.addPlot(row=2, col=1, rowspan=1, colspan=1)
+        self.p2 = self.pglayout.addPlot(row=0, col=1, rowspan=1, colspan=1)
         self.p2.setMouseEnabled(x=False, y=False)
         self.m_item = pg.ImageItem(border="k")
         self.m_item.setZValue(1000)
@@ -13949,20 +15234,23 @@ class PageMap(QtWidgets.QWidget):
         bx2 = self.p2.getAxis("top")
         bx2.setZValue(1000)
         self.ay2.setLabel(text="y",units="px")
-        self.ay2.enableAutoSIPrefix(enable=True)
+        self.si_prefix = self.ay2.enableAutoSIPrefix(enable=True)
         self.ax2.setLabel(text="x",units="px")
         self.ax2.enableAutoSIPrefix(enable=True)
         self.ay2.setStyle(tickLength=8)
         self.ax2.setStyle(tickLength=8)
         by2.setStyle(showValues=False,tickLength=0)
         bx2.setStyle(showValues=False,tickLength=0)
-        self.p1.setTitle("No images loaded")
-        self.p2.setTitle("No map available")
-        # self.p1.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Expanding)
-        # self.p2.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Expanding)
+        self.p1.setTitle("")
+        self.p1.titleLabel.setText("<center>No images loaded</center>", size='10pt')
+
 
+        self.p2.setTitle("")
+        self.p2.titleLabel.setText("<center>No map available</center>", size='10pt')
+        #self.p1.titleLabel.item.setTextWidth(self.p1.width() * 0.7)
+        #self.p2.titleLabel.item.setTextWidth(self.p2.width() * 0.7)
         self.cmimg = pg.ImageItem(border=None)
-        self.cm = self.pglayout.addPlot(row=2, col=2, rowspan=1, colspan=1)
+        self.cm = self.pglayout.addPlot(row=0, col=2, rowspan=1, colspan=1)
         self.cm.addItem(self.cmimg)
         self.cm.setMouseEnabled(x=False, y=False)
         self.cm.getViewBox().autoRange(padding=0)
@@ -13971,6 +15259,7 @@ class PageMap(QtWidgets.QWidget):
         self.cm.showAxis("left", show=True)
         self.cm.showAxis("right", show=True)
         self.cm.setTitle("")
+        self.cm.titleLabel.setText("", size='10pt')
         ay3 = self.cm.getAxis("left")
         ay3.setZValue(1000)
         by3 = self.cm.getAxis("right")
@@ -13985,12 +15274,18 @@ class PageMap(QtWidgets.QWidget):
         by3 = self.cm.getAxis("right")
         by3.setLabel(text="OD", units="")
         by3.setStyle(tickLength=8)
+        #by3.textWidth()
         ay3.setStyle(showValues=False,tickLength=0)
         bx3.setStyle(showValues=False,tickLength=0)
-
+        ax3.setHeight(h=46.2)  # workaround for overly long colorbar
+        by3.setWidth(w=60)
         self.pglayout.layout.setColumnMinimumWidth(2, 80)
         self.pglayout.layout.setColumnMaximumWidth(2, 80)
-
+        #self.pglayout.layout.setColumnMinimumWidth(1, int((self.p1.width() + self.p2.width()) / 2))
+        #self.pglayout.layout.setColumnMinimumWidth(0, int((self.p1.width() + self.p2.width()) / 2))
+        self.p1.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
+        self.p2.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
+        self.cm.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
     def mouseEventOnQList(self, e):
         if e.type() == QtCore.QEvent.MouseMove or e.type() == QtCore.QEvent.MouseButtonPress:
             qlist = self.MapSelectWidget1
@@ -14027,14 +15322,10 @@ class PageMap(QtWidgets.QWidget):
             self.stk.shifts[row][1] = -1
         self.OnSelectionChanged()
         #print(row, params)
-    def OnFocusChanged(self):
-        self.OnScrollEng(self.MapSelectWidget1.currentRow())
-        #print("FocusChanged!")
     def OnSelectionChanged(self):
-        #print("SelectionChanged!",self.stk.shifts)
         self.prelst = [index for index, value in enumerate([x[1] for x in  self.stk.shifts]) if value == -1]
         self.postlst = [index for index, value in enumerate([x[1] for x in  self.stk.shifts]) if value == 1]
-        #print(prelst,postlst)
+        #print(self.prelst,self.postlst)
         self.OnScrollEng(self.MapSelectWidget1.currentRow())
         if len(self.prelst) == 0 or len(self.postlst) == 0:
             if len(self.prelst + self.postlst) == 0:
@@ -14042,17 +15333,19 @@ class PageMap(QtWidgets.QWidget):
             else:
                 self.pbClrSel.setEnabled(True)
             self.p2.clear()
-            #print("Select at least one pre- and post-edge image!")
-            self.p2.setTitle("Select at least one pre- and post-edge image!")
+            self.cm.clear()
+            self.p2.titleLabel.setText("<center>Select at least one pre- and post-edge image!</center>",size='10pt')
+
             self.ODHighSpinBox.setEnabled(False)
             self.ODLowSpinBox.setEnabled(False)
             self.pbRSTOD.setEnabled(False)
+            self.filterSpinBox.setEnabled(False)
             self.pbExpData.setEnabled(False)
             self.pbExpImg.setEnabled(False)
 
         else:
             self.pbClrSel.setEnabled(True)
-            self.InfWarning = False
+            #self.InfWarning = False
             self.ShowMap(self.prelst,self.postlst)
             # self.OnScrollEng(self.MapSelectWidget1.currentRow())
             self.OnMetricScale(self.MetricCheckBox.isChecked(), self.ZeroOriginCheckBox.isChecked(),
@@ -14085,6 +15378,10 @@ class PageMap(QtWidgets.QWidget):
             img1.save(fileName)
         if ext == 'txt':
             np.savetxt(fileName, np.rot90(self.OD), delimiter='\t', newline='\n',fmt='%.5f')
+    def OnCopy(self):
+        self.exp = pg.exporters.ImageExporter(self.pglayout)
+        self.exp.export(copy=True)
+        return
     def OnSaveImage(self, event):
         # Save Image
         wildcard = "TIFF (*.tif);;PNG (*.png);;JPG (*.jpg);;SVG (*.svg);;"
@@ -14125,6 +15422,8 @@ class PageMap(QtWidgets.QWidget):
             painter.drawImage(0, 0, p2exp)
             painter.drawImage(p2exp.size().width() + padding, 0, cmexp)
             painter.end()
+            #pixmap = QPixmap.fromImage(tile)
+            #QCoreApplication.instance().clipboard().setImage(qimg)
             qimg.save(fileName,quality=100)
         elif ext == 'svg':
             fig1 = self.SVGClipPathRemover(etree.fromstring(p2exp))
@@ -14162,11 +15461,13 @@ class PageMap(QtWidgets.QWidget):
         except:
             pass
         return elem
+
     def OnCatChanged(self):
-        self.CMMapBox.currentIndexChanged.disconnect()
+        self.CMMapBox.blockSignals(True)
         self.CMMapBox.clear()
-        self.CMMapBox.currentIndexChanged.connect(lambda: self.OnColormap(map=self.CMMapBox.currentText(),colors=self.StepSpin.value()))
+        self.CMMapBox.blockSignals(False)
         self.CMMapBox.addItems(self.cmaps[self.CMCatBox.currentIndex()][1])
+
     def setODlimits(self,low, high):
         self.ODHighSpinBox.setMaximum(self.ODmax)
         self.ODHighSpinBox.setMinimum(low)
@@ -14220,12 +15521,12 @@ class PageMap(QtWidgets.QWidget):
                     x = (xi - 0.5 + x_off) * self.scale * self.stk.x_pxsize
                     y = (yi - 0.5 + y_off) * self.scale * self.stk.y_pxsize
                     pt = QtCore.QPointF(x,y)
-                    self.ODlabel.setText("<span style='font-size: 8pt; color: red'> x = %0.3f  µm, <span style='color: red'> y = %0.3f µm</span>, <span style='color: red'> OD = %0.2f</span>" % (x/self.scale - 0.5 * self.stk.x_pxsize, y/self.scale - 0.5 * self.stk.y_pxsize, self.OD[xi-1-int(x_min),yi-1-int(y_min)]))
+                    self.ODlabel.setText("<span style='font-size: 10pt; color: red'> x = %0.3f  µm, <span style='color: red'> y = %0.3f µm</span>, <span style='color: red'> OD = %0.2f</span>" % (x/self.scale - 0.5 * self.stk.x_pxsize, y/self.scale - 0.5 * self.stk.y_pxsize, self.OD[xi-1-int(x_min),yi-1-int(y_min)]))
                 else:
                     x = int(mousePoint.x()) + 0.5
                     y = int(mousePoint.y()) + 0.5
                     pt = QtCore.QPointF(x,y)
-                    self.ODlabel.setText("<span style='font-size: 8pt; color: red'> x = %0.0f, <span style='color: red'> y = %0.0f</span>, <span style='color: red'> OD = %0.2f</span>" % (x, y,self.OD[int(x),int(y)]))
+                    self.ODlabel.setText("<span style='font-size: 10pt; color: red'> x = %0.0f, <span style='color: red'> y = %0.0f</span>, <span style='color: red'> OD = %0.2f</span>" % (x, y,self.OD[int(x),int(y)]))
                 #print(x,y)
                 self.vLine.setPos(x)
                 self.hLine.setPos(y)
@@ -14251,6 +15552,8 @@ class PageMap(QtWidgets.QWidget):
             noshift = False
         else:
             noshift = True
+        if e.key() == 67 and (e.modifiers() & QtCore.Qt.ControlModifier):
+            self.OnCopy()
         if e.key() == Qt.Key_Up or (e.key() == QtCore.Qt.Key_8):
             if noshift:
                 self.pbUU.click()
@@ -14295,42 +15598,61 @@ class PageMap(QtWidgets.QWidget):
                 self.pbRST.click()
 
     def Clear(self):
-        self.MapSelectWidget1.itemSelectionChanged.disconnect()
+        try:
+            self.slider_eng.valueChanged.disconnect()
+            self.qlistchanged.disconnect()
+        except:
+            pass
+        self.prelst = []
+        self.postlst =[]
+        self.stk.shifts = []
+        self.stk.absdata_shifted= []
         self.p1.clear()
         self.p2.clear()
+        self.cm.clear()
         self.MapSelectWidget1.clear()
 
     def LoadEntries(self): # Called when fresh data are loaded.
         self.ODHighSpinBox.setEnabled(False)
         self.ODLowSpinBox.setEnabled(False)
         self.pbRSTOD.setEnabled(False)
+        self.filterSpinBox.setEnabled(False)
         self.pbExpData.setEnabled(False)
         self.pbExpImg.setEnabled(False)
         self.pbClrSel.setEnabled(False)
-        self.stk.shifts = []
         self.stk.absdata_shifted = self.stk.absdata.copy()
         self.p1.addItem(self.i_item)
         for i,e in enumerate(self.stk.ev): # Fill QList with energies
             self.stk.shifts.append([1,0,(0.0,0.0)]) #checked [0,1]; pre, post, undefined state for map [-1,1,0],(xshift [float],yshift [float])
-            item = QtGui.QListWidgetItem(str(int(i)).zfill(3)+"     at     " + format(e, '.2f') + " eV     "+"+0.0"+"    +0.0")
+            item = QtWidgets.QListWidgetItem(str(int(i)).zfill(3)+"     at     " + format(e, '.2f') + " eV     "+"+0.0"+"    +0.0")
             self.MapSelectWidget1.addItem(item)
+        self.slider_eng.valueChanged[int].connect(self.OnScrollEng)
+        self.qlistchanged.connect(self.qListChangeHandler)
         self.OnScrollEng(0) # Plot first image & set Scrollbar
-        self.MapSelectWidget1.itemSelectionChanged.connect(self.OnFocusChanged)
         self.OnMetricScale(self.MetricCheckBox.isChecked(), True, False)
+        self.pbSelfromSpec.setEnabled(True)
+        self.pbSelfromSpec.clicked.connect(self.OnSelfromSpec)
     def UpdateEntry(self,row):
         self.MapSelectWidget1.item(row).setText(str(int(row)).zfill(3)+"     at     " + format(self.stk.ev[row], '.2f') + " eV     "+format(self.stk.shifts[row][2][0], '+.1f')+"    "+format(self.stk.shifts[row][2][1], '+.1f'))
         #self.MapSelectWidget1.addItem(self.MapSelectWidget1.item(row))
         self.i_item.setImage(self.Shift(row))
+    def ResetAllItems(self,widget):
+        for i in range(widget.count()):
+            widget.item(i).setForeground(QtGui.QColor(0, 0, 0, 128))
     def OnScrollEng(self, value):
+        self.slider_eng.blockSignals(True)
         self.slider_eng.setValue(value)
+        self.slider_eng.blockSignals(False)
         self.MapSelectWidget1.setCurrentRow(value)
+        self.ResetAllItems(self.MapSelectWidget1)
         self.iev = value
+        self.p1.titleLabel.item.setTextWidth(self.p1.width() * 0.7)
+        self.p2.titleLabel.item.setTextWidth(self.p2.width() * 0.7)
+        #self.canvas.resizeEvent(None)
         if self.com.stack_loaded == 1:
-            # if hasattr(self, "data")
-            # im = self.stk.absdata_shifted[:, :, int(self.iev)]#.copy()
-            # self.data = im
-            self.p1.setTitle("Image at energy {0:5.2f} eV".format(float(self.stk.ev[self.iev])))
+            self.p1.titleLabel.setText("<center>Image at energy {0:5.2f} eV</center>".format(float(self.stk.ev[self.iev])),size='10pt')
             self.i_item.setImage(self.Shift(int(self.iev)))
+            self.MapSelectWidget1.item(value).setForeground(QtGui.QColor(0, 0, 0, 255))
 
     def OnCropCB(self, value=True):
         if self.com.stack_loaded == 1:
@@ -14386,6 +15708,10 @@ class PageMap(QtWidgets.QWidget):
             self.stk.shifts[row][1] = 0
             self.OnSelectionChanged()
 
+    def OnSelfromSpec(self,evt):
+        spectralimgmap = SpectralImageMap(self, self.com, self.stk)
+        spectralimgmap.show()
+
     def OnClrShifts(self):
         for row in [index for index, value in enumerate([x[2] for x in  self.stk.shifts]) if value != (0.0,0.0)]:
             self.stk.shifts[row].pop(2)  # remove tuple
@@ -14468,9 +15794,9 @@ class PageMap(QtWidgets.QWidget):
         inf_idx = np.where(np.isinf(OD))
         nan_idx = np.where(np.isnan(OD))
         if np.any(inf_idx) or np.any(nan_idx):
-            if not self.InfWarning:
-                self.InfWarning = True
-                QtGui.QMessageBox.warning(self, 'Warning!', "The OD map contained infinite or nan values. Please note that they have been zeroed.")
+            #if not self.InfWarning:
+            #    self.InfWarning = True
+            #    QtGui.QMessageBox.warning(self, 'Warning!', "The OD map contained infinite or nan values. Please note that they have been zeroed.")
             OD[inf_idx] = 0 #infinite values get replaced by zero. This is an ugly work around, but with nans the image is not displayed correctly.
             OD[nan_idx] = 0
         return OD
@@ -14496,27 +15822,34 @@ class PageMap(QtWidgets.QWidget):
     def ShowMap(self, preidx, postidx):
         self.p2.clear()
         self.p2.addItem(self.m_item)
+        self.cm.clear()
+        self.cm.addItem(self.cmimg)
         self.setCrosshair()
         try:
             ## Optional sorting switched off for convenience. Allows maps to range to negative OD
             #selection = preidx + postidx
             # selection.sort()
             if len(preidx + postidx) == 2:
-                self.p2.setTitle("Binary map from energies " + str(round(self.stk.ev[preidx[0]], 2)) + " and " + str(
-                round(self.stk.ev[postidx[0]], 2)) + " eV")
+                self.p2.titleLabel.setText("<center>Binary map from energies " + str(round(self.stk.ev[preidx[0]], 2)) + " and " + str(
+                round(self.stk.ev[postidx[0]], 2)) + " eV</center>",
+                                           size='10pt')
             elif len(preidx + postidx) <= 6:
-                self.p2.setTitle("Map from energies " + str([round(self.stk.ev[e], 2) for e in preidx]).strip('[]') + " and " +
-                                 str([round(self.stk.ev[e], 2) for e in postidx]).strip('[]') + " eV")
+                self.p2.titleLabel.setText("<center>Map from energies " + str([round(self.stk.ev[e], 2) for e in preidx]).strip('[]') + " and " +
+                                 str([round(self.stk.ev[e], 2) for e in postidx]).strip('[]') + " eV</center>",
+                                           size='10pt')
             else:
-                self.p2.setTitle("Map from "+ str(len(preidx + postidx)) +" energies: " + str(round(self.stk.ev[preidx[0]], 2)) + ' ... ' + str(round(self.stk.ev[preidx[-1]], 2)) + " and "
-                                 + str(round(self.stk.ev[postidx[0]], 2)) + ' ... ' + str(round(self.stk.ev[postidx[-1]], 2)) + " eV")
+                self.p2.titleLabel.setText("<center>Map from "+ str(len(preidx + postidx)) +" energies: " + str(round(self.stk.ev[preidx[0]], 2)) + ' ... ' + str(round(self.stk.ev[preidx[-1]], 2)) + " and "
+                                 + str(round(self.stk.ev[postidx[0]], 2)) + ' ... ' + str(round(self.stk.ev[postidx[-1]], 2)) + " eV</center>",
+                                           size='10pt')
             self.OD = self.CalcODMap(preidx, postidx)
+            if self.filterSpinBox.value() > 1:
+                self.OD = ndimage.filters.uniform_filter(self.OD, size=self.filterSpinBox.value(), mode='nearest')
             self.ODmin = np.min(self.OD)
             self.ODmax = np.max(self.OD)
             self.ODHighSpinBox.setEnabled(True)
             self.ODLowSpinBox.setEnabled(True)
-            self.ODHighSpinBox.valueChanged.disconnect()
-            self.ODLowSpinBox.valueChanged.disconnect()
+            self.ODHighSpinBox.blockSignals(True)
+            self.ODLowSpinBox.blockSignals(True)
             self.ODHighSpinBox.setMaximum(self.ODmax)
             self.ODHighSpinBox.setMinimum(self.ODmin)
             self.ODLowSpinBox.setMaximum(self.ODmax)
@@ -14524,15 +15857,16 @@ class PageMap(QtWidgets.QWidget):
             self.ODLowSpinBox.setValue(self.ODmin)
             self.ODHighSpinBox.setValue(self.ODmax)
             self.setODlimits(self.ODmin, self.ODmax)
-            self.ODHighSpinBox.valueChanged.connect(
-                lambda: self.setODlimits(self.ODLowSpinBox.value(), self.ODHighSpinBox.value()))
-            self.ODLowSpinBox.valueChanged.connect(
-                lambda: self.setODlimits(self.ODLowSpinBox.value(), self.ODHighSpinBox.value()))
+            self.ODHighSpinBox.blockSignals(False)
+            self.ODLowSpinBox.blockSignals(False)
             self.pbRSTOD.setEnabled(True)
+            self.filterSpinBox.setEnabled(True)
             self.pbExpData.setEnabled(True)
             self.pbExpImg.setEnabled(True)
+            #self.pglayout.layout.setColumnMaximumWidth(1, self.p1.width())
         except IndexError:
             self.p2.clear()
+            self.cm.clear()
             #self.p2.setTitle("Please select a second image!")
             #print("Select a second image!")
 
@@ -14824,14 +16158,14 @@ class StackListFrame(QtWidgets.QDialog):
         self.parent.page1.textctrl.setText(filelist[0])
 
         self.parent.page0.slider_eng.setRange(0,self.stk.n_ev-1)
-        self.parent.page0.iev = self.stk.n_ev/2
+        self.parent.page0.iev = int(self.stk.n_ev/2)
         self.parent.page0.slider_eng.setValue(self.parent.page1.iev)
 
         self.parent.page1.slider_eng.setRange(0,self.stk.n_ev-1)
         self.parent.page1.iev = self.stk.n_ev/2
         self.parent.page1.slider_eng.setValue(self.parent.page1.iev)
 
-        self.parent.page1.loadSpectrum(self.parent.page1.ix, self.parent.page1.iy)
+        self.parent.page1.showSpectrum(self.parent.page1.ix, self.parent.page1.iy)
         self.parent.page1.loadImage()
 
         self.parent.page0.ShowInfo(filelist[0], self.filepath)
@@ -15034,7 +16368,7 @@ class MainFrame(QtWidgets.QMainWindow):
         if sys.platform == 'win32':
             tabs.setMinimumHeight(750)
         else:
-            tabs.setMinimumHeight(850)
+            tabs.setMinimumHeight(400)
 
         tabs.tabBar().setTabTextColor(0, QtGui.QColor('green'))
         tabs.tabBar().setTabTextColor(1, QtGui.QColor('green'))
@@ -15181,8 +16515,9 @@ class MainFrame(QtWidgets.QMainWindow):
             self.page1.slider_eng.setRange(0,self.stk.n_ev-1)
             self.page1.iev = self.iev
             self.page1.slider_eng.setValue(self.iev)
-
-            self.page9.slider_eng.setRange(0,self.stk.n_ev-1)
+            if showmaptab:
+                self.page9.Clear()
+                self.page9.slider_eng.setRange(0,self.stk.n_ev-1)
             self.stk.scale_bar()
             self.common.stack_loaded = 1
             self.common.path = directory
@@ -15195,10 +16530,13 @@ class MainFrame(QtWidgets.QMainWindow):
 
             self.page1.ResetDisplaySettings()
             self.page1.loadImage()
+            self.page1.button_multicrop.setText('Crop stack 3D...')
             #print (x,y), (self.ix,self.iy), self.stk.absdata.shape
-            self.page1.loadSpectrum(self.ix, self.iy)
+            self.page1.showSpectrum(self.ix, self.iy)
             self.page1.textctrl.setText(self.page1.filename)
 
+            self.page0.Clear()
+            self.page0.LoadEntries()
             self.page0.ShowInfo(self.page1.filename, directory)
 
             self.page5.updatewidgets()
@@ -15293,7 +16631,8 @@ class MainFrame(QtWidgets.QMainWindow):
 
 
             #Update widgets
-
+            if not hasattr(self.stk, 'theta') or type(self.stk.theta) == int:
+                raise TypeError("Not a 4D stack")
             self.common.stack_4d = 1
 
             x=self.stk.n_cols
@@ -15318,12 +16657,12 @@ class MainFrame(QtWidgets.QMainWindow):
             self.page1.slider_eng.setValue(self.iev)
 
             self.page0.slider_theta.setVisible(True)
-            self.page0.tc_imagetheta.setVisible(True)
+            #self.page0.tc_imagetheta.setVisible(True)
             self.itheta = 0
             self.page0.slider_theta.setRange(0,self.stk.n_theta-1)
             self.page0.itheta = self.itheta
             self.page0.slider_theta.setValue(self.itheta)
-            self.page0.tc_imagetheta.setText("4D Data Angle: "+str(self.stk.theta[self.itheta]))
+            #self.page0.tc_imagetheta.setText("4D Data Angle: "+str(self.stk.theta[self.itheta]))
 
 
             self.page1.slider_theta.setVisible(True)
@@ -15331,9 +16670,9 @@ class MainFrame(QtWidgets.QMainWindow):
             self.page1.slider_theta.setRange(0,self.stk.n_theta-1)
             self.page1.itheta = self.itheta
             self.page1.slider_theta.setValue(self.itheta)
+            self.page1.button_multicrop.setText('Crop stack 4D...')
             self.page1.tc_imagetheta.setText("4D Data Angle: "+str(self.stk.theta[self.itheta]))
 
-
             self.page2.button_calcpca4D.setVisible(True)
             self.page4.button_calc4d.setVisible(True)
 
@@ -15346,21 +16685,26 @@ class MainFrame(QtWidgets.QMainWindow):
 
             self.page1.ResetDisplaySettings()
             self.page1.loadImage()
-            self.page1.loadSpectrum(self.ix, self.iy)
+            self.page1.showSpectrum(self.ix, self.iy)
             self.page1.textctrl.setText(self.page1.filename)
 
+            self.page0.Clear()
+            self.page0.LoadEntries()
             self.page0.ShowInfo(self.page1.filename, directory)
 
             self.page5.updatewidgets()
 
             QtWidgets.QApplication.restoreOverrideCursor()
 
+            if showmaptab:
+                self.page9.Clear()
+                self.page9.LoadEntries()
         except:
 
             self.common.stack_loaded = 0
             self.common.i0_loaded = 0
             self.new_stack_refresh()
-
+            self.page1.button_multicrop.setText('Crop stack 3D/4D...')
             QtWidgets.QApplication.restoreOverrideCursor()
             QtGui.QMessageBox.warning(self, 'Error', 'Image stack not loaded.')
 
@@ -15461,10 +16805,12 @@ class MainFrame(QtWidgets.QMainWindow):
         if self.common.stack_loaded == 0:
             self.page1.button_i0ffile.setEnabled(False)
             self.page1.button_i0histogram.setEnabled(False)
+            self.page1.button_artefacts.setEnabled(False)
             self.page1.button_prenorm.setEnabled(False)
             self.page1.button_refimgs.setEnabled(False)
-            self.page1.button_limitev.setEnabled(False)
-            self.page1.button_subregion.setEnabled(False)
+            self.page1.button_multicrop.setEnabled(False)
+            #self.page1.button_limitev.setEnabled(False)
+            #self.page1.button_subregion.setEnabled(False)
             self.page1.button_darksig.setEnabled(False)
             self.page1.button_save.setEnabled(False)
             self.page1.button_savestack.setEnabled(False)
@@ -15480,15 +16826,17 @@ class MainFrame(QtWidgets.QMainWindow):
         else:
             self.page1.button_i0ffile.setEnabled(True)
             self.page1.button_i0histogram.setEnabled(True)
+            self.page1.button_artefacts.setEnabled(True)
             self.page1.button_prenorm.setEnabled(True)
-            self.page1.button_limitev.setEnabled(True)
+            self.page1.button_multicrop.setEnabled(True)
+            #self.page1.button_limitev.setEnabled(True)
             if self.common.stack_4d == 0:
                 self.page1.button_refimgs.setEnabled(True)
-                self.page1.button_subregion.setEnabled(True)
+                #self.page1.button_subregion.setEnabled(True)
                 self.page1.button_darksig.setEnabled(True)
             else:
                 self.page1.button_refimgs.setEnabled(False)
-                self.page1.button_subregion.setEnabled(False)
+                #self.page1.button_subregion.setEnabled(False)
                 self.page1.button_darksig.setEnabled(False)
             self.page1.button_save.setEnabled(True)
             self.page1.button_savestack.setEnabled(True)
@@ -15628,7 +16976,7 @@ class MainFrame(QtWidgets.QMainWindow):
 
         #page 0
         self.page0.slider_theta.setVisible(False)
-        self.page0.tc_imagetheta.setVisible(False)
+        #self.page0.tc_imagetheta.setVisible(False)
 
         #page 1
         self.page1.rb_flux.setChecked(True)
@@ -15735,6 +17083,9 @@ class MainFrame(QtWidgets.QMainWindow):
 def main():
 
     app = QtWidgets.QApplication(sys.argv)
+    #print('main', threading.get_ident())
+    with open(qsspath, "r") as stylesheet:
+        app.setStyleSheet(stylesheet.read())
     frame = MainFrame()
     sys.exit(app.exec_())
 
diff --git a/mantis_xray/pageloaddata.ui b/mantis_xray/pageloaddata.ui
new file mode 100755
index 0000000..eff5ab2
--- /dev/null
+++ b/mantis_xray/pageloaddata.ui
@@ -0,0 +1,891 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>900</width>
+    <height>750</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <property name="spacing">
+      <number>12</number>
+     </property>
+     <property name="topMargin">
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QFrame" name="verticalFrame">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <property name="spacing">
+         <number>12</number>
+        </property>
+        <property name="sizeConstraint">
+         <enum>QLayout::SetDefaultConstraint</enum>
+        </property>
+        <property name="topMargin">
+         <number>1</number>
+        </property>
+        <property name="rightMargin">
+         <number>1</number>
+        </property>
+        <property name="bottomMargin">
+         <number>1</number>
+        </property>
+        <item>
+         <widget class="QGroupBox" name="groupBox">
+          <property name="minimumSize">
+           <size>
+            <width>250</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>250</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="title">
+           <string>Load Data</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_5">
+           <item>
+            <widget class="QPushButton" name="button_multiload">
+             <property name="font">
+              <font>
+               <family>Ubuntu</family>
+               <pointsize>8</pointsize>
+              </font>
+             </property>
+             <property name="text">
+              <string>Load XANES Stack</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QPushButton" name="button_4d">
+             <property name="font">
+              <font>
+               <family>Ubuntu</family>
+               <pointsize>8</pointsize>
+              </font>
+             </property>
+             <property name="text">
+              <string>Load 4D Stack TOMO-XANES</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_3">
+          <property name="minimumSize">
+           <size>
+            <width>250</width>
+            <height>0</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>250</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="title">
+           <string>Build a stack from a set of files</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_6">
+           <item>
+            <widget class="QPushButton" name="button_sm">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="font">
+              <font>
+               <family>Ubuntu</family>
+               <pointsize>8</pointsize>
+              </font>
+             </property>
+             <property name="text">
+              <string>Select a directory with stack files [.sm, xrm]</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer">
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="tc_imageeng">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Preview</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0" columnminimumwidth="0,0">
+          <property name="sizeConstraint">
+           <enum>QLayout::SetDefaultConstraint</enum>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <item row="0" column="0">
+           <widget class="GraphicsView" name="canvas">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="styleSheet">
+             <string notr="true">background: white</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QScrollBar" name="slider_eng">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="baseSize">
+             <size>
+              <width>0</width>
+              <height>0</height>
+             </size>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+              <kerning>false</kerning>
+             </font>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="invertedAppearance">
+             <bool>false</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QScrollBar" name="slider_theta">
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QGridLayout" name="gridLayout" rowstretch="0">
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
+      <number>0</number>
+     </property>
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <item row="0" column="0">
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <property name="spacing">
+        <number>12</number>
+       </property>
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QGroupBox" name="groupBox_5">
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>File</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_8">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>8</number>
+          </property>
+          <property name="topMargin">
+           <number>6</number>
+          </property>
+          <property name="rightMargin">
+           <number>6</number>
+          </property>
+          <property name="bottomMargin">
+           <number>9</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="tc_file">
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="cursor">
+             <cursorShape>IBeamCursor</cursorShape>
+            </property>
+            <property name="text">
+             <string>TextLabel</string>
+            </property>
+            <property name="textInteractionFlags">
+             <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox_4">
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>Path</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_9">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>8</number>
+          </property>
+          <property name="topMargin">
+           <number>6</number>
+          </property>
+          <property name="rightMargin">
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="tc_path">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="cursor">
+             <cursorShape>IBeamCursor</cursorShape>
+            </property>
+            <property name="text">
+             <string>TextLabel</string>
+            </property>
+            <property name="textInteractionFlags">
+             <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="0" column="2">
+      <widget class="QGroupBox" name="groupBox_2">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>200</width>
+         <height>300</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Export</string>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_10">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>9</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>9</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QGridLayout" name="gridLayout_3">
+          <property name="sizeConstraint">
+           <enum>QLayout::SetDefaultConstraint</enum>
+          </property>
+          <property name="topMargin">
+           <number>9</number>
+          </property>
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <item row="0" column="0">
+           <widget class="QPushButton" name="pb_copy">
+            <property name="text">
+             <string>Copy to Clipboard (Ctrl+C)</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <spacer name="verticalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QGroupBox" name="DisplayOptions">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>300</width>
+         <height>16777215</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Display Options</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>15</height>
+             </size>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>16777215</width>
+              <height>15</height>
+             </size>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>Colormap Category          Colormap    Steps</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_4">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QComboBox" name="CMCatBox">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>100</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>120</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="CMMapBox">
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="StepSpin">
+              <property name="maximumSize">
+               <size>
+                <width>40</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="minimum">
+               <number>2</number>
+              </property>
+              <property name="maximum">
+               <number>256</number>
+              </property>
+              <property name="value">
+               <number>256</number>
+              </property>
+              <property name="displayIntegerBase">
+               <number>10</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,1,1,0">
+            <property name="spacing">
+             <number>1</number>
+            </property>
+            <item>
+             <widget class="QCheckBox" name="MetricCheckBox">
+              <property name="minimumSize">
+               <size>
+                <width>80</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>80</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>Metric scale</string>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="ZeroOriginCheckBox">
+              <property name="minimumSize">
+               <size>
+                <width>100</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>100</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>Origin to zero</string>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="SquarePxCheckBox">
+              <property name="minimumSize">
+               <size>
+                <width>100</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>100</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="autoFillBackground">
+               <bool>false</bool>
+              </property>
+              <property name="text">
+               <string>Force square px</string>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="checked">
+               <bool>false</bool>
+              </property>
+              <property name="autoRepeat">
+               <bool>false</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>false</bool>
+              </property>
+              <property name="tristate">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="Line" name="line">
+          <property name="frameShadow">
+           <enum>QFrame::Plain</enum>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_7">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>2</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_2">
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>15</height>
+             </size>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>60</width>
+              <height>15</height>
+             </size>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>Transform</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="pb_rotate">
+            <property name="maximumSize">
+             <size>
+              <width>60</width>
+              <height>20</height>
+             </size>
+            </property>
+            <property name="layoutDirection">
+             <enum>Qt::LeftToRight</enum>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="icon">
+             <iconset>
+              <normaloff>images/rotate.png</normaloff>images/rotate.png</iconset>
+            </property>
+            <property name="iconSize">
+             <size>
+              <width>16</width>
+              <height>16</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="pb_mirror">
+            <property name="maximumSize">
+             <size>
+              <width>60</width>
+              <height>20</height>
+             </size>
+            </property>
+            <property name="autoFillBackground">
+             <bool>false</bool>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+            <property name="icon">
+             <iconset>
+              <normaloff>images/mirror.png</normaloff>images/mirror.png</iconset>
+            </property>
+            <property name="iconSize">
+             <size>
+              <width>16</width>
+              <height>16</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>GraphicsView</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mantis_xray/pagemap.ui b/mantis_xray/pagemap.ui
old mode 100644
new mode 100755
index 872c946..e726eeb
--- a/mantis_xray/pagemap.ui
+++ b/mantis_xray/pagemap.ui
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
+ <author>Jan-David Förster</author>
  <class>Form</class>
  <widget class="QWidget" name="Form">
   <property name="geometry">
@@ -11,7 +12,7 @@
    </rect>
   </property>
   <property name="sizePolicy">
-   <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+   <sizepolicy hsizetype="Maximum" vsizetype="Ignored">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
@@ -20,1429 +21,1679 @@
    <string>Form</string>
   </property>
   <layout class="QGridLayout" name="gridLayout_3">
-   <item row="0" column="0">
-    <widget class="QFrame" name="frame_4">
-     <property name="enabled">
-      <bool>true</bool>
-     </property>
+   <item row="0" column="2">
+    <widget class="QTabWidget" name="MapCreator">
      <property name="sizePolicy">
-      <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+      <sizepolicy hsizetype="Expanding" vsizetype="Ignored">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="minimumSize">
       <size>
-       <width>450</width>
-       <height>500</height>
+       <width>250</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>250</width>
+       <height>16777215</height>
       </size>
      </property>
+     <property name="font">
+      <font>
+       <family>Ubuntu</family>
+       <pointsize>8</pointsize>
+      </font>
+     </property>
+     <property name="focusPolicy">
+      <enum>Qt::ClickFocus</enum>
+     </property>
+     <property name="tabPosition">
+      <enum>QTabWidget::North</enum>
+     </property>
+     <property name="tabShape">
+      <enum>QTabWidget::Rounded</enum>
+     </property>
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="TabContent">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <attribute name="title">
+       <string>Map Creator</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QGroupBox" name="ImageSelection_1">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>100</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="toolTip">
+          <string notr="true">Select by Left &amp; Right Click</string>
+         </property>
+         <property name="title">
+          <string>Image #    Energy [eV]    Δx [px]  Δy [px]</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_7">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>2</number>
+          </property>
+          <property name="topMargin">
+           <number>2</number>
+          </property>
+          <property name="rightMargin">
+           <number>2</number>
+          </property>
+          <property name="bottomMargin">
+           <number>2</number>
+          </property>
+          <item>
+           <widget class="QListWidget" name="MapSelectWidget1">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximumSize">
+             <size>
+              <width>16777215</width>
+              <height>16777207</height>
+             </size>
+            </property>
+            <property name="palette">
+             <palette>
+              <active>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="127">
+                  <red>85</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </active>
+              <inactive>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="127">
+                  <red>85</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>0</red>
+                  <green>0</green>
+                  <blue>0</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </inactive>
+              <disabled>
+               <colorrole role="Highlight">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="0">
+                  <red>51</red>
+                  <green>153</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+               <colorrole role="HighlightedText">
+                <brush brushstyle="SolidPattern">
+                 <color alpha="255">
+                  <red>255</red>
+                  <green>255</green>
+                  <blue>255</blue>
+                 </color>
+                </brush>
+               </colorrole>
+              </disabled>
+             </palette>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="focusPolicy">
+             <enum>Qt::NoFocus</enum>
+            </property>
+            <property name="styleSheet">
+             <string notr="true"/>
+            </property>
+            <property name="frameShape">
+             <enum>QFrame::NoFrame</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Plain</enum>
+            </property>
+            <property name="lineWidth">
+             <number>0</number>
+            </property>
+            <property name="midLineWidth">
+             <number>0</number>
+            </property>
+            <property name="horizontalScrollBarPolicy">
+             <enum>Qt::ScrollBarAlwaysOff</enum>
+            </property>
+            <property name="editTriggers">
+             <set>QAbstractItemView::NoEditTriggers</set>
+            </property>
+            <property name="showDropIndicator" stdset="0">
+             <bool>false</bool>
+            </property>
+            <property name="dragDropMode">
+             <enum>QAbstractItemView::NoDragDrop</enum>
+            </property>
+            <property name="defaultDropAction">
+             <enum>Qt::CopyAction</enum>
+            </property>
+            <property name="alternatingRowColors">
+             <bool>false</bool>
+            </property>
+            <property name="selectionMode">
+             <enum>QAbstractItemView::NoSelection</enum>
+            </property>
+            <property name="selectionBehavior">
+             <enum>QAbstractItemView::SelectItems</enum>
+            </property>
+            <property name="movement">
+             <enum>QListView::Static</enum>
+            </property>
+            <property name="isWrapping" stdset="0">
+             <bool>false</bool>
+            </property>
+            <property name="viewMode">
+             <enum>QListView::ListMode</enum>
+            </property>
+            <property name="selectionRectVisible">
+             <bool>false</bool>
+            </property>
+            <property name="sortingEnabled">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_9">
+            <property name="leftMargin">
+             <number>3</number>
+            </property>
+            <property name="topMargin">
+             <number>3</number>
+            </property>
+            <property name="rightMargin">
+             <number>3</number>
+            </property>
+            <property name="bottomMargin">
+             <number>3</number>
+            </property>
+            <item>
+             <widget class="QPushButton" name="pbSelfromSpec">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>Select from Spectrum</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pbClrSel">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>Clear selection</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="Alignment">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
+           <horstretch>1</horstretch>
+           <verstretch>1</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="baseSize">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>Alignment</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+         </property>
+         <property name="flat">
+          <bool>false</bool>
+         </property>
+         <property name="checkable">
+          <bool>false</bool>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_6">
+          <property name="leftMargin">
+           <number>9</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_7">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QFrame" name="frame">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>120</height>
+               </size>
+              </property>
+              <layout class="QVBoxLayout" name="verticalLayout">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="leftMargin">
+                <number>0</number>
+               </property>
+               <property name="topMargin">
+                <number>0</number>
+               </property>
+               <property name="rightMargin">
+                <number>0</number>
+               </property>
+               <property name="bottomMargin">
+                <number>0</number>
+               </property>
+               <item>
+                <widget class="QCheckBox" name="CropCheckBox">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Crop</string>
+                 </property>
+                 <property name="checked">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pbClrShifts">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Fixed" vsizetype="Maximum">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="minimumSize">
+                  <size>
+                   <width>50</width>
+                   <height>35</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>50</width>
+                   <height>35</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Clear all
+shifts</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="verticalSpacer">
+                 <property name="orientation">
+                  <enum>Qt::Vertical</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>20</width>
+                   <height>40</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item>
+             <widget class="QFrame" name="frame_6">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>150</width>
+                <height>150</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>150</width>
+                <height>150</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="frameShape">
+               <enum>QFrame::StyledPanel</enum>
+              </property>
+              <property name="frameShadow">
+               <enum>QFrame::Sunken</enum>
+              </property>
+              <property name="lineWidth">
+               <number>1</number>
+              </property>
+              <property name="midLineWidth">
+               <number>0</number>
+              </property>
+              <layout class="QHBoxLayout" name="horizontalLayout_8">
+               <property name="spacing">
+                <number>0</number>
+               </property>
+               <property name="leftMargin">
+                <number>0</number>
+               </property>
+               <property name="topMargin">
+                <number>0</number>
+               </property>
+               <property name="rightMargin">
+                <number>0</number>
+               </property>
+               <property name="bottomMargin">
+                <number>0</number>
+               </property>
+               <item>
+                <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0">
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>1</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>0</number>
+                 </property>
+                 <property name="horizontalSpacing">
+                  <number>4</number>
+                 </property>
+                 <property name="verticalSpacing">
+                  <number>1</number>
+                 </property>
+                 <item row="2" column="3">
+                  <widget class="QPushButton" name="pbR">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>▹</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="1" column="2">
+                  <widget class="QPushButton" name="pbU">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>▵</string>
+                   </property>
+                   <property name="checkable">
+                    <bool>false</bool>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="4" column="4">
+                  <widget class="QPushButton" name="pbRRDD">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◢</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="2">
+                  <widget class="QPushButton" name="pbD">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>▿</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="3">
+                  <widget class="QPushButton" name="pbRD">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◿</string>
+                   </property>
+                   <property name="autoDefault">
+                    <bool>false</bool>
+                   </property>
+                   <property name="default">
+                    <bool>false</bool>
+                   </property>
+                   <property name="flat">
+                    <bool>false</bool>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="4" column="0">
+                  <widget class="QPushButton" name="pbLLDD">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◣</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="2">
+                  <widget class="QPushButton" name="pbUU">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>▴</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="4">
+                  <widget class="QPushButton" name="pbRRUU">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◥</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="1" column="1">
+                  <widget class="QPushButton" name="pbLU">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◸</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="1" column="3">
+                  <widget class="QPushButton" name="pbRU">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◹</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="0">
+                  <widget class="QPushButton" name="pbLL">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◂</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="4">
+                  <widget class="QPushButton" name="pbRR">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>▸</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="3" column="1">
+                  <widget class="QPushButton" name="pbLD">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◺</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="4" column="2">
+                  <widget class="QPushButton" name="pbDD">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>▾</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="2">
+                  <widget class="QPushButton" name="pbRST">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>11</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>•</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="2" column="1">
+                  <widget class="QPushButton" name="pbL">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◃</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="0">
+                  <widget class="QPushButton" name="pbLLUU">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>20</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                   <property name="baseSize">
+                    <size>
+                     <width>0</width>
+                     <height>0</height>
+                    </size>
+                   </property>
+                   <property name="font">
+                    <font>
+                     <family>Ubuntu</family>
+                     <pointsize>10</pointsize>
+                    </font>
+                   </property>
+                   <property name="focusPolicy">
+                    <enum>Qt::ClickFocus</enum>
+                   </property>
+                   <property name="text">
+                    <string>◤</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+              </layout>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="DisplayOptions">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+           <horstretch>1</horstretch>
+           <verstretch>1</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>16777215</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>Display Options</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_2">
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="maximumSize">
+             <size>
+              <width>16777215</width>
+              <height>15</height>
+             </size>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>Colormap Category      Colormap   Steps</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_4">
+            <item>
+             <widget class="QComboBox" name="CMCatBox">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>100</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="CMMapBox">
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSpinBox" name="StepSpin">
+              <property name="maximumSize">
+               <size>
+                <width>40</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="minimum">
+               <number>2</number>
+              </property>
+              <property name="maximum">
+               <number>256</number>
+              </property>
+              <property name="value">
+               <number>256</number>
+              </property>
+              <property name="displayIntegerBase">
+               <number>10</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,1,1,0">
+            <property name="spacing">
+             <number>1</number>
+            </property>
+            <item>
+             <widget class="QCheckBox" name="MetricCheckBox">
+              <property name="minimumSize">
+               <size>
+                <width>80</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>80</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>Metric scale</string>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="ZeroOriginCheckBox">
+              <property name="minimumSize">
+               <size>
+                <width>100</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>100</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string>Origin to zero</string>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QCheckBox" name="SquarePxCheckBox">
+              <property name="minimumSize">
+               <size>
+                <width>100</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>100</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="autoFillBackground">
+               <bool>false</bool>
+              </property>
+              <property name="text">
+               <string>Force square px</string>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="checked">
+               <bool>false</bool>
+              </property>
+              <property name="autoRepeat">
+               <bool>false</bool>
+              </property>
+              <property name="autoExclusive">
+               <bool>false</bool>
+              </property>
+              <property name="tristate">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer">
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="sizeConstraint">
+             <enum>QLayout::SetDefaultConstraint</enum>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <item>
+             <layout class="QGridLayout" name="gridLayout_2">
+              <property name="sizeConstraint">
+               <enum>QLayout::SetDefaultConstraint</enum>
+              </property>
+              <property name="horizontalSpacing">
+               <number>6</number>
+              </property>
+              <property name="verticalSpacing">
+               <number>0</number>
+              </property>
+              <item row="1" column="1">
+               <widget class="QDoubleSpinBox" name="ODLowSpinBox">
+                <property name="enabled">
+                 <bool>false</bool>
+                </property>
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>18</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>60</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="font">
+                 <font>
+                  <family>Ubuntu</family>
+                  <pointsize>8</pointsize>
+                 </font>
+                </property>
+                <property name="locale">
+                 <locale language="C" country="AnyCountry"/>
+                </property>
+                <property name="decimals">
+                 <number>3</number>
+                </property>
+                <property name="minimum">
+                 <double>-99.989999999999995</double>
+                </property>
+                <property name="singleStep">
+                 <double>0.010000000000000</double>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QDoubleSpinBox" name="ODHighSpinBox">
+                <property name="enabled">
+                 <bool>false</bool>
+                </property>
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>20</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>60</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="font">
+                 <font>
+                  <family>Ubuntu</family>
+                  <pointsize>8</pointsize>
+                 </font>
+                </property>
+                <property name="locale">
+                 <locale language="C" country="AnyCountry"/>
+                </property>
+                <property name="decimals">
+                 <number>3</number>
+                </property>
+                <property name="minimum">
+                 <double>-99.989999999999995</double>
+                </property>
+                <property name="singleStep">
+                 <double>0.010000000000000</double>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="0">
+               <widget class="QLabel" name="label_3">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>20</height>
+                 </size>
+                </property>
+                <property name="font">
+                 <font>
+                  <family>Ubuntu</family>
+                  <pointsize>8</pointsize>
+                 </font>
+                </property>
+                <property name="text">
+                 <string>Lower OD limit</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_2">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>20</height>
+                 </size>
+                </property>
+                <property name="font">
+                 <font>
+                  <family>Ubuntu</family>
+                  <pointsize>8</pointsize>
+                 </font>
+                </property>
+                <property name="text">
+                 <string>Upper OD limit</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pbRSTOD">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>20</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="layoutDirection">
+               <enum>Qt::LeftToRight</enum>
+              </property>
+              <property name="text">
+               <string>Reset
+OD limits</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="Line" name="line">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QGridLayout" name="gridLayout_4">
+            <item row="0" column="2">
+             <widget class="QSpinBox" name="filterSpinBox">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>40</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="font">
+               <font>
+                <family>Ubuntu</family>
+                <pointsize>8</pointsize>
+               </font>
+              </property>
+              <property name="locale">
+               <locale language="C" country="AnyCountry"/>
+              </property>
+              <property name="minimum">
+               <number>1</number>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0">
+             <widget class="QLabel" name="label_4">
+              <property name="text">
+               <string>Uniform filter</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QLabel" name="label_5">
+              <property name="text">
+               <string>size:</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="Export">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>120</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>Export</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_5">
+          <item row="0" column="0">
+           <widget class="QPushButton" name="pbExpData">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>OD Data (*.tif, *.txt)</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QPushButton" name="pbExpImg">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>OD Image (*.svg,*.tif,*.png*.jpg)</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QPushButton" name="pbCopy">
+            <property name="text">
+             <string>Copy to Clipboard (Ctrl+C)</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QFrame" name="frame">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="font">
+      <font>
+       <family>Ubuntu</family>
+       <pointsize>8</pointsize>
+      </font>
+     </property>
+     <property name="autoFillBackground">
+      <bool>false</bool>
+     </property>
+     <property name="styleSheet">
+      <string notr="true"/>
+     </property>
      <property name="frameShape">
       <enum>QFrame::StyledPanel</enum>
      </property>
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
-     <layout class="QHBoxLayout" name="horizontalLayout">
-      <property name="sizeConstraint">
-       <enum>QLayout::SetDefaultConstraint</enum>
+     <property name="lineWidth">
+      <number>1</number>
+     </property>
+     <property name="midLineWidth">
+      <number>0</number>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_3">
+      <property name="spacing">
+       <number>6</number>
+      </property>
+      <property name="bottomMargin">
+       <number>9</number>
       </property>
       <item>
-       <widget class="QFrame" name="frame">
+       <widget class="GraphicsView" name="canvas">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
-        <property name="autoFillBackground">
-         <bool>false</bool>
+        <property name="font">
+         <font>
+          <family>Ubuntu</family>
+          <pointsize>8</pointsize>
+         </font>
         </property>
         <property name="styleSheet">
-         <string notr="true"/>
-        </property>
-        <property name="frameShape">
-         <enum>QFrame::StyledPanel</enum>
+         <string notr="true">background: white</string>
         </property>
-        <property name="frameShadow">
-         <enum>QFrame::Raised</enum>
-        </property>
-        <layout class="QHBoxLayout" name="horizontalLayout_3">
-         <item>
-          <widget class="GraphicsView" name="canvas">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="styleSheet">
-            <string notr="true">background: white</string>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QScrollBar" name="slider_eng">
-           <property name="orientation">
-            <enum>Qt::Vertical</enum>
-           </property>
-          </widget>
-         </item>
-        </layout>
        </widget>
       </item>
-      <item alignment="Qt::AlignRight">
-       <widget class="QFrame" name="frame_5">
+      <item>
+       <widget class="QScrollBar" name="slider_eng">
         <property name="sizePolicy">
-         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
+         <sizepolicy hsizetype="Fixed" vsizetype="MinimumExpanding">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
-        <property name="minimumSize">
-         <size>
-          <width>250</width>
-          <height>0</height>
-         </size>
+        <property name="font">
+         <font>
+          <family>Ubuntu</family>
+          <pointsize>8</pointsize>
+         </font>
         </property>
-        <property name="maximumSize">
-         <size>
-          <width>250</width>
-          <height>16777215</height>
-         </size>
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
         </property>
-        <property name="frameShape">
-         <enum>QFrame::StyledPanel</enum>
-        </property>
-        <property name="frameShadow">
-         <enum>QFrame::Raised</enum>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout_9">
-         <property name="spacing">
-          <number>0</number>
-         </property>
-         <property name="leftMargin">
-          <number>0</number>
-         </property>
-         <property name="topMargin">
-          <number>2</number>
-         </property>
-         <property name="rightMargin">
-          <number>0</number>
-         </property>
-         <property name="bottomMargin">
-          <number>2</number>
-         </property>
-         <item>
-          <widget class="QTabWidget" name="MapCreator">
-           <property name="focusPolicy">
-            <enum>Qt::ClickFocus</enum>
-           </property>
-           <property name="tabPosition">
-            <enum>QTabWidget::North</enum>
-           </property>
-           <property name="tabShape">
-            <enum>QTabWidget::Rounded</enum>
-           </property>
-           <property name="currentIndex">
-            <number>0</number>
-           </property>
-           <widget class="QWidget" name="TabContent">
-            <attribute name="title">
-             <string>Map Creator</string>
-            </attribute>
-            <layout class="QVBoxLayout" name="verticalLayout_4">
-             <item>
-              <widget class="QGroupBox" name="ImageSelection_1">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
-                 <horstretch>0</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimumSize">
-                <size>
-                 <width>100</width>
-                 <height>80</height>
-                </size>
-               </property>
-               <property name="toolTip">
-                <string notr="true">Select by Left &amp; Right Click</string>
-               </property>
-               <property name="title">
-                <string>Image #    Energy [eV]    Δx [px]  Δy [px]</string>
-               </property>
-               <layout class="QVBoxLayout" name="verticalLayout_7">
-                <property name="spacing">
-                 <number>0</number>
-                </property>
-                <property name="leftMargin">
-                 <number>2</number>
-                </property>
-                <property name="topMargin">
-                 <number>2</number>
-                </property>
-                <property name="rightMargin">
-                 <number>2</number>
-                </property>
-                <property name="bottomMargin">
-                 <number>2</number>
-                </property>
-                <item>
-                 <widget class="QListWidget" name="MapSelectWidget1">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                    <horstretch>0</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="maximumSize">
-                   <size>
-                    <width>16777215</width>
-                    <height>16777215</height>
-                   </size>
-                  </property>
-                  <property name="palette">
-                   <palette>
-                    <active>
-                     <colorrole role="Highlight">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="127">
-                        <red>85</red>
-                        <green>255</green>
-                        <blue>255</blue>
-                       </color>
-                      </brush>
-                     </colorrole>
-                     <colorrole role="HighlightedText">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="255">
-                        <red>0</red>
-                        <green>0</green>
-                        <blue>0</blue>
-                       </color>
-                      </brush>
-                     </colorrole>
-                    </active>
-                    <inactive>
-                     <colorrole role="Highlight">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="127">
-                        <red>85</red>
-                        <green>255</green>
-                        <blue>255</blue>
-                       </color>
-                      </brush>
-                     </colorrole>
-                     <colorrole role="HighlightedText">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="255">
-                        <red>0</red>
-                        <green>0</green>
-                        <blue>0</blue>
-                       </color>
-                      </brush>
-                     </colorrole>
-                    </inactive>
-                    <disabled>
-                     <colorrole role="Highlight">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="0">
-                        <red>51</red>
-                        <green>153</green>
-                        <blue>255</blue>
-                       </color>
-                      </brush>
-                     </colorrole>
-                     <colorrole role="HighlightedText">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="255">
-                        <red>255</red>
-                        <green>255</green>
-                        <blue>255</blue>
-                       </color>
-                      </brush>
-                     </colorrole>
-                    </disabled>
-                   </palette>
-                  </property>
-                  <property name="focusPolicy">
-                   <enum>Qt::NoFocus</enum>
-                  </property>
-                  <property name="frameShape">
-                   <enum>QFrame::NoFrame</enum>
-                  </property>
-                  <property name="frameShadow">
-                   <enum>QFrame::Plain</enum>
-                  </property>
-                  <property name="lineWidth">
-                   <number>0</number>
-                  </property>
-                  <property name="midLineWidth">
-                   <number>0</number>
-                  </property>
-                  <property name="horizontalScrollBarPolicy">
-                   <enum>Qt::ScrollBarAlwaysOff</enum>
-                  </property>
-                  <property name="editTriggers">
-                   <set>QAbstractItemView::NoEditTriggers</set>
-                  </property>
-                  <property name="showDropIndicator" stdset="0">
-                   <bool>false</bool>
-                  </property>
-                  <property name="dragDropMode">
-                   <enum>QAbstractItemView::NoDragDrop</enum>
-                  </property>
-                  <property name="defaultDropAction">
-                   <enum>Qt::IgnoreAction</enum>
-                  </property>
-                  <property name="alternatingRowColors">
-                   <bool>true</bool>
-                  </property>
-                  <property name="selectionMode">
-                   <enum>QAbstractItemView::SingleSelection</enum>
-                  </property>
-                  <property name="selectionBehavior">
-                   <enum>QAbstractItemView::SelectItems</enum>
-                  </property>
-                  <property name="viewMode">
-                   <enum>QListView::ListMode</enum>
-                  </property>
-                  <property name="selectionRectVisible">
-                   <bool>true</bool>
-                  </property>
-                  <property name="sortingEnabled">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <layout class="QHBoxLayout" name="horizontalLayout_9">
-                  <property name="leftMargin">
-                   <number>3</number>
-                  </property>
-                  <property name="topMargin">
-                   <number>3</number>
-                  </property>
-                  <property name="rightMargin">
-                   <number>3</number>
-                  </property>
-                  <property name="bottomMargin">
-                   <number>3</number>
-                  </property>
-                  <item>
-                   <widget class="QPushButton" name="pbSelfromSpec">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <property name="text">
-                     <string>Select from Spectrum</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QPushButton" name="pbClrSel">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <property name="text">
-                     <string>Clear selection</string>
-                    </property>
-                   </widget>
-                  </item>
-                 </layout>
-                </item>
-               </layout>
-              </widget>
-             </item>
-             <item>
-              <widget class="QGroupBox" name="Alignment">
-               <property name="enabled">
-                <bool>true</bool>
-               </property>
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                 <horstretch>1</horstretch>
-                 <verstretch>1</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimumSize">
-                <size>
-                 <width>100</width>
-                 <height>175</height>
-                </size>
-               </property>
-               <property name="baseSize">
-                <size>
-                 <width>0</width>
-                 <height>0</height>
-                </size>
-               </property>
-               <property name="title">
-                <string>Alignment</string>
-               </property>
-               <property name="alignment">
-                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
-               </property>
-               <property name="flat">
-                <bool>false</bool>
-               </property>
-               <property name="checkable">
-                <bool>false</bool>
-               </property>
-               <layout class="QVBoxLayout" name="verticalLayout_6">
-                <item>
-                 <layout class="QHBoxLayout" name="horizontalLayout_7">
-                  <property name="rightMargin">
-                   <number>8</number>
-                  </property>
-                  <item>
-                   <layout class="QVBoxLayout" name="verticalLayout">
-                    <property name="spacing">
-                     <number>5</number>
-                    </property>
-                    <item>
-                     <widget class="QCheckBox" name="CropCheckBox">
-                      <property name="text">
-                       <string>Crop</string>
-                      </property>
-                      <property name="checked">
-                       <bool>true</bool>
-                      </property>
-                     </widget>
-                    </item>
-                    <item>
-                     <widget class="QPushButton" name="pbClrShifts">
-                      <property name="sizePolicy">
-                       <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                        <horstretch>0</horstretch>
-                        <verstretch>0</verstretch>
-                       </sizepolicy>
-                      </property>
-                      <property name="minimumSize">
-                       <size>
-                        <width>50</width>
-                        <height>35</height>
-                       </size>
-                      </property>
-                      <property name="maximumSize">
-                       <size>
-                        <width>50</width>
-                        <height>35</height>
-                       </size>
-                      </property>
-                      <property name="text">
-                       <string>Clear all
-shifts</string>
-                      </property>
-                     </widget>
-                    </item>
-                    <item>
-                     <widget class="QPushButton" name="AutoAlignpb">
-                      <property name="enabled">
-                       <bool>false</bool>
-                      </property>
-                      <property name="sizePolicy">
-                       <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-                        <horstretch>0</horstretch>
-                        <verstretch>0</verstretch>
-                       </sizepolicy>
-                      </property>
-                      <property name="minimumSize">
-                       <size>
-                        <width>50</width>
-                        <height>0</height>
-                       </size>
-                      </property>
-                      <property name="maximumSize">
-                       <size>
-                        <width>16777215</width>
-                        <height>16777215</height>
-                       </size>
-                      </property>
-                      <property name="text">
-                       <string>Auto
-Align</string>
-                      </property>
-                     </widget>
-                    </item>
-                    <item>
-                     <widget class="QLabel" name="label_5">
-                      <property name="enabled">
-                       <bool>false</bool>
-                      </property>
-                      <property name="maximumSize">
-                       <size>
-                        <width>16777215</width>
-                        <height>15</height>
-                       </size>
-                      </property>
-                      <property name="text">
-                       <string>Shift (px):</string>
-                      </property>
-                     </widget>
-                    </item>
-                    <item>
-                     <widget class="QLabel" name="ShiftLabel">
-                      <property name="enabled">
-                       <bool>false</bool>
-                      </property>
-                      <property name="maximumSize">
-                       <size>
-                        <width>16777215</width>
-                        <height>50</height>
-                       </size>
-                      </property>
-                      <property name="text">
-                       <string>Label</string>
-                      </property>
-                     </widget>
-                    </item>
-                   </layout>
-                  </item>
-                  <item>
-                   <widget class="QFrame" name="frame_6">
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <property name="minimumSize">
-                     <size>
-                      <width>150</width>
-                      <height>150</height>
-                     </size>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>150</width>
-                      <height>150</height>
-                     </size>
-                    </property>
-                    <property name="frameShape">
-                     <enum>QFrame::Box</enum>
-                    </property>
-                    <property name="frameShadow">
-                     <enum>QFrame::Sunken</enum>
-                    </property>
-                    <layout class="QHBoxLayout" name="horizontalLayout_8">
-                     <property name="spacing">
-                      <number>0</number>
-                     </property>
-                     <property name="leftMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="topMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="rightMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="bottomMargin">
-                      <number>0</number>
-                     </property>
-                     <item>
-                      <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0">
-                       <property name="sizeConstraint">
-                        <enum>QLayout::SetNoConstraint</enum>
-                       </property>
-                       <property name="leftMargin">
-                        <number>3</number>
-                       </property>
-                       <property name="topMargin">
-                        <number>3</number>
-                       </property>
-                       <property name="rightMargin">
-                        <number>5</number>
-                       </property>
-                       <property name="bottomMargin">
-                        <number>5</number>
-                       </property>
-                       <property name="spacing">
-                        <number>2</number>
-                       </property>
-                       <item row="1" column="3">
-                        <widget class="QPushButton" name="pbRU">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>13</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◹</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="2" column="0">
-                        <widget class="QPushButton" name="pbLL">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◂</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="4" column="4">
-                        <widget class="QPushButton" name="pbRRDD">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>18</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◢</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="1" column="2">
-                        <widget class="QPushButton" name="pbU">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>▵</string>
-                         </property>
-                         <property name="checkable">
-                          <bool>false</bool>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="3" column="2">
-                        <widget class="QPushButton" name="pbD">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>▿</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="2" column="1">
-                        <widget class="QPushButton" name="pbL">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◃</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="0" column="0">
-                        <widget class="QPushButton" name="pbLLUU">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="baseSize">
-                          <size>
-                           <width>0</width>
-                           <height>0</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>18</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◤</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="2" column="3">
-                        <widget class="QPushButton" name="pbR">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>▹</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="1" column="1">
-                        <widget class="QPushButton" name="pbLU">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>13</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◸</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="4" column="0">
-                        <widget class="QPushButton" name="pbLLDD">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>18</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◣</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="0" column="2">
-                        <widget class="QPushButton" name="pbUU">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>▴</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="0" column="4">
-                        <widget class="QPushButton" name="pbRRUU">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>18</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◥</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="2" column="4">
-                        <widget class="QPushButton" name="pbRR">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>▸</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="3" column="1">
-                        <widget class="QPushButton" name="pbLD">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>13</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◺</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="3" column="3">
-                        <widget class="QPushButton" name="pbRD">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>13</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>◿</string>
-                         </property>
-                         <property name="autoDefault">
-                          <bool>false</bool>
-                         </property>
-                         <property name="default">
-                          <bool>false</bool>
-                         </property>
-                         <property name="flat">
-                          <bool>false</bool>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="4" column="2">
-                        <widget class="QPushButton" name="pbDD">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>▾</string>
-                         </property>
-                        </widget>
-                       </item>
-                       <item row="2" column="2">
-                        <widget class="QPushButton" name="pbRST">
-                         <property name="sizePolicy">
-                          <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                           <horstretch>0</horstretch>
-                           <verstretch>0</verstretch>
-                          </sizepolicy>
-                         </property>
-                         <property name="minimumSize">
-                          <size>
-                           <width>20</width>
-                           <height>20</height>
-                          </size>
-                         </property>
-                         <property name="font">
-                          <font>
-                           <family>MS Sans Serif</family>
-                           <pointsize>22</pointsize>
-                          </font>
-                         </property>
-                         <property name="focusPolicy">
-                          <enum>Qt::ClickFocus</enum>
-                         </property>
-                         <property name="text">
-                          <string>•</string>
-                         </property>
-                        </widget>
-                       </item>
-                      </layout>
-                     </item>
-                    </layout>
-                   </widget>
-                  </item>
-                 </layout>
-                </item>
-               </layout>
-              </widget>
-             </item>
-             <item>
-              <widget class="QGroupBox" name="ODoff">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                 <horstretch>0</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="title">
-                <string>OD Offset</string>
-               </property>
-               <layout class="QVBoxLayout" name="verticalLayout_5">
-                <item>
-                 <layout class="QGridLayout" name="gridLayout_4">
-                  <item row="0" column="0">
-                   <widget class="QDoubleSpinBox" name="ODOffSpinBox">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>50</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="locale">
-                     <locale language="C" country="AnyCountry"/>
-                    </property>
-                    <property name="decimals">
-                     <number>3</number>
-                    </property>
-                    <property name="minimum">
-                     <double>-99.989999999999995</double>
-                    </property>
-                    <property name="singleStep">
-                     <double>0.010000000000000</double>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="1">
-                   <widget class="QPushButton" name="HistoI0pb">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="text">
-                     <string>Select I0</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="2">
-                   <widget class="QPushButton" name="pushButton">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="text">
-                     <string>Reset I0</string>
-                    </property>
-                   </widget>
-                  </item>
-                 </layout>
-                </item>
-               </layout>
-              </widget>
-             </item>
-             <item>
-              <widget class="QGroupBox" name="DisplayOptions">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-                 <horstretch>0</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimumSize">
-                <size>
-                 <width>0</width>
-                 <height>150</height>
-                </size>
-               </property>
-               <property name="title">
-                <string>Display Options</string>
-               </property>
-               <layout class="QVBoxLayout" name="verticalLayout_2">
-                <item>
-                 <widget class="QLabel" name="label">
-                  <property name="maximumSize">
-                   <size>
-                    <width>16777215</width>
-                    <height>15</height>
-                   </size>
-                  </property>
-                  <property name="text">
-                   <string>Colormap Category      Colormap   Steps</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <layout class="QHBoxLayout" name="horizontalLayout_4">
-                  <item>
-                   <widget class="QComboBox" name="CMCatBox">
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <property name="minimumSize">
-                     <size>
-                      <width>0</width>
-                      <height>0</height>
-                     </size>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>100</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QComboBox" name="CMMapBox"/>
-                  </item>
-                  <item>
-                   <widget class="QSpinBox" name="StepSpin">
-                    <property name="maximumSize">
-                     <size>
-                      <width>40</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="minimum">
-                     <number>2</number>
-                    </property>
-                    <property name="maximum">
-                     <number>256</number>
-                    </property>
-                    <property name="value">
-                     <number>256</number>
-                    </property>
-                    <property name="displayIntegerBase">
-                     <number>10</number>
-                    </property>
-                   </widget>
-                  </item>
-                 </layout>
-                </item>
-                <item>
-                 <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,1,1,0">
-                  <property name="spacing">
-                   <number>1</number>
-                  </property>
-                  <item>
-                   <widget class="QCheckBox" name="MetricCheckBox">
-                    <property name="minimumSize">
-                     <size>
-                      <width>80</width>
-                      <height>0</height>
-                     </size>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>80</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="text">
-                     <string>Metric scale</string>
-                    </property>
-                    <property name="checked">
-                     <bool>true</bool>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QCheckBox" name="ZeroOriginCheckBox">
-                    <property name="minimumSize">
-                     <size>
-                      <width>100</width>
-                      <height>0</height>
-                     </size>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>100</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="text">
-                     <string>Origin to zero</string>
-                    </property>
-                    <property name="checked">
-                     <bool>true</bool>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QCheckBox" name="SquarePxCheckBox">
-                    <property name="minimumSize">
-                     <size>
-                      <width>100</width>
-                      <height>0</height>
-                     </size>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>100</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="autoFillBackground">
-                     <bool>false</bool>
-                    </property>
-                    <property name="text">
-                     <string>Force square px</string>
-                    </property>
-                    <property name="checkable">
-                     <bool>true</bool>
-                    </property>
-                    <property name="checked">
-                     <bool>false</bool>
-                    </property>
-                    <property name="autoRepeat">
-                     <bool>false</bool>
-                    </property>
-                    <property name="autoExclusive">
-                     <bool>false</bool>
-                    </property>
-                    <property name="tristate">
-                     <bool>false</bool>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <spacer name="horizontalSpacer">
-                    <property name="orientation">
-                     <enum>Qt::Horizontal</enum>
-                    </property>
-                    <property name="sizeHint" stdset="0">
-                     <size>
-                      <width>40</width>
-                      <height>20</height>
-                     </size>
-                    </property>
-                   </spacer>
-                  </item>
-                 </layout>
-                </item>
-                <item>
-                 <layout class="QGridLayout" name="gridLayout_2">
-                  <item row="1" column="1">
-                   <widget class="QLabel" name="label_3">
-                    <property name="text">
-                     <string>Lower OD limit</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="1" column="0">
-                   <widget class="QDoubleSpinBox" name="ODLowSpinBox">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>60</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="locale">
-                     <locale language="C" country="AnyCountry"/>
-                    </property>
-                    <property name="decimals">
-                     <number>3</number>
-                    </property>
-                    <property name="minimum">
-                     <double>-99.989999999999995</double>
-                    </property>
-                    <property name="singleStep">
-                     <double>0.010000000000000</double>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="0">
-                   <widget class="QDoubleSpinBox" name="ODHighSpinBox">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>60</width>
-                      <height>16777215</height>
-                     </size>
-                    </property>
-                    <property name="locale">
-                     <locale language="C" country="AnyCountry"/>
-                    </property>
-                    <property name="decimals">
-                     <number>3</number>
-                    </property>
-                    <property name="minimum">
-                     <double>-99.989999999999995</double>
-                    </property>
-                    <property name="singleStep">
-                     <double>0.010000000000000</double>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="1">
-                   <widget class="QLabel" name="label_2">
-                    <property name="text">
-                     <string>Upper OD limit</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item row="0" column="2">
-                   <widget class="QPushButton" name="pbRSTOD">
-                    <property name="enabled">
-                     <bool>false</bool>
-                    </property>
-                    <property name="minimumSize">
-                     <size>
-                      <width>40</width>
-                      <height>40</height>
-                     </size>
-                    </property>
-                    <property name="maximumSize">
-                     <size>
-                      <width>60</width>
-                      <height>60</height>
-                     </size>
-                    </property>
-                    <property name="text">
-                     <string>Reset
-OD limits</string>
-                    </property>
-                   </widget>
-                  </item>
-                 </layout>
-                </item>
-               </layout>
-              </widget>
-             </item>
-             <item>
-              <widget class="QGroupBox" name="Export">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-                 <horstretch>0</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="title">
-                <string>Export</string>
-               </property>
-               <layout class="QGridLayout" name="gridLayout_5">
-                <item row="0" column="0">
-                 <widget class="QPushButton" name="pbExpData">
-                  <property name="enabled">
-                   <bool>false</bool>
-                  </property>
-                  <property name="text">
-                   <string>OD Data (*.tif, *.txt)</string>
-                  </property>
-                 </widget>
-                </item>
-                <item row="1" column="0">
-                 <widget class="QPushButton" name="pbExpImg">
-                  <property name="enabled">
-                   <bool>false</bool>
-                  </property>
-                  <property name="text">
-                   <string>OD Image (*.svg,*.tif,*.png*.jpg)</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </widget>
-             </item>
-            </layout>
-           </widget>
-          </widget>
-         </item>
-        </layout>
        </widget>
       </item>
      </layout>
@@ -1454,7 +1705,7 @@ OD limits</string>
   <customwidget>
    <class>GraphicsView</class>
    <extends>QGraphicsView</extends>
-   <header>pyqtgraph</header>
+   <header location="global">pyqtgraph</header>
   </customwidget>
  </customwidgets>
  <resources/>
diff --git a/mantis_xray/showalign2.ui b/mantis_xray/showalign2.ui
new file mode 100644
index 0000000..109d433
--- /dev/null
+++ b/mantis_xray/showalign2.ui
@@ -0,0 +1,656 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <author>Jan-David Förster</author>
+ <class>Alignment</class>
+ <widget class="QWidget" name="Alignment">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>900</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="toolTip">
+   <string/>
+  </property>
+  <property name="whatsThis">
+   <string/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="0" column="0">
+      <widget class="QGroupBox" name="groupBox">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>100</width>
+         <height>100</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Stack Browser</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QGridLayout" name="gridLayout_6">
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <item row="0" column="0">
+           <widget class="GraphicsView" name="canvas">
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QScrollBar" name="slider_eng">
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QScrollBar" name="slider_theta">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QGroupBox" name="groupBox_2">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Drifts</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="GraphicsLayoutWidget" name="DriftsWidget">
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <layout class="QGridLayout" name="gridLayout_2">
+       <property name="horizontalSpacing">
+        <number>0</number>
+       </property>
+       <property name="verticalSpacing">
+        <number>6</number>
+       </property>
+       <item row="2" column="0">
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QPushButton" name="button_ok">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="font">
+            <font>
+             <family>Ubuntu</family>
+             <pointsize>8</pointsize>
+            </font>
+           </property>
+           <property name="text">
+            <string>Accept</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="button_cancel">
+           <property name="font">
+            <font>
+             <family>Ubuntu</family>
+             <pointsize>8</pointsize>
+            </font>
+           </property>
+           <property name="text">
+            <string>Cancel</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="0" column="0">
+        <widget class="QGroupBox" name="groupBox_4">
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>Drift approximation &amp;&amp; stack shifting adjustment</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <layout class="QGridLayout" name="gridLayout_4">
+            <property name="horizontalSpacing">
+             <number>10</number>
+            </property>
+            <property name="verticalSpacing">
+             <number>0</number>
+            </property>
+            <item row="1" column="1">
+             <widget class="QLabel" name="label_7">
+              <property name="text">
+               <string>Size:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QLabel" name="label_6">
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>25</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>25</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Method:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="2">
+             <widget class="QSpinBox" name="spinBoxFiltersize">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="minimum">
+               <number>1</number>
+              </property>
+              <property name="value">
+               <number>2</number>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="4">
+             <layout class="QHBoxLayout" name="horizontalLayout_5">
+              <property name="spacing">
+               <number>0</number>
+              </property>
+              <property name="sizeConstraint">
+               <enum>QLayout::SetNoConstraint</enum>
+              </property>
+              <item>
+               <widget class="QCheckBox" name="cb_autoerror">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>16777215</width>
+                  <height>25</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>Auto quality filter</string>
+                </property>
+                <property name="checked">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QLabel" name="label_5">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>16777215</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>|  Threshold: </string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QDoubleSpinBox" name="spinBoxError">
+                <property name="maximumSize">
+                 <size>
+                  <width>60</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="decimals">
+                 <number>4</number>
+                </property>
+                <property name="maximum">
+                 <double>1.000000000000000</double>
+                </property>
+                <property name="singleStep">
+                 <double>0.002000000000000</double>
+                </property>
+                <property name="value">
+                 <double>1.000000000000000</double>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item row="0" column="2">
+             <widget class="QComboBox" name="comboBox_approx">
+              <item>
+               <property name="text">
+                <string>Moving average</string>
+               </property>
+              </item>
+              <item>
+               <property name="text">
+                <string>Linear regression</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item row="1" column="4">
+             <layout class="QHBoxLayout" name="horizontalLayout_6">
+              <item>
+               <widget class="QCheckBox" name="cb_autocrop">
+                <property name="text">
+                 <string>Auto-crop stack</string>
+                </property>
+                <property name="checked">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QCheckBox" name="cb_extrapolate">
+                <property name="text">
+                 <string>Fit extrapolation</string>
+                </property>
+                <property name="checked">
+                 <bool>false</bool>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item row="0" column="3">
+             <widget class="Line" name="line">
+              <property name="frameShadow">
+               <enum>QFrame::Plain</enum>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="3">
+             <widget class="Line" name="line_2">
+              <property name="frameShadow">
+               <enum>QFrame::Plain</enum>
+              </property>
+              <property name="orientation">
+               <enum>Qt::Vertical</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="1" column="0">
+      <layout class="QGridLayout" name="gridLayout_5" rowstretch="0,0" rowminimumheight="0,0">
+       <property name="bottomMargin">
+        <number>0</number>
+       </property>
+       <property name="horizontalSpacing">
+        <number>0</number>
+       </property>
+       <property name="verticalSpacing">
+        <number>6</number>
+       </property>
+       <item row="0" column="0">
+        <widget class="QGroupBox" name="groupBox_3">
+         <property name="minimumSize">
+          <size>
+           <width>0</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>16777215</width>
+           <height>120</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="title">
+          <string>Pre-alignment filter</string>
+         </property>
+         <layout class="QVBoxLayout" name="verticalLayout_2">
+          <property name="spacing">
+           <number>0</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <layout class="QGridLayout" name="gridLayout_3">
+            <property name="horizontalSpacing">
+             <number>10</number>
+            </property>
+            <property name="verticalSpacing">
+             <number>0</number>
+            </property>
+            <item row="1" column="0">
+             <widget class="QLabel" name="label_2">
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>25</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>25</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Correlation anchor:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QRadioButton" name="rB_referenced">
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>25</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>reference image</string>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0">
+             <widget class="QLabel" name="label">
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>25</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Noise ruggedness:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="2">
+             <widget class="QRadioButton" name="rB_consecutive">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="text">
+               <string>neighbor</string>
+              </property>
+              <property name="checked">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <layout class="QHBoxLayout" name="horizontalLayout_7">
+              <property name="rightMargin">
+               <number>6</number>
+              </property>
+              <item>
+               <widget class="QDoubleSpinBox" name="spinBoxGauss">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>25</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>60</width>
+                  <height>25</height>
+                 </size>
+                </property>
+                <property name="decimals">
+                 <number>1</number>
+                </property>
+                <property name="singleStep">
+                 <double>0.500000000000000</double>
+                </property>
+                <property name="value">
+                 <double>1.000000000000000</double>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QLabel" name="label_3">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>25</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>16777215</width>
+                  <height>25</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>(Gaussian sigma)</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QPushButton" name="button_rstroi">
+           <property name="font">
+            <font>
+             <family>Ubuntu</family>
+             <pointsize>8</pointsize>
+            </font>
+           </property>
+           <property name="text">
+            <string>Reset alignment &amp;&amp; ROI</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="button_align">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+           <property name="font">
+            <font>
+             <family>Ubuntu</family>
+             <pointsize>8</pointsize>
+            </font>
+           </property>
+           <property name="text">
+            <string>Align</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>GraphicsView</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+  <customwidget>
+   <class>GraphicsLayoutWidget</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mantis_xray/showartefacts.ui b/mantis_xray/showartefacts.ui
new file mode 100755
index 0000000..95b3ea5
--- /dev/null
+++ b/mantis_xray/showartefacts.ui
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Artefacts</class>
+ <widget class="QWidget" name="Artefacts">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>900</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="1" column="1">
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <item>
+        <widget class="QPushButton" name="button_ok">
+         <property name="text">
+          <string>Accept</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="button_cancel">
+         <property name="text">
+          <string>Cancel</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="0" column="0">
+      <widget class="QGroupBox" name="groupBox">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>100</width>
+         <height>100</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Stack Browser</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="GraphicsView" name="canvas"/>
+        </item>
+        <item>
+         <widget class="QScrollBar" name="slider_eng">
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="toolTip">
+           <string>Keep left mouse button pressed to toggle view</string>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QGroupBox" name="groupBox_2">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>250</width>
+         <height>16777215</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Artefacts &amp;&amp; Leveling</string>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <widget class="QGroupBox" name="groupBox_3">
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="title">
+           <string>Background leveling</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_3">
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout">
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <property name="bottomMargin">
+              <number>0</number>
+             </property>
+             <item>
+              <layout class="QVBoxLayout" name="verticalLayout_4">
+               <property name="bottomMargin">
+                <number>0</number>
+               </property>
+               <item>
+                <widget class="QLabel" name="label">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Method:</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="rb_median">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Median</string>
+                 </property>
+                 <property name="checked">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QRadioButton" name="rb_median_i0">
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Median (I0 masked)</string>
+                 </property>
+                 <property name="checkable">
+                  <bool>false</bool>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item>
+              <layout class="QVBoxLayout" name="verticalLayout_5">
+               <item>
+                <widget class="QLabel" name="label_2">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Direction:</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QCheckBox" name="cb_h">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Horizontal</string>
+                 </property>
+                 <property name="checked">
+                  <bool>false</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QCheckBox" name="cb_v">
+                 <property name="minimumSize">
+                  <size>
+                   <width>0</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="maximumSize">
+                  <size>
+                   <width>16777215</width>
+                   <height>15</height>
+                  </size>
+                 </property>
+                 <property name="font">
+                  <font>
+                   <family>Ubuntu</family>
+                   <pointsize>8</pointsize>
+                  </font>
+                 </property>
+                 <property name="text">
+                  <string>Vertical</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <widget class="QWidget" name="sliderWidget" native="true">
+             <property name="font">
+              <font>
+               <family>Ubuntu</family>
+               <pointsize>8</pointsize>
+              </font>
+             </property>
+             <layout class="QVBoxLayout" name="verticalLayout_6">
+              <property name="spacing">
+               <number>0</number>
+              </property>
+              <property name="leftMargin">
+               <number>0</number>
+              </property>
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <property name="rightMargin">
+               <number>0</number>
+              </property>
+              <property name="bottomMargin">
+               <number>0</number>
+              </property>
+              <item>
+               <widget class="QLabel" name="label_4">
+                <property name="font">
+                 <font>
+                  <family>Ubuntu</family>
+                  <pointsize>8</pointsize>
+                 </font>
+                </property>
+                <property name="text">
+                 <string>Textlabel</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <layout class="QHBoxLayout" name="horizontalLayout_3">
+                <property name="topMargin">
+                 <number>8</number>
+                </property>
+                <item>
+                 <widget class="QSlider" name="weight_slider">
+                  <property name="font">
+                   <font>
+                    <family>Ubuntu</family>
+                    <pointsize>8</pointsize>
+                   </font>
+                  </property>
+                  <property name="maximum">
+                   <number>100</number>
+                  </property>
+                  <property name="pageStep">
+                   <number>1</number>
+                  </property>
+                  <property name="value">
+                   <number>100</number>
+                  </property>
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QLabel" name="label_3">
+                  <property name="minimumSize">
+                   <size>
+                    <width>30</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                  <property name="maximumSize">
+                   <size>
+                    <width>30</width>
+                    <height>16777215</height>
+                   </size>
+                  </property>
+                  <property name="font">
+                   <font>
+                    <family>Ubuntu</family>
+                    <pointsize>8</pointsize>
+                   </font>
+                  </property>
+                  <property name="text">
+                   <string>TextLabel</string>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </item>
+             </layout>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="Line" name="line">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="verticalSpacer">
+          <property name="orientation">
+           <enum>Qt::Vertical</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>20</width>
+            <height>40</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>GraphicsView</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mantis_xray/showhistogram.ui b/mantis_xray/showhistogram.ui
old mode 100644
new mode 100755
index 182146e..1b00e65
--- a/mantis_xray/showhistogram.ui
+++ b/mantis_xray/showhistogram.ui
@@ -28,6 +28,21 @@
         <string>Select I0 from histogram</string>
        </property>
        <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
         <item>
          <widget class="PlotWidget" name="HistoWidget"/>
         </item>
@@ -70,6 +85,21 @@
         <string>Select I0 from image</string>
        </property>
        <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
         <item>
          <widget class="GraphicsLayoutWidget" name="I0Widget"/>
         </item>
@@ -137,6 +167,9 @@
        </item>
        <item row="1" column="2">
         <widget class="QRadioButton" name="radioPolyROI">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
          <property name="text">
           <string>Polygon ROI</string>
          </property>
@@ -171,7 +204,7 @@
   <customwidget>
    <class>GraphicsLayoutWidget</class>
    <extends>QGraphicsView</extends>
-   <header>pyqtgraph</header>
+   <header location="global">pyqtgraph</header>
   </customwidget>
   <customwidget>
    <class>PlotWidget</class>
diff --git a/mantis_xray/showmulticrop.ui b/mantis_xray/showmulticrop.ui
new file mode 100644
index 0000000..2ae0d34
--- /dev/null
+++ b/mantis_xray/showmulticrop.ui
@@ -0,0 +1,700 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MultiLimit</class>
+ <widget class="QWidget" name="MultiLimit">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1024</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="1" column="0">
+      <widget class="QScrollBar" name="slider_theta">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="0">
+      <widget class="QGroupBox" name="groupBox">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>100</width>
+         <height>100</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Stack Browser</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_4">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="GraphicsView" name="canvas"/>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="2" column="2">
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label_ev_range">
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="text">
+          <string>Energy range:</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="button_ok">
+         <property name="minimumSize">
+          <size>
+           <width>140</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>140</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="text">
+          <string>Accept</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="2" column="0">
+      <layout class="QHBoxLayout" name="horizontalLayout_5">
+       <item>
+        <widget class="QPushButton" name="button_rstroi">
+         <property name="minimumSize">
+          <size>
+           <width>140</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>140</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="text">
+          <string>Reset ROI</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="label_spatial_range">
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="text">
+          <string>Stack size:</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="0" column="2">
+      <widget class="QGroupBox" name="groupBox_3">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>Spectrum inside ROI</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="PlotWidget" name="spectrum_plotwidget"/>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="2" column="3">
+      <widget class="QPushButton" name="button_cancel">
+       <property name="minimumSize">
+        <size>
+         <width>140</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>16777215</width>
+         <height>16777215</height>
+        </size>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="text">
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <layout class="QVBoxLayout" name="verticalLayout_5">
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Maximum</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>8</width>
+           <height>15</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QScrollBar" name="slider_eng">
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="toolTip">
+          <string>Keep left mouse button pressed to toggle view</string>
+         </property>
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="1" column="2">
+      <widget class="QLabel" name="label_theta_range">
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="text">
+        <string>Theta range: </string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="3">
+      <widget class="QWidget" name="verticalWidget" native="true">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>16777215</width>
+         <height>16777215</height>
+        </size>
+       </property>
+       <property name="layoutDirection">
+        <enum>Qt::LeftToRight</enum>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_3">
+        <property name="sizeConstraint">
+         <enum>QLayout::SetNoConstraint</enum>
+        </property>
+        <property name="leftMargin">
+         <number>1</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QGroupBox" name="groupBox_ev">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>16777215</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="title">
+           <string>Image #        Energy [eV]</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_2">
+           <property name="leftMargin">
+            <number>2</number>
+           </property>
+           <property name="topMargin">
+            <number>2</number>
+           </property>
+           <property name="rightMargin">
+            <number>2</number>
+           </property>
+           <property name="bottomMargin">
+            <number>2</number>
+           </property>
+           <item>
+            <widget class="QListWidget" name="ev_widget">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="maximumSize">
+              <size>
+               <width>16777215</width>
+               <height>16777215</height>
+              </size>
+             </property>
+             <property name="palette">
+              <palette>
+               <active>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="127">
+                   <red>85</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </active>
+               <inactive>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="127">
+                   <red>85</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>0</red>
+                   <green>0</green>
+                   <blue>0</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </inactive>
+               <disabled>
+                <colorrole role="Highlight">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="0">
+                   <red>51</red>
+                   <green>153</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+                <colorrole role="HighlightedText">
+                 <brush brushstyle="SolidPattern">
+                  <color alpha="255">
+                   <red>255</red>
+                   <green>255</green>
+                   <blue>255</blue>
+                  </color>
+                 </brush>
+                </colorrole>
+               </disabled>
+              </palette>
+             </property>
+             <property name="font">
+              <font>
+               <family>Ubuntu</family>
+               <pointsize>8</pointsize>
+              </font>
+             </property>
+             <property name="focusPolicy">
+              <enum>Qt::NoFocus</enum>
+             </property>
+             <property name="styleSheet">
+              <string notr="true"/>
+             </property>
+             <property name="frameShape">
+              <enum>QFrame::NoFrame</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Plain</enum>
+             </property>
+             <property name="lineWidth">
+              <number>0</number>
+             </property>
+             <property name="midLineWidth">
+              <number>0</number>
+             </property>
+             <property name="horizontalScrollBarPolicy">
+              <enum>Qt::ScrollBarAlwaysOff</enum>
+             </property>
+             <property name="editTriggers">
+              <set>QAbstractItemView::NoEditTriggers</set>
+             </property>
+             <property name="showDropIndicator" stdset="0">
+              <bool>false</bool>
+             </property>
+             <property name="dragDropMode">
+              <enum>QAbstractItemView::NoDragDrop</enum>
+             </property>
+             <property name="defaultDropAction">
+              <enum>Qt::CopyAction</enum>
+             </property>
+             <property name="alternatingRowColors">
+              <bool>false</bool>
+             </property>
+             <property name="selectionMode">
+              <enum>QAbstractItemView::NoSelection</enum>
+             </property>
+             <property name="selectionBehavior">
+              <enum>QAbstractItemView::SelectItems</enum>
+             </property>
+             <property name="movement">
+              <enum>QListView::Static</enum>
+             </property>
+             <property name="isWrapping" stdset="0">
+              <bool>false</bool>
+             </property>
+             <property name="viewMode">
+              <enum>QListView::ListMode</enum>
+             </property>
+             <property name="selectionRectVisible">
+              <bool>false</bool>
+             </property>
+             <property name="sortingEnabled">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <widget class="QGroupBox" name="groupBox_theta">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>16777215</width>
+            <height>16777215</height>
+           </size>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="title">
+           <string>Angle #        Theta [°]</string>
+          </property>
+          <property name="alignment">
+           <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_4">
+           <property name="leftMargin">
+            <number>2</number>
+           </property>
+           <property name="topMargin">
+            <number>2</number>
+           </property>
+           <property name="rightMargin">
+            <number>2</number>
+           </property>
+           <property name="bottomMargin">
+            <number>2</number>
+           </property>
+           <item>
+            <widget class="QListWidget" name="theta_widget">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="frameShape">
+              <enum>QFrame::NoFrame</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Plain</enum>
+             </property>
+             <property name="lineWidth">
+              <number>0</number>
+             </property>
+             <property name="horizontalScrollBarPolicy">
+              <enum>Qt::ScrollBarAlwaysOff</enum>
+             </property>
+             <property name="editTriggers">
+              <set>QAbstractItemView::NoEditTriggers</set>
+             </property>
+             <property name="showDropIndicator" stdset="0">
+              <bool>false</bool>
+             </property>
+             <property name="selectionMode">
+              <enum>QAbstractItemView::NoSelection</enum>
+             </property>
+             <property name="sortingEnabled">
+              <bool>true</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QPushButton" name="pb_selectall">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>Select all</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QPushButton" name="pb_clearall">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="font">
+             <font>
+              <family>Ubuntu</family>
+              <pointsize>8</pointsize>
+             </font>
+            </property>
+            <property name="text">
+             <string>Clear all</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="cb_croptoroi">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>Crop stack to ROI</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="cb_remove_evs">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>Remove unsel. energies</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="cb_remove_theta">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="font">
+           <font>
+            <family>Ubuntu</family>
+            <pointsize>8</pointsize>
+           </font>
+          </property>
+          <property name="text">
+           <string>Remove unsel. angles</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>GraphicsView</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+  <customwidget>
+   <class>PlotWidget</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mantis_xray/showspectralroi.ui b/mantis_xray/showspectralroi.ui
new file mode 100644
index 0000000..e013d08
--- /dev/null
+++ b/mantis_xray/showspectralroi.ui
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SpectralMap</class>
+ <widget class="QWidget" name="SpectralMap">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="0" column="0">
+      <widget class="QGroupBox" name="groupBox_3">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="font">
+        <font>
+         <family>Ubuntu</family>
+         <pointsize>8</pointsize>
+        </font>
+       </property>
+       <property name="title">
+        <string>ROI selection from Spectrum</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="PlotWidget" name="spectrum_plotwidget"/>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <item>
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="button_ok">
+         <property name="minimumSize">
+          <size>
+           <width>140</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>140</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="text">
+          <string>Accept</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="button_cancel">
+         <property name="minimumSize">
+          <size>
+           <width>140</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>16777215</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="font">
+          <font>
+           <family>Ubuntu</family>
+           <pointsize>8</pointsize>
+          </font>
+         </property>
+         <property name="text">
+          <string>Cancel</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>PlotWidget</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">pyqtgraph</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/mantis_xray/stylesheet_global.qss b/mantis_xray/stylesheet_global.qss
new file mode 100644
index 0000000..8ba8989
--- /dev/null
+++ b/mantis_xray/stylesheet_global.qss
@@ -0,0 +1,27 @@
+QPushButton {
+    font: 11px "Ubuntu";
+}
+QTabWidget {
+    font: 11px "Ubuntu";
+}
+QGroupBox {
+    font: 11px "Ubuntu";
+}
+QComboBox {
+    font: 11px "Ubuntu";
+}
+QCheckBox {
+    font: 11px "Ubuntu";
+}
+QLabel {
+    font: 11px "Ubuntu";
+}
+QSpinBox {
+    font: 11px "Ubuntu";
+}
+QDoubleSpinBox {
+    font: 11px "Ubuntu";
+}
+QWidget {
+    font: 11px "Ubuntu";
+}
\ No newline at end of file
diff --git a/setup.py b/setup.py
index c789931..0741add 100644
--- a/setup.py
+++ b/setup.py
@@ -17,11 +17,9 @@ setuptools.setup(
         "Code": "https://github.com/mlerotic/spectromicroscopy",
         "Documentation": "https://docs.spectromicroscopy.com",
     },
-    install_requires=['PyQt5','numpy', 'scipy','matplotlib','h5py','Pillow','lxml','pyqtgraph'],
+    install_requires=['PyQt5','numpy', 'scipy', 'matplotlib', 'h5py', 'Pillow', 'lxml', 'pyqtgraph', "scikit-image"],
     extras_require={
-        "netCDF":  "netcdf4-python",
-        "SIRT":    "scikit-image"
-    },
+        "netCDF":  "netcdf4-python"},
     entry_points={
         "gui_scripts": "mantis-xray = mantis_xray.mantis_qt:main"},
     classifiers=[