diff --git a/docker/apmtools/APT_analyzer.ipynb b/docker/apmtools/APT_analyzer.ipynb
deleted file mode 100644
index a329a8d0b1787c5f3081d6be1edd4611d60d1ecb..0000000000000000000000000000000000000000
--- a/docker/apmtools/APT_analyzer.ipynb
+++ /dev/null
@@ -1,1214 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "c15820a3",
-   "metadata": {
-    "scrolled": true
-   },
-   "outputs": [],
-   "source": [
-    "%reset -f\n",
-    "from tkinter import *\n",
-    "from tkinter.ttk import Combobox\n",
-    "from tkinter import messagebox\n",
-    "from tkinter import filedialog\n",
-    "import matplotlib.pyplot as plt\n",
-    "from matplotlib.figure import Figure\n",
-    "from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)\n",
-    "import numpy as np\n",
-    "import apt_importers as apt\n",
-    "import math\n",
-    "from matplotlib import gridspec\n",
-    "import re\n",
-    "from tkinter.filedialog import asksaveasfile\n",
-    "import tkinter.scrolledtext as tkst\n",
-    "import webbrowser\n",
-    "from mpl_toolkits.mplot3d import proj3d\n",
-    "import pandas as pd\n",
-    "import h5py\n",
-    "\n",
-    "def data_for_cylinder_along_z(center_x,center_y,center_z,radius,height_z):\n",
-    "    z = np.linspace(center_z-height_z/2, center_z+height_z/2, 50)\n",
-    "    theta = np.linspace(0, 2*np.pi, 50)\n",
-    "    theta_grid, z_grid=np.meshgrid(theta, z)\n",
-    "    x_grid = radius*np.cos(theta_grid) + center_x\n",
-    "    y_grid = radius*np.sin(theta_grid) + center_y\n",
-    "    return x_grid,y_grid,z_grid\n",
-    "\n",
-    "def gerade(k,x,d):\n",
-    "    return k*x+d\n",
-    "\n",
-    "class APT_analyzer():                                                          # define class object \n",
-    "    def __init__(self,tk):                                                     # initialize when starting tkinter\n",
-    "        self.plot_exist=0\n",
-    "        self.conc_check=0\n",
-    "        self.excess_check=0\n",
-    "        self.invert=0\n",
-    "        self.data_color=['blue','red','green','yellow','purple','black','white','grey','brown'] # colors of cylinder to be seletected\n",
-    "        self.color_cp=['blue','red','green','yellow','purple','black','white','grey','brown']\n",
-    "        self.frame=Frame(tk)                                                   # setting up frame\n",
-    "        self.frame.pack(expand=True,fill=BOTH)                                 # placing frame\n",
-    "        self.canvas_all=Canvas(self.frame,width=1400,height=800,scrollregion=(0,0,1550,850))     #setting up canvas onto frame\n",
-    "        ################# scroll bars vertical and horizontal  ################\n",
-    "        self.hbar=Scrollbar(self.frame,orient=HORIZONTAL)                      # setting up horizontal scrollbar\n",
-    "        self.hbar.pack(side=TOP,fill=X)                                        # placing horizontal scrollbar on the top side\n",
-    "        self.hbar.config(command=self.canvas_all.xview)                        # configurating horizontal scrollbar\n",
-    "        self.vbar=Scrollbar(self.frame,orient=VERTICAL)                        # setting up vertical scrollbar\n",
-    "        self.vbar.pack(side=LEFT,fill=Y)                                       # placing vertical scrollbar on the left side\n",
-    "        self.vbar.config(command=self.canvas_all.yview)                        # configurating vertical scrollbar\n",
-    "        self.canvas_all.config(yscrollcommand=self.vbar.set,xscrollcommand=self.hbar.set)       #configurating canvas\n",
-    "        \n",
-    "\n",
-    "        self.b_page1_loading = Button(self.canvas_all, text=\"1. Load\", command=self.page_1,font=('helvetica',12,'bold')) # button for tip calculation\n",
-    "        self.canvas_all.create_window(75,20,window=self.b_page1_loading)\n",
-    "        \n",
-    "        self.b_page2_visualize = Button(self.canvas_all, text=\"2. Visualize\", command=self.page_2,font=('helvetica',12,'bold')) # button for tip calculation\n",
-    "        self.canvas_all.create_window(180,20,window=self.b_page2_visualize)\n",
-    "        \n",
-    "        self.b_page3_cylinder = Button(self.canvas_all, text=\"3. Calculate\", command=self.page_3,font=('helvetica',12,'bold')) # button for tip calculation\n",
-    "        self.canvas_all.create_window(300,20,window=self.b_page3_cylinder)\n",
-    "\n",
-    "        ############## initiate values #######################################\n",
-    "        #### page 1 ####  \n",
-    "        self.succ=0\n",
-    "        self.utext0=Label(self.canvas_all,text='Welcome to the APT-analyzer!')    # title of segment\n",
-    "        self.utext1=Label(self.canvas_all,text='This open source tool enables you to look at and analyze APT tips ')    # title of segment\n",
-    "        self.utext2=Label(self.canvas_all,text='All you need is a .pos (or .epos) file and a .rrng file')    # title of segment\n",
-    "        self.utext3=Label(self.canvas_all,text='Select the files you want to look at below and press \"Load files\"')    # title of segment\n",
-    "        self.utext4=Label(self.canvas_all,text='------------- Initiate files --------------')    # title of segment\n",
-    "        self.b_pos_file = Button(self.canvas_all,bg='green',fg='white', text=\"Select .pos /.epos file\", command=self.search_pos)        # button for pos file initiation\n",
-    "        self.b_rrng_file = Button(self.canvas_all,bg='green',fg='white', text=\"Select .rrng file\", command=self.search_rrng)             # button for rrng file initiation\n",
-    "        self.b_calc_tip = Button(self.canvas_all, text=\"Load files\", command=self.calculate_tip,bg='blue',fg='white',font=('helvetica',14,'bold')) # button for tip calculation\n",
-    "        self.dtext0=Label(self.canvas_all,text='The loading of the files may take some time.')    # title of segment\n",
-    "        self.dtext1=Label(self.canvas_all,text='When \"Sucessfully loaded files!\" appears underneath the Load button')    # title of segment\n",
-    "        self.dtext2=Label(self.canvas_all,text='then everthing is working as intendet')    # title of segment\n",
-    "        self.dtext3=Label(self.canvas_all,text='and a preview image of the tip should appear on the right')    # title of segment   \n",
-    "        self.dtext4=Label(self.canvas_all,text='You may now go to section 2.Visualize (top middle)')    # title of segment\n",
-    "        self.dtext5=Label(self.canvas_all,text='where you have more options for the visalization')    # title of segment\n",
-    "        self.dtext6=Label(self.canvas_all,text='as well as the ability to set control points and print them')    # title of segment\n",
-    "        self.dtext7=Label(self.canvas_all,text='After that you can go to section 3.Calculate (top right)')    # title of segment\n",
-    "        self.dtext8=Label(self.canvas_all,text='To calculate the concentration profile and excess profile')    # title of segment\n",
-    "        self.dtext9=Label(self.canvas_all,text='of a cylinder area which you can select within the tip')    # title of segment\n",
-    "        self.label_help=Label(self.canvas_all,text='if you need help press this button:')    # title of segment\n",
-    "        self.b_help = Button(self.canvas_all, text=\"help\",bg='orange',fg='black',command=self.help_web,font=('helvetica',14,'bold')) # button for tip calculation\n",
-    "        \n",
-    "        #### page 2 ####\n",
-    "        self.cb_atom = Combobox(tk, values='') \n",
-    "\n",
-    "        self.diss=0\n",
-    "        self.diss2=0\n",
-    "        self.slider_image_size_cv=DoubleVar()\n",
-    "        self.slider_image_size = Scale(self.canvas_all,from_=1,to=5,orient='horizontal',variable=self.slider_image_size_cv,showvalue=0)\n",
-    "        self.label_plot_tip=Label(self.canvas_all,text='------------- plot options ---------------')    # title of segment\n",
-    "        self.label_image_size=Label(self.canvas_all,text='Select image size')                     # label for resolution\n",
-    "        self.label_slider_res=Label(self.canvas_all,text='small')\n",
-    "        self.label_slider_res2=Label(self.canvas_all,text='large')     \n",
-    "        self.slider_image_size.set(3)\n",
-    "        self.b_plot1 = Button(self.canvas_all, text=\"plot tip\", command=self.plot_tip,bg='blue',fg='white',font=('helvetica',14,'bold')) # button for plotting the tip\n",
-    "        self.var_axis=IntVar()\n",
-    "        self.check_axis = Checkbutton(self.canvas_all,text=\"Hide Axes\", onvalue=1, offvalue=0,variable=self.var_axis,font=('helvetica', 10,'bold'))\n",
-    "        self.label_resolution=Label(self.canvas_all,text='Select number of atoms')                     # label for resolution\n",
-    "        self.label_select_atom=Label(self.canvas_all,text='Select atom type')\n",
-    "        self.slider_res_cv=DoubleVar()\n",
-    "        self.label_slider_res3=Label(self.canvas_all,text='small')\n",
-    "        self.label_slider_res4=Label(self.canvas_all,text='large')\n",
-    "        self.slider_res = Scale(self.canvas_all,from_=1,to=5,orient='horizontal',variable=self.slider_res_cv,showvalue=0)\n",
-    "        self.slider_res.set(1)\n",
-    "        self.label_select_atom_size=Label(self.canvas_all,text='Select atom size')\n",
-    "        self.slider_size_cv=DoubleVar()\n",
-    "        self.slider_size = Scale(self.canvas_all,from_=1,to=200,orient='horizontal',variable=self.slider_size_cv,showvalue=0)\n",
-    "        self.label_slider_res5=Label(self.canvas_all,text='small')\n",
-    "        self.label_slider_res6=Label(self.canvas_all,text='large')  \n",
-    "        self.slider_size.set(50)\n",
-    "        self.i_plot=IntVar()\n",
-    "        self.cb_inverse=Checkbutton(self.canvas_all, text='Flip Tip', onvalue=1, offvalue=0, variable=self.i_plot, font=('helvetica', 10,'bold'))   \n",
-    "        self.control=IntVar()\n",
-    "        self.label_control=Checkbutton(self.canvas_all, text='create control points by clicking on screen', onvalue=1, offvalue=0, variable=self.control, font=('helvetica', 10,'bold'))    \n",
-    "        self.text_box = Text(self.canvas_all,height=10, width=35)\n",
-    "        self.b_control_print = Button(self.canvas_all, text=\"print\",bg='green', command=self.save,fg='white',font=('helvetica',12,'bold'))        # button for pos file initiation\n",
-    "        self.b_control_clear = Button(self.canvas_all, text=\"clear\",bg='red', command=self.clear_text,fg='white',font=('helvetica',12,'bold'))        # button for pos file initiation\n",
-    "        self.var_points=IntVar()\n",
-    "        self.check_points = Checkbutton(self.canvas_all,text=\"plot with points\", onvalue=1, offvalue=0,variable=self.var_points,font=('helvetica', 10,'bold'))\n",
-    "        self.b_adjust_cly = Button(self.canvas_all, text=\"adjust cylinder according to points\",bg='yellow',fg='black', command=self.adjust,font=('helvetica',10,'bold'))        # button for pos file initiation     \n",
-    "        self.cb_color_cp = Combobox(tk, values=self.color_cp, width=10) \n",
-    "        self.cb_color_cp.current(0)\n",
-    "        self.var_plane=IntVar()\n",
-    "        self.label_color_cp=Label(self.canvas_all,text='color of control points')  \n",
-    "        self.check_plane = Checkbutton(self.canvas_all,text=\"show fit plane and normal vector\", onvalue=1, offvalue=0,variable=self.var_plane,font=('helvetica', 10,'bold'))\n",
-    "        \n",
-    "        #### page 3 ####\n",
-    "        self.var_cyl=IntVar()\n",
-    "        self.label_conc=Label(self.canvas_all,text='------------ concentration calculation option  ------------')#.place(x=20,y=400)    # title of segment\n",
-    "        self.var_cyl=IntVar()\n",
-    "        self.check_cylinder = Checkbutton(self.canvas_all,text=\"show cylinder for concentration calculation\", onvalue=1, offvalue=0,variable=self.var_cyl,font=('helvetica', 10,'bold'))#.place(x=20,y=220)\n",
-    "        \n",
-    "        self.b_calc_conc = Button(self.canvas_all, text=\"plot concentration\", command=self.calc_con,bg='blue',fg='white',font=('helvetica',12,'bold'))   # button for calculating the concentration of cylinder\n",
-    "        self.b_calc_excess = Button(self.canvas_all, text=\"plot excess\", command=self.calc_excess,bg='blue',fg='white',font=('helvetica',12,'bold'))    # button for calculating the concentration of cylinder\n",
-    "        self.b_plot_cyl = Button(self.canvas_all, text=\"plot cylinder\", command=self.calc_zoom,bg='blue',fg='white',font=('helvetica',13,'bold'))  # button for calculating the concentration of cylinder\n",
-    "        self.b_print_ex = Button(self.canvas_all, text=\"print excess\", command=self.save_excess,bg='green',fg='white',font=('helvetica',13,'bold'))    # button for calculating the concentration of cylinder\n",
-    "        \n",
-    "        self.label_cly_pos=Label(self.canvas_all,text='cylinder center position')\n",
-    "        self.label_cly_x=Label(self.canvas_all,text='x')\n",
-    "        self.cly_x=StringVar(value='0')\n",
-    "        self.entry_cly_x=Entry(self.canvas_all,textvariable=self.cly_x,width=10)        \n",
-    "        self.label_cly_y=Label(self.canvas_all,text='y') \n",
-    "        self.cly_y=StringVar(value='0')\n",
-    "        self.entry_cly_y=Entry(self.canvas_all,textvariable=self.cly_y,width=10)        \n",
-    "        self.label_cly_z=Label(self.canvas_all,text='z')\n",
-    "        self.cly_z=StringVar(value='0')\n",
-    "        self.entry_cly_z=Entry(self.canvas_all,textvariable=self.cly_z,width=10)\n",
-    "        self.label_cly_radius=Label(self.canvas_all,text='radius of cylinder')  \n",
-    "        self.radius=StringVar(value='10')\n",
-    "        self.entry_cly_radius=Entry(self.canvas_all,textvariable=self.radius)        \n",
-    "        self.label_cly_height=Label(self.canvas_all,text='height of cylinder') \n",
-    "        self.height=StringVar(value='30')\n",
-    "        self.entry_cly_height=Entry(self.canvas_all,textvariable=self.height)        \n",
-    "        self.label_cly_beta=Label(self.canvas_all,text='tilt along x-axis')\n",
-    "        self.beta=StringVar(value='0')\n",
-    "        self.entry_cly_beta=Entry(self.canvas_all,textvariable=self.beta)\n",
-    "        self.label_cly_alpha=Label(self.canvas_all,text='tilt along y-axis')\n",
-    "        self.alpha=StringVar(value='0')\n",
-    "        self.entry_cly_alpha=Entry(self.canvas_all,textvariable=self.alpha)\n",
-    "        self.label_color_cyl=Label(self.canvas_all,text='color of the cylinder')   # label for cylinder color\n",
-    "        self.cb_color = Combobox(self.canvas_all, values=self.data_color)\n",
-    "        self.cb_color.current(0)            \n",
-    "        self.label_inter=Label(self.canvas_all,text='Select interval')      # label for resolution\n",
-    "        self.slider_inter_cv=DoubleVar()\n",
-    "        self.label_slider_inter=Label(self.canvas_all,text='small                 large')    # title of segment\n",
-    "        self.slider_inter = Scale(self.canvas_all,from_=1,to=20,orient='horizontal',variable=self.slider_inter_cv,showvalue=0)#Combobox(self.canvas_all, values=self.data_res)                                                            # combobox for resolution\n",
-    "        self.slider_inter.set(15)\n",
-    "        self.b_plot2 = Button(self.canvas_all, text=\"plot tip\", command=self.plot_tip,bg='blue',fg='white',font=('helvetica',13,'bold')) # button for plotting the tip\n",
-    "        self.b_print_conc = Button(self.canvas_all, text=\"print concentration\", command=self.save_conc,bg='green',fg='white',font=('helvetica',13,'bold')) # button for plotting the tip\n",
-    "        self.var_norm=IntVar()\n",
-    "        self.check_norm = Checkbutton(self.canvas_all,text=\"normalize Excess\", onvalue=1, offvalue=0,variable=self.var_norm)\n",
-    "        self.var_switch=IntVar()\n",
-    "        self.check_switch = Checkbutton(self.canvas_all,text=\"set cylinders                  as bulk*\", onvalue=1, offvalue=0,variable=self.var_switch)\n",
-    "        self.label_astrix=Label(self.canvas_all,text='* the conc. of each segment is calculated in relation to the ends')  \n",
-    "        self.data_bulk=['start','end']\n",
-    "        self.cb_bulk = Combobox(tk, values=self.data_bulk, width=4) \n",
-    "        self.cb_bulk.current(0)\n",
-    "        self.text_box_ex = Text(self.canvas_all,height=6, width=25)\n",
-    "        #self.cb_exp=Checkbutton(self.canvas_all, text='create points for excess calculation', onvalue=1, offvalue=0, variable=self.control, font=('helvetica', 10,'bold'))    \n",
-    "        self.label_exp=Label(self.canvas_all,text='For calcuating the excess select 4 points')  \n",
-    "        \n",
-    "        \n",
-    "        ############## setting up page 1 ##################\n",
-    "        self.a1=self.canvas_all.create_window(200,50,window=self.utext0)        \n",
-    "        self.a2=self.canvas_all.create_window(200,70,window=self.utext1)        \n",
-    "        self.a3=self.canvas_all.create_window(200,90,window=self.utext2)        \n",
-    "        self.a4=self.canvas_all.create_window(200,110,window=self.utext3)        \n",
-    "        self.a5=self.canvas_all.create_window(200,140,window=self.utext4)  \n",
-    "        self.a6=self.canvas_all.create_window(120,165,window=self.b_pos_file) \n",
-    "        self.a7=self.canvas_all.create_window(280,165,window=self.b_rrng_file) \n",
-    "        self.a8=self.canvas_all.create_window(200,230,window=self.b_calc_tip)\n",
-    "        self.a9=self.canvas_all.create_window(200,300,window=self.dtext0)        \n",
-    "        self.a10=self.canvas_all.create_window(200,320,window=self.dtext1)  \n",
-    "        self.a11=self.canvas_all.create_window(200,340,window=self.dtext2)   \n",
-    "        self.a12=self.canvas_all.create_window(200,360,window=self.dtext3)   \n",
-    "        self.a13=self.canvas_all.create_window(200,400,window=self.dtext4)        \n",
-    "        self.a14=self.canvas_all.create_window(200,420,window=self.dtext5)        \n",
-    "        self.a15=self.canvas_all.create_window(200,440,window=self.dtext6)\n",
-    "        self.a16=self.canvas_all.create_window(200,460,window=self.dtext7)\n",
-    "        self.a17=self.canvas_all.create_window(200,480,window=self.dtext8)\n",
-    "        self.a18=self.canvas_all.create_window(200,500,window=self.dtext9)\n",
-    "        self.a19=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a20=self.canvas_all.create_window(200,560,window=self.b_help)\n",
-    "        self.a21=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a22=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a23=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a24=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a25=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a26=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a27=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a28=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a29=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a30=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a31=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a32=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a33=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a34=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "            \n",
-    "        ###################### setup figures  #################################                        \n",
-    "        self.fig=Figure(figsize=(17,13))                                       # defining figure size\n",
-    "        self.canvas=FigureCanvasTkAgg(self.fig,master=self.canvas_all)         # setting up canvas for figure\n",
-    "        self.toolbar=NavigationToolbar2Tk(self.canvas, self.canvas_all)        # setting up toolbar for figure\n",
-    "        self.canvas_all.create_window(400,10,window=self.canvas.get_tk_widget(),anchor=N+W,tags='canvas') #placing figure canvas on general canvas\n",
-    "        self.canvas_all.pack(expand=True,fill=BOTH)                            # placing general canvas at the end\n",
-    "        self.E=2                                                               # setting up variable to check if .pos/.epos file is selected\n",
-    "        self.R=2                                                               # setting up variable to check if .rrng file is selected       \n",
-    "              \n",
-    "    def page_1(self):\n",
-    "        self.canvas_all.delete(self.a1,self.a2,self.a3,self.a4,self.a5,self.a6,self.a7,self.a8,self.a9,self.a10,self.a11,self.a12,self.a13,self.a14,self.a15,self.a16,self.a17,self.a18,self.a19,self.a20,self.a21,self.a22,self.a23,self.a24,self.a25,self.a26,self.a27,self.a28,self.a29,self.a30,self.a31,self.a32,self.a33,self.a34)        \n",
-    "        if self.succ==1:self.a_succ=self.canvas_all.create_window(200,260,window=self.label_succ) #placing label on canvas\n",
-    "        if self.R==1:self.aRS=self.canvas_all.create_window(280,190,window=self.label_rrng_selected)\n",
-    "        if self.R==0:self.aR=self.canvas_all.create_window(280,190,window=self.label_rrng_selected)\n",
-    "        if self.E==0:self.aE=self.canvas_all.create_window(120,190,window=self.label_pos_selected)\n",
-    "        if self.E==1:self.aES=self.canvas_all.create_window(120,190,window=self.label_pos_selected)\n",
-    "            \n",
-    "        self.a1=self.canvas_all.create_window(200,50,window=self.utext0)        \n",
-    "        self.a2=self.canvas_all.create_window(200,70,window=self.utext1)        \n",
-    "        self.a3=self.canvas_all.create_window(200,90,window=self.utext2)        \n",
-    "        self.a4=self.canvas_all.create_window(200,110,window=self.utext3)        \n",
-    "        self.a5=self.canvas_all.create_window(200,140,window=self.utext4)  \n",
-    "        self.a6=self.canvas_all.create_window(120,165,window=self.b_pos_file) \n",
-    "        self.a7=self.canvas_all.create_window(280,165,window=self.b_rrng_file) \n",
-    "        self.a8=self.canvas_all.create_window(200,230,window=self.b_calc_tip)\n",
-    "        self.a9=self.canvas_all.create_window(200,300,window=self.dtext0)        \n",
-    "        self.a10=self.canvas_all.create_window(200,320,window=self.dtext1)  \n",
-    "        self.a11=self.canvas_all.create_window(200,340,window=self.dtext2)   \n",
-    "        self.a12=self.canvas_all.create_window(200,360,window=self.dtext3)   \n",
-    "        self.a13=self.canvas_all.create_window(200,400,window=self.dtext4)        \n",
-    "        self.a14=self.canvas_all.create_window(200,420,window=self.dtext5)        \n",
-    "        self.a15=self.canvas_all.create_window(200,440,window=self.dtext6)\n",
-    "        self.a16=self.canvas_all.create_window(200,460,window=self.dtext7)\n",
-    "        self.a17=self.canvas_all.create_window(200,480,window=self.dtext8)\n",
-    "        self.a18=self.canvas_all.create_window(200,500,window=self.dtext9)\n",
-    "        self.a19=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a20=self.canvas_all.create_window(200,560,window=self.b_help)\n",
-    "        self.a21=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a22=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a23=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a24=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a25=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a26=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a27=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a28=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a29=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a30=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a31=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a32=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a33=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        self.a34=self.canvas_all.create_window(200,520,window=self.label_help)\n",
-    "        \n",
-    "    def page_2(self):\n",
-    "        self.canvas_all.delete(self.a1,self.a2,self.a3,self.a4,self.a5,self.a6,self.a7,self.a8,self.a9,self.a10,self.a11,self.a12,self.a13,self.a14,self.a15,self.a16,self.a17,self.a18,self.a19,self.a20,self.a21,self.a22,self.a23,self.a24,self.a25,self.a26,self.a27,self.a28,self.a29,self.a30,self.a31,self.a32,self.a33,self.a34)        \n",
-    "        if self.R==1:self.canvas_all.delete(self.aRS)\n",
-    "        if self.R==0:self.canvas_all.delete(self.aR)\n",
-    "        if self.E==0:self.canvas_all.delete(self.aE)\n",
-    "        if self.E==1:self.canvas_all.delete(self.aES)\n",
-    "        if self.succ==1: self.canvas_all.delete(self.a_succ)\n",
-    "        ############## setting up buttons, Scales, comboboxes, etc. for plot options ###################    \n",
-    "        self.a1=self.canvas_all.create_window(200,50,window=self.label_plot_tip)        \n",
-    "        self.a2=self.canvas_all.create_window(100,80,window=self.label_image_size)        \n",
-    "        self.a3=self.canvas_all.create_window(30,105,window=self.label_slider_res)        \n",
-    "        self.a4=self.canvas_all.create_window(170,105,window=self.label_slider_res2)        \n",
-    "        self.a5=self.canvas_all.create_window(100,105,window=self.slider_image_size)        \n",
-    "        self.a6=self.canvas_all.create_window(250,300,window=self.b_plot1)        \n",
-    "        self.a7=self.canvas_all.create_window(280,170,window=self.check_axis)        \n",
-    "        self.a8=self.canvas_all.create_window(100,145,window=self.label_resolution)        \n",
-    "        self.a9=self.canvas_all.create_window(280,80,window=self.label_select_atom)          \n",
-    "        self.a10=self.canvas_all.create_window(30,170,window=self.label_slider_res3)        \n",
-    "        self.a11=self.canvas_all.create_window(170,170,window=self.label_slider_res4)        \n",
-    "        self.a12=self.canvas_all.create_window(100,170,window=self.slider_res)        \n",
-    "        self.a13=self.canvas_all.create_window(100,210,window=self.label_select_atom_size)        \n",
-    "        self.a14=self.canvas_all.create_window(30,230,window=self.label_slider_res5)        \n",
-    "        self.a15=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a16=self.canvas_all.create_window(100,230,window=self.slider_size)        \n",
-    "        self.a17=self.canvas_all.create_window(280,230,window=self.cb_inverse)        \n",
-    "        self.a18=self.canvas_all.create_window(280,110,window=self.cb_atom)             # putting combobox with element selection on canvas\n",
-    "        self.a19=self.canvas_all.create_window(200,350,window=self.label_control)        \n",
-    "        self.a20=self.canvas_all.create_window(200,450,window=self.text_box)        \n",
-    "        self.a21=self.canvas_all.create_window(100,560,window=self.b_control_print)        \n",
-    "        self.a22=self.canvas_all.create_window(300,560,window=self.b_control_clear)        \n",
-    "        self.a23=self.canvas_all.create_window(200,560,window=self.check_points)  \n",
-    "        self.a24=self.canvas_all.create_window(200,600,window=self.b_adjust_cly)\n",
-    "        self.a25=self.canvas_all.create_window(100,310,window=self.cb_color_cp)\n",
-    "        self.a26=self.canvas_all.create_window(100,290,window=self.label_color_cp)\n",
-    "        self.a27=self.canvas_all.create_window(200,630,window=self.check_plane) \n",
-    "        self.a28=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a29=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a30=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a31=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a32=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a33=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "        self.a34=self.canvas_all.create_window(170,230,window=self.label_slider_res6)\n",
-    "    def page_3(self):\n",
-    "        self.canvas_all.delete(self.a1,self.a2,self.a3,self.a4,self.a5,self.a6,self.a7,self.a8,self.a9,self.a10,self.a11,self.a12,self.a13,self.a14,self.a15,self.a16,self.a17,self.a18,self.a19,self.a20,self.a21,self.a22,self.a23,self.a24,self.a25,self.a26,self.a27,self.a28,self.a29,self.a30,self.a31,self.a32,self.a33,self.a34)        \n",
-    "        if self.R==1:self.canvas_all.delete(self.aRS)\n",
-    "        if self.R==0:self.canvas_all.delete(self.aR)\n",
-    "        if self.E==0:self.canvas_all.delete(self.aE)\n",
-    "        if self.E==1:self.canvas_all.delete(self.aES)\n",
-    "        if self.succ==1: self.canvas_all.delete(self.a_succ)\n",
-    "        ###########  setting up buttons, Scales, comboboxes etc. for cylinder selection and concentration calculations  ###################\n",
-    "        self.label_exp=Label(self.canvas_all,text='For calcuating the excess select 4 points') \n",
-    "        self.entry_cly_x=Entry(self.canvas_all,textvariable=self.cly_x,width=10) \n",
-    "        self.entry_cly_y=Entry(self.canvas_all,textvariable=self.cly_y,width=10)\n",
-    "        self.entry_cly_z=Entry(self.canvas_all,textvariable=self.cly_z,width=10)\n",
-    "        self.entry_cly_alpha=Entry(self.canvas_all,textvariable=self.alpha)\n",
-    "        self.entry_cly_beta=Entry(self.canvas_all,textvariable=self.beta)\n",
-    "        \n",
-    "        self.a1=self.canvas_all.create_window(200,50,window=self.label_conc)        \n",
-    "        self.a2=self.canvas_all.create_window(200,90,window=self.check_cylinder)        \n",
-    "        self.a3=self.canvas_all.create_window(100,450,window=self.b_calc_conc)        \n",
-    "        self.a4=self.canvas_all.create_window(100,500,window=self.b_calc_excess)        \n",
-    "        self.a5=self.canvas_all.create_window(300,400,window=self.b_plot_cyl)    \n",
-    "        self.a6=self.canvas_all.create_window(300,500,window=self.b_print_ex) \n",
-    "        self.a7=self.canvas_all.create_window(200,120,window=self.label_cly_pos)    \n",
-    "        self.a8=self.canvas_all.create_window(100,140,window=self.label_cly_x)        \n",
-    "        self.a9=self.canvas_all.create_window(100,170,window=self.entry_cly_x)      \n",
-    "        self.a10=self.canvas_all.create_window(200,140,window=self.label_cly_y)        \n",
-    "        self.a11=self.canvas_all.create_window(200,170,window=self.entry_cly_y)        \n",
-    "        self.a12=self.canvas_all.create_window(300,140,window=self.label_cly_z)        \n",
-    "        self.a13=self.canvas_all.create_window(300,170,window=self.entry_cly_z)\n",
-    "        self.a14=self.canvas_all.create_window(100,200,window=self.label_cly_radius)\n",
-    "        self.a15=self.canvas_all.create_window(100,225,window=self.entry_cly_radius)                       \n",
-    "        self.a16=self.canvas_all.create_window(300,200,window=self.label_cly_height)        \n",
-    "        self.a17=self.canvas_all.create_window(300,225,window=self.entry_cly_height)         \n",
-    "        self.a18=self.canvas_all.create_window(100,255,window=self.label_cly_beta)        \n",
-    "        self.a19=self.canvas_all.create_window(100,280,window=self.entry_cly_beta)        \n",
-    "        self.a20=self.canvas_all.create_window(300,255,window=self.label_cly_alpha)      \n",
-    "        self.a21=self.canvas_all.create_window(300,280,window=self.entry_cly_alpha)             \n",
-    "        self.a22=self.canvas_all.create_window(100,330,window=self.label_color_cyl)        \n",
-    "        self.a23=self.canvas_all.create_window(100,355,window=self.cb_color)        \n",
-    "        self.a24=self.canvas_all.create_window(300,310,window=self.label_inter)        \n",
-    "        self.a25=self.canvas_all.create_window(300,330,window=self.label_slider_inter)        \n",
-    "        self.a26=self.canvas_all.create_window(300,355,window=self.slider_inter)        \n",
-    "        self.a27=self.canvas_all.create_window(100,400,window=self.b_plot2)        \n",
-    "        self.a28=self.canvas_all.create_window(300,450,window=self.b_print_conc)\n",
-    "        self.a29=self.canvas_all.create_window(100,550,window=self.check_norm)\n",
-    "        self.a30=self.canvas_all.create_window(260,550,window=self.check_switch)\n",
-    "        self.a31=self.canvas_all.create_window(220,580,window=self.label_astrix)\n",
-    "        self.a32=self.canvas_all.create_window(280,550,window=self.cb_bulk)\n",
-    "        self.a33=self.canvas_all.create_window(200,610,window=self.label_exp)\n",
-    "        self.a34=self.canvas_all.create_window(200,675,window=self.text_box_ex)\n",
-    "        \n",
-    "    def help_web(self):\n",
-    "        url='https://github.com/areichm/APT_analyzer'\n",
-    "        new=1\n",
-    "        webbrowser.open(url,new=new)\n",
-    "        \n",
-    "    def clear_text(self):    \n",
-    "        self.text_box.delete('1.0', END)\n",
-    "                \n",
-    "    def save(self):\n",
-    "        points=self.text_box.get(1.0,END)\n",
-    "        points=points.split('\\n')\n",
-    "        points=[x for x in points if x!='']\n",
-    "        xyz=[]\n",
-    "        for i in range(0,len(points)):\n",
-    "            points_inner=points[i].split(',')\n",
-    "            for j in points_inner:\n",
-    "                m=j.split('=')\n",
-    "                xyz.append(m[1])\n",
-    "        # with np.unique now contains only the unique data\n",
-    "        data=np.unique(np.array(xyz).reshape(int(len(xyz)/3),3), axis=0)\n",
-    "        # ##MK::sprint 09\n",
-    "        # using here df.to_hdf via pandas needs pandas==1.4.4 with pytables compiled under the hood !\n",
-    "        # pytables however is not directly available as a compiled package via pypi\n",
-    "        # in conda pytables is precompiled inside the conda package already\n",
-    "        # label=('x','y','z')      \n",
-    "        # df=pd.DataFrame(data,columns=label)\n",
-    "        h5File = \"controlpoints.h5\"\n",
-    "        # df.to_hdf(h5File,'data')\n",
-    "        # instead use h5py directly\n",
-    "        h5w = h5py.File(h5File, 'w')\n",
-    "        dst = h5w.create_dataset('/xyz', data=np.asarray(data, np.float32))\n",
-    "        dst.attrs[\"units\"] = \"nm\"\n",
-    "        h5w.close()\n",
-    "        messagebox.showinfo(title='APT_analyzer',message='Control points saved to hdf5 file: \"controlpoints.h5\" inside the APT-analyzer folder.')\n",
-    "\n",
-    "    def save_conc(self):\n",
-    "        if self.conc_check==0:messagebox.showinfo(title='APT_analyzer',message='please plot concentration first')\n",
-    "        else: \n",
-    "            self.df_con.to_csv('APT_analyzer_concentration.csv')\n",
-    "            messagebox.showinfo(title='APT_analyzer',message='Control points saved to csv file: \"APT_analyzer_concentration.csv\" inside the APT-analyzer folder.')\n",
-    "            \n",
-    "    def save_excess(self):\n",
-    "        if self.excess_check==0:messagebox.showinfo(title='APT_analyzer',message='please plot excess first')\n",
-    "        else: \n",
-    "            self.df_ex.to_csv('APT_analyzer_excess.csv')\n",
-    "            messagebox.showinfo(title='APT_analyzer',message='Control points saved to csv file: \"APT_analyzer_excess.csv\" inside the APT-analyzer folder.')\n",
-    "                      \n",
-    "    def adjust(self):                   # adjust cylinder according to controlpoints\n",
-    "        self.var_cyl.set(1)\n",
-    "        XX=[]                           # setting up arrays\n",
-    "        YY=[]\n",
-    "        ZZ=[]\n",
-    "        points=self.text_box.get(1.0,END)   # get text from text box\n",
-    "        points=points.split('\\n')           # split the text into each row\n",
-    "        points=[x for x in points if x!=''] # remove any rows that dont contain information\n",
-    "        for i in range(0,len(points)):      # loop over all rows\n",
-    "                points_inner=points[i].split(',')   # split each row into parts of each coordinates\n",
-    "                xyz2=[]\n",
-    "                for j in points_inner:               # loop over all values inside row\n",
-    "                    m=j.split('=')                   # isolate actual number\n",
-    "                    xyz2.append(m[1])                # save number\n",
-    "                XX.append(float(xyz2[0]))            # save x,y and z coordinate\n",
-    "                YY.append(float(xyz2[1]))\n",
-    "                if self.i_plot.get()==0:ZZ.append(float(xyz2[2]))\n",
-    "                if self.i_plot.get()==1:ZZ.append(-float(xyz2[2]))      # if inverse tip is selected reverse z coordinate\n",
-    "        \n",
-    "        if len(XX)>=3:                               # if 3 or more control points are chosen\n",
-    "                center_x=round(sum(XX)/len(XX),3)             # calculate center in x, y and z\n",
-    "                center_y=round(sum(YY)/len(YY),3)\n",
-    "                if self.i_plot.get()==0:center_z=round(sum(ZZ)/len(ZZ),3)\n",
-    "                if self.i_plot.get()==1:center_z=round(-sum(ZZ)/len(ZZ),3)\n",
-    "                self.cly_x=StringVar(value=center_x)                    #save the center as coordinates for cylinder\n",
-    "                self.cly_y=StringVar(value=center_y)\n",
-    "                self.cly_z=StringVar(value=center_z)\n",
-    "                tmp_C=[]\n",
-    "                for i in range(len(XX)):\n",
-    "                    tmp_C.append([XX[i],YY[i],ZZ[i]])                              #write x,y and z into one matrix and transpose it below\n",
-    "                C=np.array(tmp_C).T\n",
-    "                svd=np.linalg.svd(C - np.mean(C, axis=1, keepdims=True))           # using singular value decomposition to find fit\n",
-    "                left=svd[0]                                                        # upper line has to substract out the centroid first\n",
-    "                fit=left[:,-1]\n",
-    "                normal=np.array([fit[0],fit[1],fit[2]])\n",
-    "                norm=np.linalg.norm(normal)\n",
-    "                n_n=normal/norm                                                    # select fitted values\n",
-    "                aa=np.arcsin(-n_n[1])\n",
-    "                bb=math.atan2(n_n[0],n_n[2])     # this is done by applying rotation matrix in reverse order onto normal verctor\n",
-    "                                                 # and then solving the equation for alpha and beta\n",
-    "                #al=round(math.degrees(aa),4)    # that rotate the normal vector into x=0 and y=0\n",
-    "                #if normal[2]<0:al=round(math.degrees(-aa),4)\n",
-    "                al=round(math.degrees(aa),4)\n",
-    "                be=round(math.degrees(bb),4)\n",
-    "                self.alpha=StringVar(value=al)                                     # then transforming into degree and  \n",
-    "                self.beta=StringVar(value=be)                                      # saving alpha and beta values into entry field\n",
-    "        else: messagebox.showinfo(title='APT_analyzer',message='Choose at least 3 control points')  # if less than 3 points are selected show message\n",
-    "                \n",
-    "    def search_pos(self):                                                      # function for searching for pos/epos file\n",
-    "        if self.E==0:self.canvas_all.delete(self.aE)\n",
-    "        if self.E==1:self.canvas_all.delete(self.aES)\n",
-    "        self.filename=filedialog.askopenfilename()                             # getting file from search\n",
-    "        S='.POS' in self.filename                                              # checking if .POS is in the filename\n",
-    "        ES='.EPOS' in self.filename                                            # checking if .EPOS is in the filename\n",
-    "        s='.pos' in self.filename                                              # checking if .pos is in the filename\n",
-    "        es='.epos' in self.filename                                            # checking if .epos is in the filename\n",
-    "        if S or s is True:                                                     # if .POS or .pos was selected\n",
-    "            self.label_pos_selected=Label(text='pos file selected')            # create label for pos\n",
-    "            self.aE=self.canvas_all.create_window(120,190,window=self.label_pos_selected) #placing label on canvas\n",
-    "            self.E=0                                                           # set variable for later recognition\n",
-    "            if self.succ==1: self.canvas_all.delete(self.a_succ) \n",
-    "            self.succ=0\n",
-    "        elif ES or es is True:                                                 # if .EPOS or .epos was selected\n",
-    "            self.label_pos_selected=Label(text='epos file selected')           # creating label for epos\n",
-    "            self.aES=self.canvas_all.create_window(120,190,window=self.label_pos_selected) #put label on canvas\n",
-    "            self.E=1                                                           # set variable for later recognition\n",
-    "            if self.succ==1: self.canvas_all.delete(self.a_succ) \n",
-    "            self.succ=0\n",
-    "        else:                                                                  # if any other filetype was selected\n",
-    "            messagebox.showinfo(title='APT_analyzer',message='select .pos or .epos file. Warning: Notation has to be either .pos /.epos or .POS / .EPOS')\n",
-    "            self.filename=[]                                                   # leave filename empty\n",
-    "            self.E=2                                                           # set variable back to 2\n",
-    "            \n",
-    "    def search_rrng(self):                                                     # function for searching for rrng file\n",
-    "        if self.R==1:self.canvas_all.delete(self.aRS)\n",
-    "        if self.R==0:self.canvas_all.delete(self.aR)\n",
-    "        self.filename2=filedialog.askopenfilename()                            # getting file from search\n",
-    "        S='.RRNG' in self.filename2                                            # checking if .RRNG is in the filename\n",
-    "        s='.rrng' in self.filename2                                            # checking if .rrng is in the filename\n",
-    "        SR='.RNG' in self.filename2\n",
-    "        sr='.rng' in self.filename2\n",
-    "        if S or s is True:                                                     # if .RRNG or .rrng was selected\n",
-    "            self.label_rrng_selected=Label(text='.rrng file selected')         # create label for rrng\n",
-    "            self.aR=self.canvas_all.create_window(280,190,window=self.label_rrng_selected) #placing label on canvas\n",
-    "            self.R=0                                                           # setting variable for later recognition\n",
-    "            if self.succ==1: self.canvas_all.delete(self.a_succ) \n",
-    "            self.succ=0\n",
-    "        elif SR or sr is True:\n",
-    "            self.label_rrng_selected=Label(text='.rng file selected')         # create label for rrng\n",
-    "            self.aRS=self.canvas_all.create_window(280,190,window=self.label_rrng_selected) #placing label on canvas\n",
-    "            self.R=1 \n",
-    "            if self.succ==1: self.canvas_all.delete(self.a_succ) \n",
-    "            self.succ=0\n",
-    "        else:                                                                  # if no correct file was selected\n",
-    "            messagebox.showinfo(title='APT_analyzer',message='select .rrng file. Warning: Notation has to be either .rrng or .RRNG')\n",
-    "            self.filename2=[]                                                   # leaving filename empty\n",
-    "            self.R=2                                                           # set variable back to 2\n",
-    "        \n",
-    "    def calculate_tip(self):                                                   # function for reading and converting the pos and rrng file and creating the tip\n",
-    "        if self.E==2:messagebox.showinfo(title='APT_analyzer',message='no file .pos/.epos file selected')   # checking if no  pos/epos file is selected (E=2)\n",
-    "        elif self.R==2:messagebox.showinfo(title='APT_analyzer',message='no file .rrng file selected')    # checking if no  rrng file is selected (R=2)\n",
-    "        else:                                                                    # if pos/epos and rrng file is selected\n",
-    "            with open(self.filename, 'rb') as f:                                   # opening pos/epos data from file1\n",
-    "                data = f.read()                                                    # reading pos/epos data from file1\n",
-    "            data_rrng=self.filename2                                               # reading rrng data from file2\n",
-    "            if self.E==0:pos=apt.read_pos(data)                                    # converting pos data if pos file was selected (E==0)\n",
-    "            elif self.E==1:pos=apt.read_epos(data)                                 # converting epos data if epos file was selected (E==1)\n",
-    "            if self.R==0:rrngs=apt.read_rrng(data_rrng)                           # converting rrng data\n",
-    "            elif self.R==1:rrngs=apt.read_rng(data_rrng)\n",
-    "            self.tip=apt.label_ions(pos, rrngs)                                    # label ions using apt_importers functions\n",
-    "            self.ele=apt.unique(list(self.tip['comp']))                            # determining how many unique elements in tip using apt_importers functions\n",
-    "            string=['all']                                                         # setting up strings for atom selection combobox\n",
-    "            for i in range (0,len(self.ele)):                                      # loop over all unique elements\n",
-    "                string.append(self.ele[i])                                         # creating strings with all unique elements\n",
-    "            self.data_atom=(string)                                                # data for combobox containing all unique elements + 'all' at start\n",
-    "            self.cb_atom = Combobox(tk, values=self.data_atom)                     # creating combobox with unique elements data \n",
-    "            self.atom=1\n",
-    "        \n",
-    "            self.cb_atom.current(0)                                                # setting initial value of combobox to 'all'  \n",
-    "            self.fig.clear()                                                   # if plot single was selected clear all previous plots\n",
-    "            self.canvas_all.delete('message') \n",
-    "            self.spec=gridspec.GridSpec(ncols=2,nrows=2,width_ratios=[2,1],wspace=0.5,hspace=0.5,height_ratios=[2,1]) #adjust the size of the figure compared to (111)\n",
-    "            self.ax=self.fig.add_subplot(self.spec[0],projection='3d')\n",
-    "            N=5000\n",
-    "            u_ele=self.ele\n",
-    "            x=np.array(self.tip['x'])[::N]                                         # select x cooridant (only take every Nth atom to plot later)\n",
-    "            y=np.array(self.tip['y'])[::N]                                         # select y cooridant from tip data\n",
-    "            z=np.array(self.tip['z'])[::N]                                         # select z cooridant from tip data\n",
-    "            c=np.array(self.tip['colour'])[::N]                                    # select the colour column in the tip data\n",
-    "            label=np.array(self.tip['comp'])[::N]                                  # select the composition column in the tip data\n",
-    "            for i in range(0,len(u_ele)):                                          # loop that goes over every different elements\n",
-    "                e=label==u_ele[i]                                                 # seperation of the elements\n",
-    "                x_new=x[e]                                                        # select the x values of each element indiviually\n",
-    "                y_new=y[e]\n",
-    "                z_new=z[e]\n",
-    "                c_new=c[e]\n",
-    "                self.ax.scatter3D(x_new,y_new,z_new,c=c_new,label=u_ele[i],s=1)  # scatter plot each element seperatly and assign label\n",
-    "                x_N=len(x) \n",
-    "                self.ax.set_title('preview (number of atoms={:.0f},     1/{:.0f} of all atoms)'.format(x_N,N))                                                   # assigne x_N value to show the number of plotted atoms in title\n",
-    "            self.canvas.draw_idle()\n",
-    "            apt.set_axes_equal(self.ax)                                            # function for setting the axes equal for 3d plot\n",
-    "            self.ax.legend(loc='center left', bbox_to_anchor=(1.07, 0.5))#, fontsize=7)                                                        # show legends of each element   \n",
-    "            self.ax.set_xlabel('X-axis',fontweight='bold')                     # label x axis\n",
-    "            self.ax.set_ylabel('Y-axis',fontweight='bold')                # label y axis\n",
-    "            self.ax.set_zlabel('Z-axis',fontweight='bold')                     # label z axis\n",
-    "            self.label_succ=Label(text='Sucessfully loaded files!')         # create label for rrng\n",
-    "            self.a_succ=self.canvas_all.create_window(200,260,window=self.label_succ) #placing label on canvas\n",
-    "            self.succ=1\n",
-    "    \n",
-    "    def clear(self):                                                           # function for clearing canvas\n",
-    "        self.fig.clear()                                                       # clearing canvas\n",
-    "        self.canvas.draw_idle()                                                # drawing \n",
-    "        self.canvas_all.delete('message')                                      # deleting message about concentration data\n",
-    "        \n",
-    "    def plot_tip(self):                                                        # function about plotting tip\n",
-    "        if self.plot_exist==1:                                                 # if plot already exists get the parameters of old plot\n",
-    "            azim=self.ax.azim                                                  # get azimutal angle of old plot\n",
-    "            elev=self.ax.elev\n",
-    "            xlim=self.ax.get_xlim()                                           # get x,y and z limit of old plot\n",
-    "            ylim=self.ax.get_ylim()\n",
-    "            zlim=self.ax.get_zlim()\n",
-    "        if self.i_plot.get()==0:self.invert=0                                 # if inversion checkbox is unmarked set value=0\n",
-    "        else: self.invert=1                                                   # if inversion checkbox is marked set value=1\n",
-    "            \n",
-    "        color_zyl=str(self.cb_color.get())                                    # get color of cylinder from color entry box\n",
-    "        color_cp=str(self.cb_color_cp.get())\n",
-    "        self.canvas_all.delete('message')                                      # clearing message about concentration data\n",
-    "        Z= self.cb_atom.get()                                                  # getting variable from combobox of atom selection\n",
-    "        M = self.slider_res.get()                                              # getting variable from combobox of resolution selection\n",
-    "        SS=self.slider_size.get()                                              # getting variable from combobox of atom size selection\n",
-    "        S=float(SS)/10                                                         # transforming entry into float and deviding by 10 so values 0.1 to 1 are also included\n",
-    "        image_size=self.slider_image_size.get()\n",
-    "        image_size=float(image_size)**2\n",
-    "        u_ele=self.ele\n",
-    "        self.fig.clear()                                                   # if plot single was selected clear all previous plots\n",
-    "        self.spec=gridspec.GridSpec(ncols=2,nrows=2,width_ratios=[image_size,1],wspace=0.1,hspace=0.1,height_ratios=[image_size,1]) #adjust the size of the figure compared to (111)\n",
-    "        self.ax=self.fig.add_subplot(self.spec[0],projection='3d')         # make new figure with size depending on the image size slider\n",
-    "        if self.plot_exist==1:                                             # if plot already exist set old parameters of plot as new ones\n",
-    "            self.ax.view_init(elev=elev,azim=azim)                         # set azimuthal angle and elevation of old plot as new one\n",
-    "            self.ax.set_xlim3d(xlim[0],xlim[1])                            # set x,y and z limit of old plot as new one\n",
-    "            self.ax.set_ylim3d(ylim[0],ylim[1])\n",
-    "            if self.i_plot.get()==0 and self.invert==0:self.ax.set_zlim3d(zlim[0],zlim[1])  # depending on if the plot should be inverted or not\n",
-    "            if self.i_plot.get()==1 and self.invert==1:self.ax.set_zlim3d(zlim[0],zlim[1])  # reset the z limit of new plot to center it again\n",
-    "        self.plot_exist=1                                                      # set plot exist as one in order to mark that plot exists\n",
-    "        n=len(np.array(self.tip['x']))                                         # get the number of atoms\n",
-    "        N=int(50000/(10**M))                                                   # calc N (the number how many atoms should be plotted)\n",
-    "        if N==0:N=1\n",
-    "        \n",
-    "        x=np.array(self.tip['x'])[::N]                                         # select x cooridant (only take every Nth atom to plot later)\n",
-    "        y=np.array(self.tip['y'])[::N]                                         # select y cooridant from tip data\n",
-    "        z=np.array(self.tip['z'])[::N]                                         # select z cooridant from tip data\n",
-    "        c=np.array(self.tip['colour'])[::N]                                    # select the colour column in the tip data\n",
-    "        label=np.array(self.tip['comp'])[::N]                                  # select the composition column in the tip data\n",
-    "\n",
-    "        max_x=max(x)\n",
-    "        min_x=min(x)\n",
-    "        max_z=max(z)\n",
-    "        min_z=min(z)\n",
-    "        max_y=max(y)\n",
-    "        min_y=min(y)\n",
-    "        for i in range(0,len(u_ele)):                                          # loop that goes over every different elements\n",
-    "            e=label==u_ele[i]                                                 # seperation of the elements\n",
-    "            x_new=x[e]                                                        # select the x values of each element indiviually\n",
-    "            y_new=y[e]\n",
-    "            z_new=z[e]\n",
-    "            c_new=c[e]     \n",
-    "            if self.i_plot.get()==1: z_new=-z_new                                          # if inverse tip is selected change the sign of the z coordinates\n",
-    "            if Z=='all':                                                      # if all was selected plot all of them together\n",
-    "                X=np.array([x,y,z]).T \n",
-    "                c_new[c_new=='#FFFFFF']='#000000'\n",
-    "                self.ax.scatter(x_new,y_new,z_new,c=c_new,label=u_ele[i],s=S,zorder = 1,depthshade = False,picker=True)  # scatter plot each element seperatly and assign label\n",
-    "                x_N=len(x) \n",
-    "                self.ax.set_title('number of atoms={:.0f},     1/{:.0f} of all atoms'.format(x_N,N))                                                   # assigne x_N value to show the number of plotted atoms in title\n",
-    "            elif u_ele[i]==Z:                                                 # if a certain element was selected in combobox for element selection\n",
-    "                X=np.array([x_new,y_new,z_new]).T                             # putting all \n",
-    "                c_new[c_new=='#FFFFFF']='#000000'\n",
-    "                self.ax.scatter(X[:,0],X[:,1],X[:,2],c=c_new,label=u_ele[i],s=S,zorder = 1, depthshade = False,picker=True)  #scatter plot each element seperatly and assign label         \n",
-    "                x_N=len(x_new)                                                 # assigne x_N only to show the number of plotted atoms of selected element \n",
-    "                self.ax.set_title('number of atoms={:.0f},     1/{:.0f} of all atoms of this type'.format(x_N,N))                                                   \n",
-    "        apt.set_axes_equal(self.ax)                                            # function for setting the axes equal for 3d plot\n",
-    "        self.ax.legend(loc='center left', bbox_to_anchor=(1.07, 0.5))#, fontsize=7)                                                       # show legends of each element\n",
-    "        if self.var_axis.get()==0:                                             # if show axis was selected\n",
-    "            self.ax.set_xlabel('X-axis',fontweight='bold')                     # label x axis\n",
-    "            self.ax.set_ylabel('Y-axis',fontweight='bold')                     # label y axis\n",
-    "            self.ax.set_zlabel('Z-axis',fontweight='bold')                     # label z axis\n",
-    "        elif self.var_axis.get()==1:                                           # if show axis was not selected\n",
-    "            self.ax.set_axis_off()                                             # dont show axis\n",
-    "        \n",
-    "        if self.var_cyl.get()==1:                                              # if show clyinder was selected\n",
-    "            x_pos=self.cly_x.get()                                            # get x value from x entry box\n",
-    "            if x_pos=='': x_pos=0\n",
-    "            else:x_pos = float(x_pos)\n",
-    "            y_pos =self.cly_y.get()                                           # get y value from y entry box\n",
-    "            if y_pos=='': y_pos=0\n",
-    "            else:y_pos = float(y_pos)\n",
-    "            z_pos = self.cly_z.get()                                          # get z value from z entry box\n",
-    "            if z_pos=='': z_pos=0\n",
-    "            else:z_pos = float(z_pos) \n",
-    "            if self.i_plot.get()==1:      z_pos = -z_pos                      # if inverse tip is selected inverse the z coordinates of the cylinder              \n",
-    "            height = float(self.height.get())                                 # get height value from height entry box\n",
-    "            alpha = float(self.alpha.get())                                   # get tilt along y value from alpha entry box\n",
-    "            beta = float(self.beta.get())                                     # get tilt along x value from beta entry box\n",
-    "            r = float(self.radius.get())                                      # get radius value from radius entry box \n",
-    "            theta=np.linspace(0,2*np.pi,201)                                  # create linspace variable for plotting the circle\n",
-    "            alpha=math.radians(alpha)                                         # transform alpha from deg in rad\n",
-    "            beta=math.radians(beta)                                           # transfrom beta from deg in rad\n",
-    "            Xc,Yc,Zc=data_for_cylinder_along_z(0,0,0,r,height)  # calculating cylinder\n",
-    "            Z=np.array([Xc,Yc,Zc]).T\n",
-    "            matrix_l=np.array([(np.cos(beta),                   np.sin(alpha)*np.sin(beta),        np.cos(alpha)*np.sin(beta)),\n",
-    "                               (0,                              np.cos(alpha),                     -np.sin(alpha)),\n",
-    "                               (-np.sin(beta),                  np.sin(alpha)*np.cos(beta),        np.cos(alpha)*np.cos(beta))])\n",
-    "            pro=[]\n",
-    "            for j in range(0,len(Z)):\n",
-    "                 for i in range (0,len(Z[j])):\n",
-    "                         pro.append(matrix_l.dot(Z[i][j]))  \n",
-    "            pro=np.array(pro)                \n",
-    "            Z_new=pro.reshape(50,50,3).T\n",
-    "            self.ax.plot_surface(Z_new[0]+x_pos,Z_new[1]+y_pos,Z_new[2]+z_pos,alpha=0.4,color=color_zyl) # plotting cylinder\n",
-    "            apt.set_axes_equal(self.ax)\n",
-    "            \n",
-    "        if self.var_points.get()==1:\n",
-    "            XX=[]\n",
-    "            YY=[]\n",
-    "            ZZ=[]\n",
-    "            points=[]\n",
-    "            points=self.text_box.get(1.0,END)\n",
-    "            points=points.split('\\n')\n",
-    "            points=[x for x in points if x!='']\n",
-    "            for i in range(0,len(points)):\n",
-    "                points_inner=points[i].split(',')\n",
-    "                xyz2=[]\n",
-    "                for j in points_inner:\n",
-    "                    m=j.split('=')\n",
-    "                    xyz2.append(m[1])\n",
-    "                x2=float(xyz2[0])\n",
-    "                y2=float(xyz2[1])\n",
-    "                z2=float(xyz2[2])\n",
-    "                XX.append(x2)\n",
-    "                YY.append(y2)\n",
-    "                ZZ.append(z2)\n",
-    "                if self.i_plot.get()==1:z2=-z2                                          # if inverse tip is selected\n",
-    "                self.ax.scatter3D(x2,y2,z2,marker='+',color=color_cp,s=S*100)\n",
-    "            if len(XX)>=3 and self.var_plane.get()==1:\n",
-    "                center_x=sum(XX)/len(XX)\n",
-    "                center_y=sum(YY)/len(YY)\n",
-    "                center_z=sum(ZZ)/len(ZZ)\n",
-    "                self.cly_x=StringVar(value=center_x)\n",
-    "                self.cly_y=StringVar(value=center_y)\n",
-    "                self.cly_z=StringVar(value=center_z)\n",
-    "                tmp_C=[]\n",
-    "                for i in range(len(XX)):\n",
-    "                    tmp_C.append([XX[i],YY[i],ZZ[i]])\n",
-    "                C=np.array(tmp_C).T\n",
-    "                svd=np.linalg.svd(C - np.mean(C, axis=1, keepdims=True))\n",
-    "                left=svd[0]\n",
-    "                fit=left[:,-1]\n",
-    "                #print('solution: %f x +%f y +%f z = 0' %(fit[0],fit[1],fit[2]))\n",
-    "                normal=np.array([fit[0],fit[1],fit[2]])   \n",
-    "                r=5\n",
-    "                self.ax.plot([center_x,center_x+r*normal[0]],[center_y,center_y+r*normal[1]],[center_z,center_z+r*normal[2]],color='r',linewidth=5)\n",
-    "                xlim=self.ax.get_xlim()\n",
-    "                ylim=self.ax.get_ylim()\n",
-    "                X,Y=np.meshgrid(np.arange(xlim[0],xlim[1]),np.arange(ylim[0],ylim[1]))\n",
-    "                Z=np.zeros(X.shape)\n",
-    "                for r in range(X.shape[0]):\n",
-    "                    for c in range(X.shape[1]):\n",
-    "                        #Z[r,c]=fit[0]*X[r,c]+fit[1]*Y[r,c]+fit[2]\n",
-    "                        Z[r,c]=-(fit[0]*X[r,c]+fit[1]*Y[r,c])/fit[2]\n",
-    "                #self.ax.plot([cpx,fit[0]],[cpy,fit[1]],[cpz,-1])\n",
-    "                self.ax.plot_wireframe(X+center_x,Y+center_y,Z+center_z,color='k')\n",
-    "        self.canvas.draw_idle()  \n",
-    "  \n",
-    "        def distance(point, event):\n",
-    "#         Return distance between mouse position and given data point\n",
-    "#         Args:point (np.array): np.array of shape (3,), with x,y,z in data coords event (MouseEvent): mouse event (which contains mouse position in .x and .xdata)\n",
-    "#         Returns:distance (np.float64): distance (in screen coords) between mouse pos and data point          \n",
-    "             assert point.shape == (3,), \"distance: point.shape is wrong: %s, must be (3,)\" % point.shape  \n",
-    "             x2, y2, _ = proj3d.proj_transform(point[0], point[1], point[2], self.ax.get_proj())   # Project 3d data space to 2d data space\n",
-    "             x3, y3 = self.ax.transData.transform((x2, y2))                                        # Convert 2d data space to 2d screen space\n",
-    "             return np.sqrt ((x3 - event.x)**2 + (y3 - event.y)**2)                                # calculate distance\n",
-    "    \n",
-    "        def onclick(event):\n",
-    "            distances = [distance (X[i,0:3], event) for i in range(X.shape[0])]                                              # use function distance to evaluate the closests index to mouse click\n",
-    "            index=np.argmin(distances)                                                                                       # select the closest index\n",
-    "            self.ax.scatter(X[index, 0], X[index, 1], X[index, 2],marker='+',color=color_cp,s=S*100)                         # plot controlpoint at closest index point\n",
-    "            text='x='+str(np.round(X[index, 0],4))+', y='+str(np.round(X[index, 1],4))+', z='+str(np.round(X[index, 2],4))   # write x,y,z coordinates into text file\n",
-    "            if self.i_plot.get()==1:text='x='+str(np.round(X[index, 0],4))+', y='+str(np.round(X[index, 1],4))+', z='+str(-np.round(X[index, 2],4))\n",
-    "            self.text_box.insert(END,text)                                                                                   # insert text file in textbox\n",
-    "            self.text_box.insert(END,'\\n')                                                                                   # make sure next control point is next row\n",
-    "            self.canvas.draw_idle()\n",
-    "                \n",
-    "        if self.control.get()==1: \n",
-    "            if self.diss==1:self.fig.canvas.mpl_disconnect(self.cid)\n",
-    "            self.cid=self.fig.canvas.mpl_connect('button_press_event',onclick)\n",
-    "            self.diss=1\n",
-    "        elif self.control.get()==0 and self.diss==1: \n",
-    "            self.fig.canvas.mpl_disconnect(self.cid)\n",
-    "            self.diss=0\n",
-    "          \n",
-    "    def calc_con(self):                                                        # function for calculating the concentration\n",
-    "        if self.diss2==1:self.fig.canvas.mpl_disconnect(self.cid) \n",
-    "        self.plot_exist=0\n",
-    "        self.print_con=[]\n",
-    "        self.print_con2=[]\n",
-    "        self.canvas_all.delete('message') \n",
-    "        start_end=self.cb_bulk.get()\n",
-    "        atom= self.cb_atom.get()\n",
-    "        u_ele_real=self.ele\n",
-    "        image_size=self.slider_image_size.get()\n",
-    "        image_size=float(image_size)/2\n",
-    "        self.fig.clear()\n",
-    "        self.spec=gridspec.GridSpec(ncols=2,nrows=2,width_ratios=[image_size,1],wspace=0.5,hspace=0.5,height_ratios=[image_size,1]) #adjust the size of the figure compared to (111)\n",
-    "        self.ax1=self.fig.add_subplot(self.spec[0])\n",
-    "        self.ax1.set_xlabel('z position of cylinder')\n",
-    "        self.ax1.set_ylabel('concentration [%]')\n",
-    "        x_real=np.array(self.tip['x'])\n",
-    "        y_real=np.array(self.tip['y'])\n",
-    "        z_real=np.array(self.tip['z'])\n",
-    "        if self.i_plot.get()==1:                                     # atoms z coordinatines inversion\n",
-    "            z_real = -z_real\n",
-    "        c_real=np.array(self.tip['colour'])\n",
-    "        label_real=np.array(self.tip['comp'])\n",
-    "        inter=float(self.slider_inter.get()/20)\n",
-    "        height = float(self.height.get())\n",
-    "        alpha = float(self.alpha.get())\n",
-    "        beta = float(self.beta.get())\n",
-    "        r = float(self.radius.get())\n",
-    "        x_pos = float(self.cly_x.get())\n",
-    "        y_pos = float(self.cly_y.get())\n",
-    "        z_pos = float(self.cly_z.get())\n",
-    "        if self.i_plot.get()==1:                                     # cylinder z coordinatines inversion\n",
-    "            z_pos = -z_pos\n",
-    "        z_start=-height/2\n",
-    "        z_end=height/2\n",
-    "        alpha=math.radians(-alpha)\n",
-    "        beta=math.radians(-beta)\n",
-    "        ###################   tilt and move zylinder ######################################\n",
-    "        pro=[]\n",
-    "        Z=np.array([x_real-x_pos,y_real-y_pos,z_real-z_pos]).T\n",
-    "        M_ROT1=[(1,      0,                  0     ),            # rotational matrix along the x-direction\n",
-    "                (0,  np.cos(alpha),  -np.sin(alpha)),\n",
-    "                (0,  np.sin(alpha),    np.cos(alpha))]\n",
-    "\n",
-    "        M_ROT2=[(np.cos(beta),      0,       np.sin(beta)),     # rotational matrix along the y-direction\n",
-    "                (0,                  1,            0      ),\n",
-    "                (-np.sin(beta),      0,       np.cos(beta))]\n",
-    "        matrix_l=np.array(M_ROT1).dot(M_ROT2)\n",
-    "        for j in range(0,len(Z)):\n",
-    "                    pro.append(matrix_l.dot(Z[j])) \n",
-    "        Z_new=np.array(pro)\n",
-    "        x_real=Z_new[:,0]\n",
-    "        y_real=Z_new[:,1]\n",
-    "        z_real=Z_new[:,2]\n",
-    "        ######################################################################### \n",
-    "        xy=((x_real)**2+(y_real)**2)**(1/2)                                    # cirlce constraint for atoms       \n",
-    "        circle=xy<=r                                                           # only select atoms inside of circle\n",
-    "        message='concentration: \\n'                                            # initialize the message displayed on the right side of the plot\n",
-    "        for m in range(0,len(u_ele_real)):                                     # loop over each individual elements\n",
-    "            plot_z=[]                                                          # x component of concentration plots \n",
-    "            Num=[]                                                             # Number of atoms inside the circle and intervals (for concentration calculation)\n",
-    "            Num_all=[]                                                         # total number of atoms (of each element) to calculate the % contribution of each\n",
-    "            e=label_real[circle]==u_ele_real[m]                                # seperation of the elements\n",
-    "            z_circle=z_real[circle]                                            # only selec the atoms with circle constraint\n",
-    "            z_p=z_circle[e]                                                    # only select the atoms wth circle constraint of specific element\n",
-    "            c_circle=c_real[circle]\n",
-    "            c_p=c_circle[e]\n",
-    "            for j in range (0,int((z_end-z_start)/inter)+1):                     # loop of intervals\n",
-    "                init=z_p>=z_start+j*inter                                      # starting condition of interval for each element\n",
-    "                init_all=z_circle>=z_start+j*inter                             # starting condition of interval for all elements together\n",
-    "                z_all2=z_circle[init_all]                                      # selecting atoms which fulfill starting constraint for all elements\n",
-    "                z_p2=z_p[init]                                                 # selecting atoms which fulfill the starting constraint for each individual element\n",
-    "                init2=z_p2<=z_start+(j*inter+inter)                            # ending constraint of interval\n",
-    "                init2_all=z_all2<=z_start+(j*inter+inter)                      # ending constraint of interval for all elements\n",
-    "                z_all3=z_all2[init2_all]                                       # selecting atoms which also fulfill ending constraint for all elements\n",
-    "                z_p3=z_p2[init2]                                               # selecting atom which also fulfill ending constraint for each individual elements\n",
-    "                Num_all.append(len(z_all3))                                    # append the number of atoms which fulfill both contraints\n",
-    "                Num.append(len(z_p3))                                          # append the number of atoms which fulfill both constraints for each individual element\n",
-    "                plot_z.append(z_start+j*inter)#+inter/2)                       # append the x-coordinate for the concentration plot\n",
-    "            a=np.array(Num,dtype=float)                                        # transform total number of atoms for each individual element into array of floats\n",
-    "            b=np.array(Num_all,dtype=float)                                    # transform total number of atoms into array of floats\n",
-    "            if self.var_switch.get()==1: \n",
-    "                if start_end=='start':b=np.array(Num_all[0])\n",
-    "                last=len(np.array(Num_all))-1    \n",
-    "                if start_end=='end':b=np.array(Num_all[last])\n",
-    "                if b==0:messagebox.showinfo(title='APT_analyzer',message='Reference bulk concentration is 0')\n",
-    "            self.conc=100*np.divide(a,b, out=np.zeros_like(a), where=b!=0)     # calculate concentration, if total amount of atoms == 0, result is 0\n",
-    "            message=message+u_ele_real[m]                                      # append element type into message\n",
-    "            message=message+': maximal value: '                                # add text to message\n",
-    "            message=message+str(round(max(self.conc),2))                            # add maximum of concentration to message\n",
-    "            message=message+' minimal value: '                                 # add text to message\n",
-    "            message=message+str(round(min(self.conc),2))                            # add minimum of concentration to message\n",
-    "            message=message+'\\n'                                               # add line split to message  \n",
-    "            if atom=='all':                                                       # seperate if atom select checkbox 'all' is selected\n",
-    "                if c_p[0]=='#FFFFFF':c_p[0]='#000000'                                        # if color of particles is white change it to black so it can be seen with white background\n",
-    "                self.ax1.plot(plot_z,self.conc,c_p[0],label=u_ele_real[m])                 # plot the concentration of each element individually\n",
-    "                self.print_con2.append(u_ele_real[m])\n",
-    "                self.print_con.append(self.conc)\n",
-    "            elif u_ele_real[m]==atom:                                             # if certain element is selected in checkbox\n",
-    "                if c_p[0]=='#FFFFFF':c_p[0]='#000000'\n",
-    "                self.ax1.plot(plot_z,self.conc,c_p[0],label=u_ele_real[m])                 # only plot selected element from the select atom checkbox\n",
-    "                self.print_con2.append(u_ele_real[m])\n",
-    "                self.print_con.append(self.conc)\n",
-    "        self.print_con2.append('z_cyl')\n",
-    "        plot_z2=plot_z.copy()\n",
-    "        plot_z2=np.array(plot_z2).reshape(np.shape(np.array(self.conc)))\n",
-    "        self.print_con.append(plot_z2)\n",
-    "        self.df_con=pd.DataFrame(np.array(self.print_con).T,columns=self.print_con2)\n",
-    "        self.ax1.legend(loc='center left', bbox_to_anchor=(1.07, 0.5))\n",
-    "        self.ax1.set_title('concentration of elements along cylinder / intervalsize=%1.2f' %inter)\n",
-    "        self.canvas.draw_idle()\n",
-    "        self.message=Text(height = 20,width = 50,relief=FLAT)\n",
-    "        self.message.insert(END, message)\n",
-    "        self.message.configure(state='disabled')\n",
-    "        image_ratio=image_size/2.5\n",
-    "        place_factor=0.2\n",
-    "        place_value=1450-place_factor*(1450-image_ratio*1450)\n",
-    "        self.canvas_all.create_window(place_value,300,window=self.message,tags='message')\n",
-    "        self.conc_check=1\n",
-    "        \n",
-    "        \n",
-    "        \n",
-    "    def calc_excess(self):\n",
-    "        self.plot_exist=0\n",
-    "        self.print_ex=[]\n",
-    "        self.print_ex2=[]\n",
-    "        self.canvas_all.delete('message')  \n",
-    "        atom= self.cb_atom.get()      \n",
-    "        color_zyl=str(self.cb_color.get())\n",
-    "        u_ele_real=self.ele        \n",
-    "        image_size=self.slider_image_size.get()\n",
-    "        image_size=float(image_size)/2\n",
-    "        self.fig.clear()\n",
-    "        self.spec=gridspec.GridSpec(ncols=2,nrows=2,width_ratios=[image_size,1],wspace=0.5,hspace=0.5,height_ratios=[image_size,1]) #adjust the size of the figure compared to (111)\n",
-    "        self.ax1=self.fig.add_subplot(self.spec[0])\n",
-    "        self.ax1.set_xlabel('z position of cylinder')\n",
-    "        self.ax1.set_ylabel('Total amount of atoms')\n",
-    "        x_real=np.array(self.tip['x'])\n",
-    "        y_real=np.array(self.tip['y'])\n",
-    "        z_real=np.array(self.tip['z'])                             # atoms z coordinatines inversion\n",
-    "        if self.i_plot.get()==1:\n",
-    "            z_real=-z_real\n",
-    "        c_real=np.array(self.tip['colour'])\n",
-    "        label_real=np.array(self.tip['comp'])\n",
-    "        inter=float(self.slider_inter.get()/20)\n",
-    "        height = float(self.height.get())\n",
-    "        alpha = float(self.alpha.get())\n",
-    "        beta = float(self.beta.get())\n",
-    "        r = float(self.radius.get())\n",
-    "        x_pos = float(self.cly_x.get())\n",
-    "        y_pos = float(self.cly_y.get())\n",
-    "        z_pos = float(self.cly_z.get())\n",
-    "        if self.i_plot.get()==1:                                   # cylinder z coordinatines inversion\n",
-    "            z_pos=-z_pos\n",
-    "        z_start=-height/2\n",
-    "        z_end=height/2\n",
-    "        alpha=math.radians(-alpha)                               # transfroms radius into radians\n",
-    "        beta=math.radians(-beta)                                 # - because otherwise it tilts the cylinder in the wrong direction (dont know why)\n",
-    "        ###################   tilt and move zylinder ######################################\n",
-    "        pro=[]\n",
-    "        Z=np.array([x_real-x_pos,y_real-y_pos,z_real-z_pos]).T\n",
-    "        M_ROT1=[(1,      0,                  0     ),            # rotational matrix along the x-direction\n",
-    "                (0,  np.cos(alpha),  -np.sin(alpha)),\n",
-    "                (0,  np.sin(alpha),    np.cos(alpha))]\n",
-    "\n",
-    "        M_ROT2=[(np.cos(beta),      0,       np.sin(beta)),     # rotational matrix along the y-direction\n",
-    "                (0,                  1,            0      ),\n",
-    "                (-np.sin(beta),      0,       np.cos(beta))]\n",
-    "        matrix_l=np.array(M_ROT1).dot(M_ROT2)\n",
-    "        for j in range(0,len(Z)):\n",
-    "                    pro.append(matrix_l.dot(Z[j])) \n",
-    "        Z_new=np.array(pro)\n",
-    "        x_real=Z_new[:,0]\n",
-    "        y_real=Z_new[:,1]\n",
-    "        z_real=Z_new[:,2]\n",
-    "        ######################################################################### \n",
-    "        xy=((x_real)**2+(y_real)**2)**(1/2)\n",
-    "        circle=xy<=r\n",
-    "        for m in range(0,len(u_ele_real)):\n",
-    "            plot_z=[]\n",
-    "            excess=[]\n",
-    "            ex=0\n",
-    "            e=label_real[circle]==u_ele_real[m]               #seperation of the atoms \n",
-    "            z_circle=z_real[circle]\n",
-    "            z_p=z_circle[e]\n",
-    "            c_circle=c_real[circle]\n",
-    "            c_p=c_circle[e]\n",
-    "            for j in range (0,int((z_end-z_start)/inter)+1):\n",
-    "                init=z_p>=z_start+j*inter   \n",
-    "                z_p2=z_p[init]\n",
-    "                init2=z_p2<=z_start+(j*inter+inter)\n",
-    "                z_p3=z_p2[init2]\n",
-    "                ex+=len(z_p3)\n",
-    "                excess.append(ex)\n",
-    "                plot_z.append(z_start+j*inter)#+inter/2)   \n",
-    "            if self.var_norm.get()==1:excess=np.array(excess)/(max(excess))\n",
-    "            if atom=='all':\n",
-    "                if c_p[0]=='#FFFFFF':c_p[0]='#000000'\n",
-    "                self.ax1.plot(plot_z,excess,c_p[0],label=u_ele_real[m])\n",
-    "                excess_save=excess.copy()\n",
-    "                self.print_ex2.append(u_ele_real[m])\n",
-    "                self.print_ex.append(np.array(excess))\n",
-    "            elif u_ele_real[m]==atom:\n",
-    "                if c_p[0]=='#FFFFFF':c_p[0]='#000000'\n",
-    "                self.ax1.plot(plot_z,excess,c_p[0],label=u_ele_real[m]) \n",
-    "                excess_save=excess.copy()\n",
-    "                self.print_ex2.append(u_ele_real[m])\n",
-    "                self.print_ex.append(np.array(excess)) \n",
-    "        self.print_ex2.append('z_cyl')\n",
-    "        plot_z2=plot_z.copy()\n",
-    "        plot_z2=np.array(plot_z2).reshape(np.shape(np.array(excess)))\n",
-    "        self.print_ex.append(plot_z2)\n",
-    "        self.df_ex=pd.DataFrame(np.array(self.print_ex).T,columns=self.print_ex2)\n",
-    "        self.ax1.set_title('Excess (total atom number of elements along cylinder) / intervalsize=%1.2f ' %inter)\n",
-    "        self.ax1.legend(loc='center left', bbox_to_anchor=(1.07, 0.5))\n",
-    "        \n",
-    "        points_ex=self.text_box_ex.get(1.0,END)   # get text from text box\n",
-    "        if points_ex!='\\n':\n",
-    "            points_ex=points_ex.split('\\n')           # split the text into each row\n",
-    "            points_ex=[x for x in points_ex if x!=''] # remove any rows that dont contain information\n",
-    "            XX=[]\n",
-    "            YY=[]\n",
-    "            for i in range(0,len(points_ex)):      # loop over all rows\n",
-    "                    points_inner=points_ex[i].split(',')   # split each row into parts of each coordinates\n",
-    "                    xy2=[]\n",
-    "                    for j in points_inner:               # loop over all values inside row\n",
-    "                        m=j.split('=')                   # isolate actual number\n",
-    "                        xy2.append(m[1])                # save number\n",
-    "                    XX.append(float(xy2[0]))            # save x,y and z coordinate\n",
-    "                    YY.append(float(xy2[1]))\n",
-    "            if len(XX)==4:\n",
-    "                k1=(YY[0]-YY[1])/(XX[0]-XX[1])\n",
-    "                k3=(YY[2]-YY[3])/(XX[2]-XX[3])\n",
-    "                d1=YY[1]-k1*XX[1]\n",
-    "                d3=YY[3]-k3*XX[3]\n",
-    "                x=np.array([-height/2,height/2])\n",
-    "                y1=gerade(np.array(k1),x,np.array(d1))\n",
-    "                y3=gerade(np.array(k3),x,np.array(d3))\n",
-    "                diff=[]\n",
-    "                for i in range(0,len(excess_save)):\n",
-    "                    upper_line=gerade(np.array(k3),plot_z[i],np.array(d3))\n",
-    "                    lower_line=gerade(np.array(k1),plot_z[i],np.array(d1))  \n",
-    "                    diff.append(np.abs((upper_line-excess_save[i])-(excess_save[i]-lower_line)))\n",
-    "                plot_z=np.array(plot_z)\n",
-    "                x_found=plot_z[diff==min(diff)]\n",
-    "                y_excess_u=gerade(np.array(k3),x_found,np.array(d3))\n",
-    "                y_excess_l=gerade(np.array(k1),x_found,np.array(d1))\n",
-    "                excess_atom_value=y_excess_u[0]-y_excess_l[0]\n",
-    "                excess_value=excess_atom_value/(np.pi*r**2)\n",
-    "                self.ax1.plot([x_found,x_found],[y_excess_l,y_excess_u])\n",
-    "                self.ax1.plot(x,y1,color=color_zyl)\n",
-    "                self.ax1.plot(x,y3,color=color_zyl)\n",
-    "                self.ax1.scatter(XX,YY,color='black',marker='x')\n",
-    "                self.ax1.annotate(\" 1\", (XX[0], YY[0]))\n",
-    "                self.ax1.annotate(\" 2\", (XX[1], YY[1]))\n",
-    "                self.ax1.annotate(\" 3\", (XX[2], YY[2]))\n",
-    "                self.ax1.annotate(\" 4\", (XX[3], YY[3]))\n",
-    "                self.output = Text(height = 10,width = 50,relief=FLAT)\n",
-    "                image_ratio=image_size/2.5\n",
-    "                place_factor=0.25\n",
-    "                place_value=650-place_factor*(650-image_ratio*650)\n",
-    "                self.canvas_all.create_window(650,place_value,window=self.output,tags='message')\n",
-    "                message2='Calculated with the following 4 points: \\n'\n",
-    "                message2=message2+'point 1: x = '+str(XX[0])+'   y = '+str(YY[0])+'\\n'\n",
-    "                message2=message2+'point 2: x = '+str(XX[1])+'   y = '+str(YY[1])+'\\n'\n",
-    "                message2=message2+'point 3: x = '+str(XX[2])+'   y = '+str(YY[2])+'\\n'\n",
-    "                message2=message2+'point 4: x = '+str(XX[3])+'   y = '+str(YY[3])+'\\n'+'\\n'\n",
-    "                message2=message2+'the interfacial excess atoms = '+str(np.round(excess_atom_value,3))+' atoms'+'\\n'\n",
-    "                message2=message2+'the interfacial excess = '+str(np.round(excess_value,3))+' atoms/nm²'\n",
-    "                self.output.insert(END, message2)\n",
-    "                self.output.configure(state='disabled')\n",
-    "                self.canvas.draw_idle()    \n",
-    "            elif len(XX)>=4:messagebox.showinfo(title='APT_analyzer',message='Too many fit points selected. Reduce to 4 points to fit excess.')\n",
-    "        def onclick(event):\n",
-    "            x=np.round(event.xdata,2)\n",
-    "            y=np.round(event.ydata,2)\n",
-    "            self.ax1.scatter(x,y,color='black',marker='x')\n",
-    "            text='x='+str(x)+', y='+str(y)\n",
-    "            self.text_box_ex.insert(END,text)\n",
-    "            self.text_box_ex.insert(END,'\\n')\n",
-    "            self.canvas.draw_idle()   \n",
-    "        if self.diss2==1:self.fig.canvas.mpl_disconnect(self.cid)    \n",
-    "        self.cid=self.fig.canvas.mpl_connect('button_press_event',onclick)\n",
-    "        self.diss2=1\n",
-    "        self.canvas.draw_idle()  \n",
-    "        self.excess_check=1\n",
-    "                    \n",
-    "    def calc_zoom(self):     \n",
-    "        self.plot_exist=0\n",
-    "        self.canvas_all.delete('message')   \n",
-    "        image_size=self.slider_image_size.get()\n",
-    "        image_size=float(image_size)**2\n",
-    "        self.fig.clear()\n",
-    "        self.spec=gridspec.GridSpec(ncols=2,nrows=2,width_ratios=[image_size,1],wspace=0.5,hspace=0.5,height_ratios=[image_size,1]) #adjust the size of the figure compared to (111)\n",
-    "        self.ax2=self.fig.add_subplot(self.spec[0],projection='3d')\n",
-    "        atom= self.cb_atom.get()\n",
-    "        M = self.slider_res.get()\n",
-    "        SS=self.slider_size.get()\n",
-    "        S=float(SS)/10\n",
-    "        u_ele_real=self.ele\n",
-    "        n=len(np.array(self.tip['x']))\n",
-    "        N_plot=int(50000/(10**M))\n",
-    "        if N_plot==0:N_plot=1\n",
-    "        x_real=np.array(self.tip['x'])\n",
-    "        y_real=np.array(self.tip['y'])    \n",
-    "        z_real=np.array(self.tip['z'])\n",
-    "        if self.i_plot.get()==1:                                # atoms z coordinatines inversion\n",
-    "            z_real = -z_real\n",
-    "        c_real=np.array(self.tip['colour'])\n",
-    "        label_real=np.array(self.tip['comp'])\n",
-    "        height = float(self.height.get())\n",
-    "        alpha = -float(self.alpha.get())\n",
-    "        beta = -float(self.beta.get())\n",
-    "        r = float(self.radius.get())\n",
-    "        x_pos = float(self.cly_x.get())\n",
-    "        y_pos = float(self.cly_y.get())\n",
-    "        z_pos = float(self.cly_z.get())\n",
-    "        if self.i_plot.get()==1:                                # cylinder z coordinatines inversion\n",
-    "            z_pos = -z_pos\n",
-    "        color_zyl=str(self.cb_color.get())\n",
-    "        z_start=-height/2\n",
-    "        z_end=height/2\n",
-    "        alpha=math.radians(alpha)\n",
-    "        beta=math.radians(beta)\n",
-    "        ###################   tilt and move zylinder ######################################\n",
-    "        pro=[]\n",
-    "        Z=np.array([x_real-x_pos,y_real-y_pos,z_real-z_pos]).T\n",
-    "        M_ROT1=[(1,      0,                  0     ),            # rotational matrix along the x-direction\n",
-    "                (0,  np.cos(alpha),  -np.sin(alpha)),\n",
-    "                (0,  np.sin(alpha),    np.cos(alpha))]\n",
-    "\n",
-    "        M_ROT2=[(np.cos(beta),      0,       np.sin(beta)),     # rotational matrix along the y-direction\n",
-    "                (0,                  1,            0      ),\n",
-    "                (-np.sin(beta),      0,       np.cos(beta))]\n",
-    "        matrix_l=np.array(M_ROT1).dot(M_ROT2)\n",
-    "        for j in range(0,len(Z)):\n",
-    "                    pro.append(matrix_l.dot(Z[j])) \n",
-    "        Z_new=np.array(pro)\n",
-    "        x_real=Z_new[:,0]\n",
-    "        y_real=Z_new[:,1]\n",
-    "        z_real=Z_new[:,2]\n",
-    "        #########################################################################   \n",
-    "        xy=((x_real)**2+(y_real)**2)**(1/2)\n",
-    "        circle=xy<=r\n",
-    "        for m in range(0,len(u_ele_real)):\n",
-    "            e=label_real[circle]==u_ele_real[m]               #seperation of the atoms \n",
-    "            z_circle=z_real[circle]\n",
-    "            x_circle=x_real[circle]\n",
-    "            y_circle=y_real[circle]\n",
-    "            c_circle=c_real[circle]\n",
-    "            z_p=z_circle[e]  \n",
-    "            x_p=x_circle[e] \n",
-    "            y_p=y_circle[e]\n",
-    "            c_p=c_circle[e]\n",
-    "            init_plot=z_p>=z_start\n",
-    "            x_pl2=x_p[init_plot]\n",
-    "            y_pl2=y_p[init_plot]\n",
-    "            z_pl2=z_p[init_plot]\n",
-    "            c_pl2=c_p[init_plot]\n",
-    "            init_plot2=z_pl2<=z_end    \n",
-    "            x_pl3=x_pl2[init_plot2]\n",
-    "            y_pl3=y_pl2[init_plot2]\n",
-    "            z_pl3=z_pl2[init_plot2]\n",
-    "            c_pl3=c_pl2[init_plot2]\n",
-    "            if atom=='all':\n",
-    "                c_pl3[c_pl3=='#FFFFFF']='#000000'\n",
-    "                x_N=len(x_real[::N_plot])\n",
-    "                self.ax2.scatter3D(x_pl3[::N_plot],y_pl3[::N_plot],z_pl3[::N_plot],c=c_pl3[::N_plot],label=u_ele_real[m],s=S)\n",
-    "                self.ax2.set_title('number of atoms={:.0f},     1/{:.0f} of all atoms'.format(x_N,N_plot)) \n",
-    "            elif u_ele_real[m]==atom:\n",
-    "                c_pl3[c_pl3=='#FFFFFF']='#000000'\n",
-    "                x_N=len(x_pl3[::N_plot])\n",
-    "                self.ax2.scatter3D(x_pl3[::N_plot],y_pl3[::N_plot],z_pl3[::N_plot],c=c_pl3[::N_plot],label=u_ele_real[m],s=S)\n",
-    "                self.ax2.set_title('number of atoms={:.0f},     1/{:.0f} of all atoms of this type'.format(x_N,N_plot))                  \n",
-    "        if self.var_axis.get()==0: \n",
-    "            #self.ax2.set_title('number of atoms=%i' %x_N)\n",
-    "            self.ax2.set_xlabel('X-axis',fontweight='bold')\n",
-    "            self.ax2.set_ylabel('Y-axis',fontweight='bold')\n",
-    "            self.ax2.set_zlabel('Z-axis',fontweight='bold')\n",
-    "        elif self.var_axis.get()==1:\n",
-    "            self.ax2.set_axis_off()         \n",
-    "        apt.set_axes_equal(self.ax2)   \n",
-    "        self.ax2.legend() \n",
-    "        if self.var_cyl.get()==1:\n",
-    "            x_pos = float(self.cly_x.get())\n",
-    "            y_pos = float(self.cly_y.get())\n",
-    "            z_pos = float(self.cly_z.get())\n",
-    "            height = float(self.height.get())\n",
-    "            alpha = float(self.alpha.get())\n",
-    "            beta = float(self.beta.get())\n",
-    "            r = float(self.radius.get())\n",
-    "            color_zyl=str(self.cb_color.get())\n",
-    "            theta=np.linspace(0,2*np.pi,201)\n",
-    "            z_start=-height/2\n",
-    "            z_end=height/2\n",
-    "            alpha=math.radians(alpha)\n",
-    "            beta=math.radians(beta)\n",
-    "        \n",
-    "            y_circle=r*np.cos(theta)\n",
-    "            x_circle=r*np.sin(theta)\n",
-    "            z_circle_s=np.ones(201)*z_start\n",
-    "            z_circle_e=np.ones(201)*z_end\n",
-    "\n",
-    "            x_line1=np.ones(201)*r\n",
-    "            x_line2=np.ones(201)*-r\n",
-    "            y_line=np.ones(201)*0\n",
-    "            z_line=np.linspace(z_start,z_end,201)\n",
-    "            lw=5\n",
-    "            self.ax2.plot(x_line1,y_line,z_line,color_zyl,linewidth=lw)\n",
-    "            self.ax2.plot(x_line2,y_line,z_line,color_zyl,linewidth=lw)\n",
-    "            self.ax2.plot(x_circle,y_circle,z_circle_s,color_zyl,linewidth=lw)  \n",
-    "            self.ax2.plot(x_circle,y_circle,z_circle_e,color_zyl,linewidth=lw) \n",
-    "        self.canvas.draw_idle() \n",
-    "\n",
-    "tk = Tk()                                                                      # tkinter\n",
-    "tk.title(\"APT analyzer\")                                                       # select title of tool\n",
-    "tk.geometry('1100x700')                                                        # select size of tool\n",
-    "tt=APT_analyzer(tk)                                                            # select tool              \n",
-    "tk.mainloop()                                                                  # start tool"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "2b4bf9ed-bc19-456f-99b6-c0cfe5691b57",
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3 (ipykernel)",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.9.12"
-  }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/docker/apmtools/Cheatsheet.ipynb b/docker/apmtools/Cheatsheet.ipynb
index cd86404bf13e1f8777ec0a6c80e5dc448a89b328..07614ea6e7ffbfb0958695e2b45f35a87134fb4a 100644
--- a/docker/apmtools/Cheatsheet.ipynb
+++ b/docker/apmtools/Cheatsheet.ipynb
@@ -5,7 +5,7 @@
    "id": "88054eb2",
    "metadata": {},
    "source": [
-    "![FAIRmat](FAIRmat_S.png)"
+    "<img src=\"NOMADOasisLogo.png\" alt=\"Drawing\" style=\"height: 149px;\"/>&emsp;&emsp;<img src=\"FAIRmatNewLogo.png\" alt=\"Drawing\" style=\"height: 149px;\"/>"
    ]
   },
   {
@@ -21,17 +21,44 @@
    "id": "4091c1e2",
    "metadata": {},
    "source": [
-    "The apmtools container offers functionalities to work, i.e. perform data analyses<br>\n",
+    "The apmtools container offers functionalities to work and perform data analyses<br>\n",
     "with reconstructed and ranged datasets from atom probe microscopy experiments.<br>\n",
     "\n",
-    "This container includes two tools for processing of atom probe data:\n",
-    "* The **Leoben APT_analyzer** by Alexander Reichmann et al.\n",
-    "* The **paraprobe-toolbox** by Markus Kühbach et al.\n",
+    "This container includes three tools:\n",
+    "* **APTyzer** by Alexander Reichmann et al. https://github.com/areichm/APTyzer\n",
+    "* **paraprobe-toolbox** by Markus Kühbach et al. https://gitlab.com/paraprobe/paraprobe-toolbox\n",
+    "* **APAV** by Jesse Smith et al. https://gitlab.com/jesseds/apav\n",
     "\n",
-    "Each tool comes with a tutorial-style example.\n",
+    "Each tool comes shipped with tutorial-style examples.\n",
     "***"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "e7afeb96-16a6-4d5a-9986-7aacfc9980f4",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "<div class=\"alert alert-block alert-info\">\n",
+    "Having APTyzer, APAV, and paraprobe-toolbox configured in one container comes with the benefit<br>\n",
+    "that one can switch between using these tools or couple them together via an e.g. jupyter notebook.\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fd044275-1ce9-4fea-bbe8-9903c3620a18",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "<div class=\"alert alert-block alert-info\">\n",
+    "Containers of the Nomad Remote Tools Hub (NORTH) are configured such that they have access to the data in the uploads section of the Oasis instance.<br>\n",
+    "Individual examples which exemplify how to use the tools in the apmtools container may have to be unpacked/decompressed before their first use.\n",
+    "</div>"
+   ]
+  },
   {
    "cell_type": "markdown",
    "id": "69238a64",
@@ -39,29 +66,31 @@
     "tags": []
    },
    "source": [
-    "# Getting started with the Leoben APT_analyzer"
+    "# Getting started with APTyzer"
    ]
   },
   {
    "cell_type": "markdown",
-   "id": "6e324fa1",
+   "id": "4aa12615-4734-4802-b6b9-407d6f1797bd",
    "metadata": {},
    "source": [
-    "The Leoben APT_analyzer is a Python-based tool with a GUI which can be used to display tomographic<br>\n",
-    "reconstructions for performing composition and interfacial excesses analyses. The tool is maintained<br>\n",
-    "by Alexander Reichmann at the Montanuniversität Leoben.<br>\n",
-    "\n",
-    "First you should navigate into the respective directory of the tool.<br>"
+    "<div class=\"alert alert-block alert-info\">\n",
+    "Computational requirements: Examples with dataset with a few million ions like most used below should be processable even on a computer with a single core and say at least 4GB main memory.\n",
+    "</div>"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": null,
-   "id": "5fd98af7",
+   "cell_type": "markdown",
+   "id": "6e324fa1",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "! cd /home/atom_probe_tools/leoben_apt_analyzer"
+    "APTyzer is a Python-based tool with a graphical user interface (GUI) which can be used for displaying of a tomographically<br>\n",
+    "reconstructed atom probe dataset thus enabling composition and interfacial excesses analyses. APTyzer can also be used for<br>\n",
+    "preparing the meshing of single interface patches (grain or phase boundaries) via setting control points manually.<br>\n",
+    "These points can be exported and loaded with the paraprobe-toolbox. APTyzer is maintained by Alexander Reichmann,<br>\n",
+    "who is a PhD student with Lorenz Romaner at the Montanuniversität Leoben, Austria.<br>\n",
+    "\n",
+    "To use the tool you should navigate into the respective sub-directory.<br>"
    ]
   },
   {
@@ -69,7 +98,17 @@
    "id": "1aa22278",
    "metadata": {},
    "source": [
-    "### Step 1: Enter the leoben_apt_analyzer sub-directory via the explorer panel on the left side"
+    "### Step 1: Navigate into the respective sub-directory via the explorer panel on the left side"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5fd98af7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "! cd /home/atom_probe_tools/aptyzer"
    ]
   },
   {
@@ -77,7 +116,7 @@
    "id": "cc1408cc-45ec-40c6-90cb-dcec5f900619",
    "metadata": {},
    "source": [
-    "### Step 2: Download an example dataset to get started with the leoben_apt_analyzer"
+    "### Step 2: Download and unpack an example dataset to get started"
    ]
   },
   {
@@ -87,7 +126,23 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "! cd /home/atom_probe_tools/leoben_apt_analyzer && wget https://www.zenodo.org/record/6794809/files/aut_leoben_leitner.tar.gz && tar -xvf aut_leoben_leitner.tar.gz"
+    "! cd /home/atom_probe_tools/aptyzer && wget https://www.zenodo.org/record/6794809/files/aut_leoben_leitner.tar.gz && tar -xvf aut_leoben_leitner.tar.gz"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1d7b6c36-5967-46be-835d-3678c4ef8865",
+   "metadata": {},
+   "source": [
+    "### Step 3: Start APTyzer by executing the APT_analyzer.ipynb in a new browser tab"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "65cc8b4d-3f83-49fd-94f8-4309852499de",
+   "metadata": {},
+   "source": [
+    "Open the aptyzer.ipynb via the JupyterLab side bar (on the left side). Clicking through this notebook will start the graphical user interface."
    ]
   },
   {
@@ -95,7 +150,6 @@
    "id": "8cea07f1-ccc5-40f4-881a-f9fec8a3f206",
    "metadata": {},
    "source": [
-    "### Step 3: Start the apt_analyzer by executing the leoben_apt_analyzer.ipynb in a new browser tab\n",
     "### Step 4: Run the tool using the POS and RRNG with the aut_leoben_leitner example dataset."
    ]
   },
@@ -104,13 +158,13 @@
    "id": "051121d5-f318-42a7-81d8-a11349401e4c",
    "metadata": {},
    "source": [
-    "There is a detailed tutorial (cheatsheet.pdf) for the APT_analyzer in the sub-directory of the tool.<br>\n",
-    "\n",
-    "The APT_analyzer enables to export manually selected control points to support building computational<br>\n",
-    "geometry models of interfaces. These control points can be exported to an HDF5 file and this file be<br>\n",
-    "used as input for the paraprobe-toolbox. Specifically, the control points can be used to instruct<br>\n",
-    "paraprobe-nanochem to attempt an automatic modelling of an interface.\n",
-    "\n",
+    "There is a detailed tutorial (tutorial.pdf) how to use APTyzer for arbitary datasets. The tool offers export functionalities<br>\n",
+    "for manually selected control points to support building computational geometry models of interfaces.<br>\n",
+    "These control points can be exported to an HDF5 file and this file can be used for example as input for the<br>\n",
+    "paraprobe-nanochem tool from the paraprobe-toolbox.<br>\n",
+    "A respective tutorial how to achieve this is available in the paraprobe-toolbox teaching material<br>\n",
+    "and here specifically the aut_leoben_leitner example. This tutorial will show how to use the<br>\n",
+    "control points and create an automatically meshed model for an interface in the dataset.<br>\n",
     "***"
    ]
   },
@@ -124,20 +178,42 @@
     "# Getting started with paraprobe-toolbox"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "144832aa-b357-406c-84ad-d410d27bd8c0",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "<div class=\"alert alert-block alert-info\">\n",
+    "Computational requirements: Examples with dataset with a few million ions like most used below should be processable even on a computer with a single core<br>\n",
+    "and four GB main memory. Having multiple CPU cores can be useful as the tools of the paraprobe-toolbox use multi-threading for most of the<br>\n",
+    "numerical and geometrical analyses.<br>\n",
+    "Making guarantees about the maximum data set sizes (in terms of number of ions) is difficult as it strongly depends on which type of analyses are performed<br>\n",
+    "and how these are parameterized. Noteworthy to mention is that even the largest examples at the time of writing this cheatsheet which are available in the<br>\n",
+    "paraprobe-toolbox were processable with a laptop with 32GB main memory in total. Examples with a few million ions consumed not more than one to eight GB.<br>\n",
+    "</div>"
+   ]
+  },
   {
    "cell_type": "markdown",
    "id": "ec70f493",
    "metadata": {},
    "source": [
-    "The paraprobe-toolbox is a collection of software tools for applying computational geometry tasks on tomographic<br>\n",
-    "reconstructions of atom probe data to extract and characterize microstructural features. The tool is developed<br>\n",
-    "by <a href=\"https://arxiv.org/abs/2205.13510\">Markus Kühbach et al.</a>. The tool is instructed via a jupyter notebook which documents a script of analysis steps.<br>\n",
+    "The paraprobe-toolbox is a collection of software tools for applying computational geometry tasks on point cloud data<br>\n",
+    "such as tomographic reconstructions of atom probe data to extract and characterize microstructural features.<br>\n",
+    "The tool is developed by <a href=\"https://arxiv.org/abs/2205.13510\">Markus Kühbach et al.</a>. The tool is instructed via a jupyter notebook which documents<br>\n",
+    "how to chain via scripting different analysis steps. Apart from this, it is possible to use the tools via<br>\n",
+    "Python scripting to perform e.g. batch processing on computer clusters.<br>\n",
     "\n",
-    "During the workflow atom probe data are processable with multiple computational steps.<br>\n",
-    "Each step uses a different scientific speciality tool. These use CPU parallelization and performance libraries.<br>\n",
-    "The jupyter notebooks enable users to script the steps of the workflow to automate many steps of the<br>\n",
-    "data analysis in a reproducible and documented way including iso-surface computations, parameter<br>\n",
-    "studies, mesh processing, and writing reports or creating plots automatically.<br>"
+    "Tools of the paraprobe-toolbox are chained into computational workflows. Each step uses a different scientific<br>\n",
+    "speciality tool. All these tools have *paraprobe* as a prefix in their executable name.<br>\n",
+    "The tools use CPU parallelization and specific libraries of the computational geometry or other specialists'<br>\n",
+    "communities. The jupyter notebooks enable users to achieve a complete automation of their<br>\n",
+    "data analyses (if this is desired). Internally, each tools keeps track of input and output files via<br>\n",
+    "hashes and time stamps to enable provenance tracking and support repeatable and reproducible research.<br>\n",
+    "All results are openly accessible and documented via so-called <a href=\"https://fairmat-experimental.github.io/nexus-fairmat-proposal\">NeXus application definitions (see the NORTH/apmtools pages).</a><br>\n",
+    "Such workflows can include parameter studies, mesh processing, writing of reports, and creation of plots.<br>"
    ]
   },
   {
@@ -147,14 +223,16 @@
     "tags": []
    },
    "source": [
-    "### Step 1: Enter the paraprobe-toolbox/teaching/example_analyses sub-directory using the jupyter explorer panel to the left."
+    "### Step 1: Enter the paraprobe-toolbox/teaching/example_analyses sub-directory via the explorer panel to the left."
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
    "id": "f6461c64-cbcd-4d0a-8be3-850205382a71",
-   "metadata": {},
+   "metadata": {
+    "tags": []
+   },
    "outputs": [],
    "source": [
     "# analysis results are stored here:\n",
@@ -170,13 +248,11 @@
    "id": "bce1299f-24fb-4ffc-99d3-99aac8921136",
    "metadata": {},
    "source": [
-    "Reconstruction and ranging data (i.e. POS, ePOS, APT, RNG, RRNG, NXS) to be consumed by paraprobe should be stored in *teaching/example_data*<br>\n",
-    "Analyses with relevant IPYNB jupyter notebooks should be stored in *teaching/example_analyses*\n",
+    "Reconstruction and ranging data (i.e. POS, ePOS, APT, RNG, RRNG, NXS) to be consumed by paraprobe-toolbox should be stored in *teaching/example_data*.<br>\n",
+    "Analyses with relevant jupyter notebooks should be stored in *teaching/example_analyses*.\n",
     "\n",
-    "**Using NeXus:** the tools have been modified to enable now reading also data from NeXus/HDF5 files\n",
-    "which have been created<br>\n",
-    "with the NXapm application definition (see <a href=\"https://fairmat-experimental.github.io/nexus-fairmat-proposal\">nexus-fairmat-proposal</a> and here specifically<br>\n",
-    "the section about atom probe for more details)."
+    "The tools use NeXus data schemas and HDF5 files. The specification of these files is documented in the so-called<br>\n",
+    "<a href=\"https://fairmat-experimental.github.io/nexus-fairmat-proposal\">nexus-fairmat-proposal</a> (see specifically the NORTH/apmtools pages)."
    ]
   },
   {
@@ -184,15 +260,7 @@
    "id": "670cc82a-2ea2-4a48-bded-793b15e2f58f",
    "metadata": {},
    "source": [
-    "### Step 2: Unpack one of the example datasets or use a NeXus/HDF5 file from your upload section."
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "id": "31c88293-1cc5-48dd-9f3a-ada16de9ac65",
-   "metadata": {},
-   "source": [
-    "Individual examples have to be unpacked/decompressed before you can use them.<br>"
+    "### Step 2: Unpack the example datasets or use a NeXus/HDF5 file from your uploads section."
    ]
   },
   {
@@ -202,7 +270,8 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "! cd /home/atom_probe_tools/paraprobe-toolbox/teaching/example_data/usa_portland_wang && tar -xvf usa_portland_wang.tar.gz"
+    "! cd /home/atom_probe_tools/paraprobe-toolbox/teaching/example_data/usa_portland_wang && tar -xvf usa_portland_wang.tar.gz\n",
+    "! cd /home/atom_probe_tools/paraprobe-toolbox/teaching/example_data/aut_leoben_leitner && tar -xvf aut_leoben_leitner.tar.gz"
    ]
   },
   {
@@ -210,15 +279,15 @@
    "id": "c409e217-e14a-4bba-a07e-e16753288bd8",
    "metadata": {},
    "source": [
-    "Alternatively, **If you have already a NeXus/HDF5 file in your upload section you can also use this file.**<br>\n",
-    "In order to do so you can move that file into one of the example_data analysis section inside<br>\n",
-    "the container. This works because the container is configured such that the directory which<br>\n",
-    "represents the upload section is mounted into the container and accessible via the config section.<br>"
+    "Alternatively, NeXus/HDF5 files in your uploads section can also be used. In order to do so, you can move<br>\n",
+    "the respective file(s) into one of the example_data analysis sections inside the container.<br>\n",
+    "This works because the container is configured such that the directory which represents<br>\n",
+    "the uploads section is mounted into the apmtools container and is accessible via config directory.<br>"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": null,
    "id": "22c54c6b-fe0d-4e47-9247-4d5f42761134",
    "metadata": {},
    "outputs": [],
@@ -231,7 +300,7 @@
    "id": "4fa357bd-7e4a-4c78-afeb-cc4debe34f48",
    "metadata": {},
    "source": [
-    "### Step 3: Explore the usage of the tool via jupyter notebooks. Start with the unpacked example usa_portland_wang."
+    "### Step 3: Start with the unpacked example usa_portland_wang."
    ]
   },
   {
@@ -239,8 +308,15 @@
    "id": "8c8865e7-70e9-4309-93c3-5eaf73e2d2e0",
    "metadata": {},
    "source": [
-    "Each example comes with a detailed jupyter notebook which guides through the analysis. This notebook documents the workflow<br>\n",
-    "and instructs it by orchestrating the interaction between python tools, C/C++ tools, HDF5, and H5Web for visualization."
+    "Each example of the paraprobe-toolbox comes with a detailed jupyter notebook which guides through the analysis.<br>\n",
+    "Especially the usa_portland_wang and the aut_leoben_leitner (see connection to APTyzer tool) examples<br>\n",
+    "show the multi-faceted analysis features of the tools in the paraprobe-toolbox.<br>\n",
+    "These examples show how Python and C/C++ applications work together with NeXus, HDF5, and H5Web<br>\n",
+    "to provide tools which can be flexibly be coupled to other open-source atom probe software and<br>\n",
+    "used to complement analyses which have been achieved with commercial software like APSuite/IVAS.<br>\n",
+    "More complex examples with customizable jupyter notebooks are available in the documentation<br>\n",
+    "of the tool https://paraprobe-toolbox.readthedocs.io/en/latest/.<br>\n",
+    "***"
    ]
   },
   {
@@ -248,11 +324,153 @@
    "id": "80d09ac1-e56d-4923-9ba3-9e869d368a51",
    "metadata": {},
    "source": [
-    "The tool is described in further details in various places https://arxiv.org/abs/2205.13510 and<br>\n",
-    "https://gitlab.com/paraprobe/paraprobe-toolbox <br>\n",
-    "The notebooks exemplify how individual tools of the toolbox interact.\n",
+    "# Getting started with APAV"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bfec8daa-59c3-47b9-a0af-8f03afd5c9a6",
+   "metadata": {},
+   "source": [
+    "<div class=\"alert alert-block alert-info\">\n",
+    "Computational requirements: Examples with dataset with a few million ions like most used below should be processable even on a computer with a single core and say at least 4GB main memory.<br>\n",
+    "Having multiple CPU cores can be useful as APAV uses multi-threading for some costly numerical analyses.\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c10fcef1-e82f-4400-af22-f6df70687faf",
+   "metadata": {},
+   "source": [
+    "APAV (Atom Probe Analysis and Visualization) is a Python package for analysis and visualization of atom probe tomography datasets.<br>\n",
+    "The tool is developed by <a href=\"https://joss.theoj.org/papers/10.21105/joss.04862\">Jesse Smith et al.</a>. Complementary to the design of the paraprobe-toolbox functionalities,<br>\n",
+    "APAV can be chained into workflows via e.g. a jupyter notebook. A particular functional strength and focus of APAV<br>\n",
+    "has been ranging and handling of so-called multi-hit events via a graphical user interface via Python.<br>\n",
+    "\n",
+    "APAV has a detailed documentation https://apav.readthedocs.io/en/latest/index.html."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b75f60d5-3151-4986-9222-ddaeb1fa7e5f",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "<div class=\"alert alert-block alert-info\">\n",
+    "Jesse Smith has also made available example data which can be used for learning the multi-hit event analyses capabilities of APAV. If these files are not available <a href=\"https://doi.org/10.5281/zenodo.6794809\">via this Zenodo repository (version >9)</a>,<br>\n",
+    "users are requested to inspect the respective file share location from the revision of the APAV JOSS paper <a href=\"https://github.com/openjournals/joss-reviews/issues/4862\">see the comment from jdasm from November 30, 2022 here</a><br>\n",
+    "The respective GBCO dataset relevant here is especially this one R5038_00333-v02.epos.  <a href=\"https://doi.org/10.1017/S1431927621012794\">Scientific details can be found here</a>.\n",
+    "</div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f88501b0-a4bd-427d-b303-a45a3556ab35",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "### Step 1: Enter the apav sub-directory via the explorer panel to the left."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "474644bb-75fd-4514-bab5-8d9d30e46610",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "! ls /home/atom_probe_tools/apav"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ba59fb6e-2b63-4e95-99f7-75248c2a4f79",
+   "metadata": {},
+   "source": [
+    "### Step 2: Use available files in community-specific formats from your uploads section or download the above-mentioned examples from APAV."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "f9bf1d28-abff-4628-aaa8-cb61f796e412",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import shutil"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "5d092aaf-663d-4ef3-9ac7-5fc6762d785f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "! cd /home/atom_probe_tools/apav && wget https://www.zenodo.org/record/77885531/files/apm_sprint14_apav_usa_denton_smith.zip && shutil.unpack_archive(\"apm_sprint14_apav_usa_denton_smith.zip\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f65c621e-05f5-45ca-9a01-4cbd3206bc55",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "The APAV documentation details which formats are supported."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9e3fb02c-1706-4864-a27c-06aaadc5c11b",
+   "metadata": {
+    "tags": []
+   },
+   "source": [
+    "### Step 3: Start a new jupyter-notebook and use it to compose your own analysis workflow."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "57c641c2-748c-4c8a-a2f1-4d9428f141a5",
+   "metadata": {},
+   "source": [
+    "The APAV documentation can support you with starting your own analyses.\n",
     "***"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a27bbf75-8a2a-4df3-8096-f942afc5e656",
+   "metadata": {},
+   "source": [
+    "# Version, funding, feedback\n",
+    "* **APTyzer** https://github.com/areichm/APTyzer 887b82f\n",
+    "* **paraprobe-toolbox** https://gitlab.com/paraprobe/paraprobe-toolbox e349fd3 (v0.4)\n",
+    "* **APAV** https://pypi.org/project/APAV v1.4.0\n",
+    "* **NeXus** https://fairmat-experimental.github.io/nexus-fairmat-proposal latest\n",
+    "\n",
+    "Last revision: Markus Kühbach, 2023/04/17\n",
+    "\n",
+    "<a href=\"https://www.fairmat-nfdi.eu/fairmat/\">FAIRmat</a> is a consortium on research data management which is part of the German NFDI.<br>\n",
+    "The project is funded by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) – project 460197019.\n",
+    "\n",
+    "If you spot issues with this container or you would like to suggest how we can improve the apmtools container:<br>\n",
+    "Please contact the respective maintainer of this container."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "ff8b1235-d4c8-4ce0-9013-d1d87b7191df",
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
@@ -271,7 +489,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.9.12"
+   "version": "3.8.16"
   }
  },
  "nbformat": 4,
diff --git a/docker/apmtools/Dockerfile b/docker/apmtools/Dockerfile
index 559ea7f38469bd974a7584f0c3115fd7aab8b827..bd71db8477b83a684b2b72d68b6a11e0544d32b0 100644
--- a/docker/apmtools/Dockerfile
+++ b/docker/apmtools/Dockerfile
@@ -1,7 +1,7 @@
 # recipe to create the nomad-remote-tools-hub apmtools container via a dockerfile
 FROM gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/webtop
 
-# # for testing the container locally without running in oauth errors
+# for testing the container locally without running in oauth errors
 # FROM ghcr.io/linuxserver/webtop:amd64-ubuntu-openbox-version-e1079163
 # # found that newest system python is 3.8.something
 # # rest should come only from and be managed through (mini)conda not pip!
@@ -16,67 +16,62 @@ FROM gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/webtop
 
 USER root
 
-# query version afterwards like so dpkg -s <packagename> | grep '^Version:'
-# OS dependencies, low-level system libraries
-RUN apt-get update
-RUN apt-get install -y git=1:2.25.1-1ubuntu3.5 \
-  && apt-get install -y m4=1.4.18-4 \
-  && apt-get install -y file=1:5.38-4 \
-  && apt-get install -y wget=1.20.3-1ubuntu2 \
-  && apt-get install -y mesa-common-dev=21.2.6-0ubuntu0.1~20.04.2 \
-  && apt-get install -y libglu1-mesa-dev=9.0.1-1build1 \
-  && apt-get install -y build-essential=12.8ubuntu1.1 \
-  && apt-get install -y mpich=3.3.2-2build1 \
-  && apt-get install -y libgmp-dev=2:6.2.0+dfsg-4 \
-  && apt-get install -y libmpfr-dev=4.0.2-1 \
-  && rm -rf /var/lib/apt/lists/* \
-  && mkdir -p /home \
+RUN mkdir -p /home \
   && mkdir -p /home/atom_probe_tools \
-  && wget https://repo.anaconda.com/miniconda/Miniconda3-py39_4.12.0-Linux-x86_64.sh \
-  && mv Miniconda3-py39_4.12.0-Linux-x86_64.sh miniconda3_py3.9_4.12.0_linux_x86_64.sh \
-  && chmod +x miniconda3_py3.9_4.12.0_linux_x86_64.sh \
-  && bash ./miniconda3_py3.9_4.12.0_linux_x86_64.sh -b -p /usr/local/miniconda3 \
-  && rm -f miniconda3_py3.9_4.12.0_linux_x86_64.sh
+  && mkdir -p /home/atom_probe_tools/apav \
+  && mkdir -p /home/atom_probe_tools/aptyzer
 
-# future improvements should use --no-install-recommends to safe space further, but for mpich this created problems when building paraprobe
+COPY Cheatsheet.ipynb FAIRmatNewLogo.png NOMADOasisLogo.png /home/atom_probe_tools/
+ENV PATH=/usr/local/miniconda3/bin:/home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/cmake/cmake-3.26.3/localinstallation/bin:$PATH
 
-COPY Cheatsheet.ipynb FAIRmat_S.png APT_analyzer.ipynb /home/atom_probe_tools/
-
-# add all relevant environment variables that required for building the 
-# container make sure to reflect eventual changes of the cmake version
-ENV PATH=/usr/local/miniconda3/bin:/home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/cmake/cmake-3.22.2/localinstallation/bin:$PATH
+# query version afterwards like so dpkg -s <packagename> | grep '^Version:'
+# OS dependencies, low-level system libraries, --fix-missing, rm -rf /var/lib/apt/lists/*
+# future improvements should use --no-install-recommends to safe space further, but for mpich this created problems when building paraprobe-toolbox
 
-RUN mkdir -p /home \
+RUN cd ~ \
+  && apt update \
+  && apt install -y curl=7.68.0-1ubuntu2.18 \
+  && curl -sL https://deb.nodesource.com/setup_18.x -o nodesource_setup.sh \
+  && chmod +x nodesource_setup.sh \
+  && ./nodesource_setup.sh \
+  && apt install -y nodejs=18.16.0-deb-1nodesource1 \
+  && apt install -y m4=1.4.18-4 file=1:5.38-4 git=1:2.25.1-1ubuntu3.11 wget=1.20.3-1ubuntu2 mesa-common-dev=21.2.6-0ubuntu0.1~20.04.2 libglu1-mesa-dev=9.0.1-1build1 build-essential=12.8ubuntu1.1 mpich=3.3.2-2build1 libgmp-dev=2:6.2.0+dfsg-4ubuntu0.1 libmpfr-dev=4.0.2-1 libssl-dev=1.1.1f-1ubuntu2.18 hwloc=2.1.0+dfsg-4 \
+  && wget https://repo.anaconda.com/miniconda/Miniconda3-py38_23.1.0-1-Linux-x86_64.sh \
+  && mv Miniconda3-py38_23.1.0-1-Linux-x86_64.sh miniconda3-py38_23.1.0-1-Linux-x86_64.sh \
+  && chmod +x miniconda3-py38_23.1.0-1-Linux-x86_64.sh \
+  && bash ./miniconda3-py38_23.1.0-1-Linux-x86_64.sh -b -p /usr/local/miniconda3 \
+  && rm -f miniconda3-py38_23.1.0-1-Linux-x86_64.sh \
   && cd /home \
   && conda config --add channels conda-forge \
   && conda config --set channel_priority strict \
-  && conda install python ipykernel=6.15.3 gitpython=3.1.27 nomkl=1.0 pandas=1.4.4 ase=3.22.1 radioactivedecay=0.4.15 scikit-learn=1.1.2 silx=1.0.0 jupyterlab=3.4.7 nodejs=18.9.0 \
-  && pip install jupyterlab_h5web[full]==6.0.1 \
+  && conda install -c conda-forge nomkl=1.0 jupyterlab-h5web=7.0.0 jupyterlab=3.6.3 hdbscan=0.8.29 gitpython=3.1.31 nodejs=18.15.0 ase=3.19.0 radioactivedecay=0.4.17 pandas=2.0.0 sphinx=6.1.3 \
   && conda clean -afy \
-  && mkdir -p /home/atom_probe_tools \
-  && mkdir -p /home/atom_probe_tools/leoben_apt_analyzer \
-  && git clone https://github.com/areichm/APT_analyzer.git \
-  && cd APT_analyzer \
-  && git checkout 6ee93ca6052c221ae335cbaa2a218911024301fa \
-  && cp APT_analyzer_tutorial.pdf /home/atom_probe_tools/leoben_apt_analyzer/cheatsheet.pdf \
-  && cp /home/atom_probe_tools/APT_analyzer.ipynb /home/atom_probe_tools/leoben_apt_analyzer/leoben_apt_analyzer.ipynb \
-  && cp LICENSE /home/atom_probe_tools/leoben_apt_analyzer/LICENSE \
-  && cp README.md /home/atom_probe_tools/leoben_apt_analyzer/README.md \
-  && cp apt_importers.py /home/atom_probe_tools/leoben_apt_analyzer/apt_importers.py \
-  && cd .. \
-  && rm -rf APT_analyzer \
-  && rm /home/atom_probe_tools/APT_analyzer.ipynb \
+  && cd /home \
+  && python3 -m pip install --upgrade pip \
+  && python3 -m pip install ecdf==0.7.0 pytictoc==1.5.2 ifes-apt-tc-data-modeling==0.0.8 python-docs-theme==2023.3.1 \
+  && cd /home \
+  && cd /home/atom_probe_tools/apav \
+  && python3 -m pip install apav==1.4.0 \
+  && cd /home/atom_probe_tools \
+  && git clone https://github.com/areichm/APTyzer.git \
+  && cd APTyzer \
+  && git checkout 887b82f \
+  && cp APTyzer_V_1_2o.ipynb /home/atom_probe_tools/aptyzer/aptyzer.ipynb \
+  && cp LICENSE /home/atom_probe_tools/aptyzer/LICENSE \
+  && cp README.md /home/atom_probe_tools/aptyzer/README.md \
+  && cp Tutorial_APTyzer_V1_2.pdf /home/atom_probe_tools/aptyzer/tutorial.pdf \
+  && rm -rf /home/atom_probe_tools/APTyzer \
   && cd /home/atom_probe_tools \
   && git clone https://gitlab.com/paraprobe/paraprobe-toolbox.git \
   && cd paraprobe-toolbox \
-  && git checkout b95be8c9e79f044fd8716ffe5d2b7adf4e14208d \
+  && git checkout e349fd34d7cfcb4282c2f3f61c69f9e5659f68e6 \
   && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
   && mkdir -p cmake \
   && cd cmake \
-  && wget https://cmake.org/files/v3.22/cmake-3.22.2.tar.gz \
-  && tar -xvf cmake-3.22.2.tar.gz \
-  && rm -rf cmake-3.22.2.tar.gz \
-  && cd cmake-3.22.2 \
+  && wget https://cmake.org/files/v3.26/cmake-3.26.3.tar.gz \
+  && tar -xvf cmake-3.26.3.tar.gz \
+  && rm -rf cmake-3.26.3.tar.gz \
+  && cd cmake-3.26.3 \
   && mkdir -p localinstallation \
   && chmod +x bootstrap \
   && ./bootstrap --prefix="$PWD/localinstallation/" -- -DCMAKE_USE_OPENSSL=OFF 2>&1 | tee PARAPROBE.CMake.Bootstrap.STDOUTERR.txt \
@@ -85,37 +80,18 @@ RUN mkdir -p /home \
   && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
   && mkdir -p hdf5 \
   && cd hdf5 \
-  && wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.13/hdf5-1.13.2/src/CMake-hdf5-1.13.2.tar.gz \
-  && gunzip CMake-hdf5-1.13.2.tar.gz \
-  && tar -xvf CMake-hdf5-1.13.2.tar \
-  && rm -rf CMake-hdf5-1.13.2.tar \
-  && cd CMake-hdf5-1.13.2 \
+  && wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.14/hdf5-1.14.0/src/CMake-hdf5-1.14.0.tar.gz \
+  && tar -xvf CMake-hdf5-1.14.0.tar.gz \
+  && rm -rf CMake-hdf5-1.14.0.tar.gz \
+  && cd CMake-hdf5-1.14.0 \
   && ./build-unix.sh 2>&1 | tee PARAPROBE.Hdf5.Build.STDOUTERR.txt \
-  && ./HDF5-1.13.2-Linux.sh --include-subdir --skip-license 2>&1 | tee PARAPROBE.Hdf5.Install.STDOUTERR.txt \
+  && ./HDF5-1.14.0-Linux.sh --include-subdir --skip-license 2>&1 | tee PARAPROBE.Hdf5.Install.STDOUTERR.txt \
   && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
   && mkdir -p boost \
   && cd boost \
-  && wget https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_1_80_0.tar.gz \
-  && tar -xvf boost_1_80_0.tar.gz \
-  && rm -f boost_1_80_0.tar.gz \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
-  && mkdir -p fftw \
-  && cd fftw \
-  && wget https://www.fftw.org/fftw-3.3.10.tar.gz \
-  && tar -xvf fftw-3.3.10.tar.gz \
-  && rm -f fftw-3.3.10.tar.gz \
-  && cd fftw-3.3.10 \
-  && mkdir -p localinstallation \
-  && ./configure --prefix="$PWD/localinstallation/" --enable-float --enable-sse 2>&1 | tee PARAPROBE.FFTW.Configure.STDOUTERR.txt \
-  && make -j4 2>&1 | tee PARAPROBE.FFTW.Make4.STDOUTERR.txt \
-  && make check 2>&1 | tee PARAPROBE.FFTW.MakeCheck.STDOUTERR.txt \
-  && make install 2>&1 | tee PARAPROBE.FFTW.MakeInstall.STDOUTERR.txt \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
-  && mkdir -p tetgen \
-  && cd tetgen \
-  && tar -xvf tetgen1.6.0.tar.gz \
-  && cd tetgen1.6.0 \
-  && make -j4 tetlib 2>&1 | tee PARAPROBE.TetGen.Make4.STDOUTERR.txt \
+  && wget https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz \
+  && tar -xvf boost_1_81_0.tar.gz \
+  && rm -f boost_1_81_0.tar.gz \
   && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
   && mkdir -p eigen \
   && cd eigen \
@@ -125,80 +101,54 @@ RUN mkdir -p /home \
   && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
   && mkdir -p cgal \
   && cd cgal \
-  && wget https://github.com/CGAL/cgal/releases/download/v5.5/CGAL-5.5.tar.xz \
-  && tar -xvf CGAL-5.5.tar.xz \
-  && rm -f CGAL-5.5.tar.xz \
+  && wget https://github.com/CGAL/cgal/releases/download/v5.5.2/CGAL-5.5.2.tar.xz \
+  && tar -xvf CGAL-5.5.2.tar.xz \
+  && rm -f CGAL-5.5.2.tar.xz \
   && cd /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory \
   && mkdir -p voroxx \
   && cd voroxx \
   && git clone https://github.com/chr1shr/voro.git \
   && cd voro \
   && git checkout 56d619faf3479313399516ad71c32773c29be859 \
-  && cd .. \
-  && mv voro voro++-0.4.6 \
   && cd /home/atom_probe_tools/paraprobe-toolbox \
-  && sed -i 's|set(MYPROJECTPATH "<<YOURPATH>>")|set(MYPROJECTPATH \"'"$PWD"'\/\")|g' /home/atom_probe_tools/paraprobe-toolbox/code/PARAPROBE.Dependencies.cmake \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-utils/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-utils/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-ranger/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-ranger/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && cp paraprobe_ranger /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_ranger \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-surfacer/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-surfacer/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && cp paraprobe_surfacer /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_surfacer \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-distancer/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-distancer/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && cp paraprobe_distancer /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_distancer \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-tessellator/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-tessellator/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && cp paraprobe_tessellator /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_tessellator \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-nanochem/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-nanochem/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && cp paraprobe_nanochem /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_nanochem \
-  && mkdir -p /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-intersector/build \
-  && cd /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-intersector/build \
-  && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=mpicxx .. \
-  && make -j4 \
-  && cp paraprobe_intersector /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_intersector \
-  && chmod +x /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe_* \
+  && sed -i 's|set(MYPROJECTPATH "<<YOURPATH>>/paraprobe-toolbox")|set(MYPROJECTPATH \"'"$PWD"'\/\")|g' code/PARAPROBE.Dependencies.cmake \
   && cd /home/atom_probe_tools/paraprobe-toolbox \
-  && rm -f PARAPROBE.Step*.sh \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-clusterer \
+  && chmod +x PARAPROBE.Step05.Build.Tools.sh \
+  && ./PARAPROBE.Step05.Build.Tools.sh \
+  && chmod +x PARAPROBE.Step06.Install.Tools.sh \
+  && ./PARAPROBE.Step06.Install.Tools.sh \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/boost \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/cgal \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/chrono \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/eigen \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/hdf5 \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/hornus2017 \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/lewiner2002 \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/mandatory/voroxx \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-utils/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-ranger/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-selector/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-surfacer/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-distancer/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-tessellator/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-spatstat/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-nanochem/build \
+  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-intersector/build \
   && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-crystalstructure \
   && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-miscellaneous \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/paraprobe-spatstat \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/code/thirdparty/ \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/teaching/example_analyses/aus_sydney_rielli_primig \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/teaching/example_analyses/aut_leoben_mendez_martin \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/teaching/example_analyses/ger_berlin_kuehbach_fairmat \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/teaching/example_data/aus_sydney_rielli_primig \
-  && rm -rf /home/atom_probe_tools/paraprobe-toolbox/teaching/example_data/aut_leoben_mendez_martin \
   && chown -R ${PUID}:${PGID} /home \
   && chown -R ${PUID}:${PGID} /usr/local/miniconda3
 
+# all rm -rf statements should only be used during container build when we do not like
+# to have a version which can be recompiled inside the container
 # as the entire C/C++ executables for all thirdparty dependencies are linked
-# statically the entire thirdparty/mandatory can be deleted
+# statically the entire thirdparty/mandatory is deleted during the container build
+# which  freezes the state of each paraprobe tool but has the disadvantage that the
+# tools can then not be recompiled from inside the container
 
 COPY 02-exec-cmd /config/custom-cont-init.d/02-exec-cmd
 
 ENV HOME=/home/atom_probe_tools
 WORKDIR $HOME
 
-# further optimization for the future could be to copy the content from conda bin and lib over like done in
-# https://gitlab.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/-/blob/develop/docker/nionswift/Dockerfile
-# but there might be more low level dependencies from h5web so this is currently not used
-
-# for running this container standalone e.g.
-# docker run -p 3000:8888 <<imagename>>
\ No newline at end of file
+# for running this container standalone e.g. docker run -p 3000:8888 <<imagename>>
diff --git a/docker/apmtools/FAIRmatNewLogo.png b/docker/apmtools/FAIRmatNewLogo.png
new file mode 100644
index 0000000000000000000000000000000000000000..aba8697486c07a914800f7519a978306e12d5637
Binary files /dev/null and b/docker/apmtools/FAIRmatNewLogo.png differ
diff --git a/docker/apmtools/FAIRmat_S.png b/docker/apmtools/FAIRmat_S.png
deleted file mode 100644
index 43c597e6f09d0850fd1b7c646a481d7c8f0ef3f4..0000000000000000000000000000000000000000
Binary files a/docker/apmtools/FAIRmat_S.png and /dev/null differ
diff --git a/docker/apmtools/NOMADOasisLogo.png b/docker/apmtools/NOMADOasisLogo.png
new file mode 100644
index 0000000000000000000000000000000000000000..b5f82fd462e34ef25e8e93ba6aa834a212d001dc
Binary files /dev/null and b/docker/apmtools/NOMADOasisLogo.png differ
diff --git a/tools.json b/tools.json
index f416bd9677e21e4bfac9de04a806f888242270ad..047db2d776b9d28230b4911d841ec41cc68298c1 100644
--- a/tools.json
+++ b/tools.json
@@ -134,7 +134,7 @@
     },
     "apmtools": {
         "short_description": "An example for analyzing atom probe data.",
-        "description": "Miscellaneous tools from the atom probe community:\nCurrently the Leoben APT_analyzer and the paraprobe-toolbox.",
+        "description": "Miscellaneous tools from the atom probe community:\nCurrently APTyzer, paraprobe-toolbox, and APAV.\nA JupyterLab instance will start which has a detailed Cheatsheet notebook for getting started.",
         "image": "gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/apmtools-webtop",
         "privileged": true,
         "icon": "jupyter_logo.svg",
@@ -148,7 +148,7 @@
     },
     "fiji": {
         "short_description": "ImageJ and Fiji for image processing",
-        "description": "ImageJ and Fiji with amongst others several electron-microscopy specific plug-ins",
+        "description": "ImageJ and Fiji with amongst others several electron-microscopy specific plug-ins.\nA JupyterLab instance will start which has a detailed Cheatsheet notebook for getting started.",
         "image": "gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/fiji-webtop",
         "privileged": true,
         "icon": "jupyter_logo.svg",
@@ -162,7 +162,7 @@
     },
     "frwr": {
         "short_description": "Inline electron holography by C. Koch",
-        "description": "FRWR3 in-line holography/focus series reconstruction code",
+        "description": "FRWR3 in-line holography/focus series reconstruction code.",
         "image": "gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/frwr-webtop",
         "privileged": true,
         "icon": "jupyter_logo.svg",
@@ -176,7 +176,7 @@
     },
     "abtem": {
         "short_description": "Electronic structure supported image simulation for transmission electron microscopy.",
-        "description": "VESTA, GPAW, and abTEM configured in one container for simulating images and diffraction patterns in transmission electron microscopy",
+        "description": "VESTA, GPAW, and abTEM configured in one container for simulating images and diffraction patterns in transmission electron microscopy.\nA JupyterLab instance will start which has a detailed Cheatsheet notebook for getting started.",
         "image": "gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-remote-tools-hub/abtem-webtop",
         "privileged": true,
         "icon": "jupyter_logo.svg",