diff --git a/doc/getting_started.rst b/doc/getting_started.rst
index 05e2d9f7874288941e35fb3568acd9dc3a8b0820..f90b9d60fc3e737bde51d8387620e5939f485d68 100644
--- a/doc/getting_started.rst
+++ b/doc/getting_started.rst
@@ -15,10 +15,10 @@ If the toolbox has been installed in your home directory previously, everything
 
 .. code:: bash
 
-    pip install --user .
+    pip install --user ".[maxwell]"
 
 Alternatively, use the -e flag for installation to install the package in development mode.
 
 .. code:: bash
 
-    pip install --user -e .
+    pip install --user -e ".[maxwell]"
diff --git a/setup.py b/setup.py
index 9076e9155e56da1c0d690e125316e83fbf8a7727..fc1c33f2427f25609399819aa365d2b1ac246714 100644
--- a/setup.py
+++ b/setup.py
@@ -8,6 +8,13 @@ with open('VERSION') as f:
     _version = _version.strip("\n")
 
 
+basic_analysis_reqs = ['numpy', 'scipy',]  # and is readily available in Karabo
+advanced_analysis_reqs = [
+    'pandas', 'imageio', 'xarray>=0.13.0', 'h5py', 'h5netcdf',]
+interactive_reqs = ['ipykernel', 'matplotlib', 'tqdm',]
+maxwell_reqs = ['joblib', 'extra_data', 'euxfel_bunch_pattern>=0.6']
+
+
 setup(name='toolbox_scs',
       version=_version,
       description="A collection of code for the SCS beamline",
@@ -20,9 +27,11 @@ setup(name='toolbox_scs',
       package_dir={'': 'src'},
       packages=find_packages('src'),
       package_data={},
-      install_requires=[
-          'xarray>=0.13.0', 'numpy', 'matplotlib',
-          'pandas', 'scipy', 'h5py', 'h5netcdf',
-          'extra_data', 'euxfel_bunch_pattern>=0.6',
-      ],
-      )
+      install_requires=basic_analysis_reqs,
+      extras_require={
+          'advanced': advanced_analysis_reqs,
+          'interactive': interactive_reqs,
+          'maxwell': advanced_analysis_reqs + interactive_reqs + maxwell_reqs,
+          'test': ['pytest']
+      }
+)
diff --git a/src/toolbox_scs/__init__.py b/src/toolbox_scs/__init__.py
index f1acd8952e8152f74d61597f7d86e179b079c846..a1d290a8129544c3d3868474064fb0c2eef6cd4f 100644
--- a/src/toolbox_scs/__init__.py
+++ b/src/toolbox_scs/__init__.py
@@ -1,39 +1,22 @@
-from .load import (load, concatenateRuns, get_array, run_by_path)
-from .constants import mnemonics
-from .mnemonics_machinery import mnemonics_for_run
-
-__all__ = (
-    # functions
-    "load",
-    "concatenateRuns",
-    "get_array",
-    "run_by_path",
-    "mnemonics_for_run",
-    # Classes
-    # Variables
-    "mnemonics",
-)
+from .constants import *
+from .detectors import *
 
+# Module name is the same as a child function, we use alias to avoid conflict
+import toolbox_scs.load as load_module
+from .load import *
 
-# ------------------------------------------------------------------------------
-# Clean namespace
-# clean_ns is a collection of undesired items in the namespace
-# ------------------------------------------------------------------------------
+from .misc import *
+from .mnemonics_machinery import *
+from .routines import *
 
-clean_ns = [
-    # filenames
-    'constants',
-    'mnemonics_machinery'
-    # folders
-    'misc',
-    'util',
-    'detectors',
-    'routines',
-    ]
-
-for name in dir():
-    if name in clean_ns:
-        del globals()[name]
+__all__ = (
+    # top-level modules
+    constants.__all__
+    + load_module.__all__
+    + mnemonics_machinery.__all__
 
-del globals()['clean_ns']
-del globals()['name']
+    # submodules
+    + detectors.__all__
+    + misc.__all__
+    + routines.__all__
+)
diff --git a/src/toolbox_scs/constants.py b/src/toolbox_scs/constants.py
index 28587b5e544d7dfd66adf0ca88d22d2c0e92f298..09784e727a6e1934cd13f2e3117b5402113c13ef 100644
--- a/src/toolbox_scs/constants.py
+++ b/src/toolbox_scs/constants.py
@@ -1,3 +1,8 @@
+__all__ = [
+    'mnemonics'
+]
+
+
 mnemonics = {
     # Machine
     "sase3": ({'source': 'SCS_RR_UTC/MDL/BUNCH_DECODER',
diff --git a/src/toolbox_scs/detectors/__init__.py b/src/toolbox_scs/detectors/__init__.py
index a34b0b9fb6dd0f3ae3b6a4b6868c615ecb5dcff9..da11c8f515d266f771e05d9e76a52ae87d47e51f 100644
--- a/src/toolbox_scs/detectors/__init__.py
+++ b/src/toolbox_scs/detectors/__init__.py
@@ -1,82 +1,21 @@
-from .xgm import (
-    get_xgm, calibrate_xgm)
-from .digitizers import (
-    get_peaks, get_tim_peaks, get_laser_peaks, get_digitizer_peaks,
-    check_peak_params)
-from .bam_detectors import get_bam
-from .pes import get_pes_tof, get_pes_params
-from .dssc_data import (
-    save_xarray, load_xarray, get_data_formatted, save_attributes_h5)
-from .dssc_misc import (
-    load_dssc_info, create_dssc_bins, quickmask_DSSC_ASIC,
-    get_xgm_formatted, load_mask)
-from .dssc_processing import (
-    process_dssc_data)
-from .dssc import (
-    DSSCBinner, DSSCFormatter)
-from .azimuthal_integrator import (
-    AzimuthalIntegrator, AzimuthalIntegratorDSSC)
+from .azimuthal_integrator import *
+from .bam_detectors import *
+from .digitizers import *
+from .dssc import *
+from .dssc_data import *
+from .dssc_misc import *
+from .dssc_processing import *
+from .pes import *
+from .xgm import *
 
 __all__ = (
-    # Functions
-    "get_xgm",
-    "calibrate_xgm",
-    "get_peaks",
-    "get_tim_peaks",
-    "get_laser_peaks",
-    "get_digitizer_peaks",
-    "check_peak_params",
-    "get_bam",
-    "get_pes_tof",
-    "get_pes_params",
-    "save_xarray",
-    "load_xarray",
-    "get_data_formatted",
-    "save_attributes_h5",
-    "load_dssc_info",
-    "create_dssc_bins",
-    "quickmask_DSSC_ASIC",
-    "get_xgm_formatted",
-    "load_mask",
-    "calc_xgm_frame_indices",
-    "process_dssc_data",
-    # Classes
-    "DSSCBinner",
-    "DSSCFormatter",
-    "AzimuthalIntegrator",
-    "AzimuthalIntegratorDSSC",
-    # Variables
+    azimuthal_integrator.__all__
+    + bam_detectors.__all__
+    + digitizers.__all__
+    + dssc.__all__
+    + dssc_data.__all__
+    + dssc_misc.__all__
+    + dssc_processing.__all__
+    + pes.__all__
+    + xgm.__all__
 )
-
-
-# -----------------------------------------------------------------------------
-# Clean namespace
-#     -> certain filenames we dont need in the namespace. Especially not those
-#     that are marked as private by using an underscore (_<filename>.py).
-# -----------------------------------------------------------------------------
-
-clean_ns = [
-    # filenames
-    'DSSC_bkp',
-    'DSSC1module',
-    'dssc',
-    'dssc_routines',
-    'dssc_processing',
-    'dssc_data',
-    'dssc_misc',
-    'dssc_plot',
-    'azimuthal_integrator',
-    'FastCCD',
-    'xgm',
-    'digitizers',
-    'bam_detectors',
-    'pes'
-    ]
-
-
-for name in dir():
-    if name in clean_ns:
-        del globals()[name]
-
-del globals()['clean_ns']
-del globals()['name']
diff --git a/src/toolbox_scs/detectors/azimuthal_integrator.py b/src/toolbox_scs/detectors/azimuthal_integrator.py
index d6326dfc77a83c8f7daea565b6d3ef21b4d919e4..235c9584faf86b4a355dcde726af3c951c8e9ab0 100644
--- a/src/toolbox_scs/detectors/azimuthal_integrator.py
+++ b/src/toolbox_scs/detectors/azimuthal_integrator.py
@@ -1,6 +1,11 @@
 import logging
 import numpy as np
 
+__all__ = [
+    'AzimuthalIntegrator',
+    'AzimuthalIntegratorDSSC'
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/bam_detectors.py b/src/toolbox_scs/detectors/bam_detectors.py
index 12d6ef1b2abaf1cf69df1a42efbb88fea9a94892..667d20afb4fa39b2626664d9ce7ecc6cada2096f 100644
--- a/src/toolbox_scs/detectors/bam_detectors.py
+++ b/src/toolbox_scs/detectors/bam_detectors.py
@@ -15,6 +15,9 @@ from ..misc.bunch_pattern_external import is_pulse_at
 from ..mnemonics_machinery import (mnemonics_to_process,
                                    mnemonics_for_run)
 
+__all__ = [
+    'get_bam',
+]
 
 log = logging.getLogger(__name__)
 
diff --git a/src/toolbox_scs/detectors/digitizers.py b/src/toolbox_scs/detectors/digitizers.py
index b67732336174509374ec5f1c2b9374c30968e0dc..339d17a90ec6448bdb095573e5af590adc0a73e6 100644
--- a/src/toolbox_scs/detectors/digitizers.py
+++ b/src/toolbox_scs/detectors/digitizers.py
@@ -18,6 +18,14 @@ from ..util.exceptions import ToolBoxValueError
 from ..mnemonics_machinery import (mnemonics_to_process,
                                    mnemonics_for_run)
 
+__all__ = [
+    'check_peak_params',
+    'get_digitizer_peaks',
+    'get_laser_peaks',
+    'get_peaks',
+    'get_tim_peaks',
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/dssc.py b/src/toolbox_scs/detectors/dssc.py
index aaa80bf7f4ff77451146a440e570ed9df4eba508..7aa93a9f4697e2506bb92c117014139ef87ba784 100644
--- a/src/toolbox_scs/detectors/dssc.py
+++ b/src/toolbox_scs/detectors/dssc.py
@@ -29,7 +29,10 @@ from .dssc_misc import (
 from .dssc_processing import (
         process_dssc_data, create_empty_dataset)
 
-__all__ = ["DSSCBinner", "DSSCFormatter"]
+__all__ = [
+    "DSSCBinner",
+    "DSSCFormatter"]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/dssc_data.py b/src/toolbox_scs/detectors/dssc_data.py
index 078117727a8daabe88c6be50c9f3f92725801adc..94b23366c08097c42d4f2c98423289e12325ea6f 100644
--- a/src/toolbox_scs/detectors/dssc_data.py
+++ b/src/toolbox_scs/detectors/dssc_data.py
@@ -6,6 +6,13 @@ import xarray as xr
 
 from ..util.exceptions import ToolBoxFileError
 
+__all__ = [
+    'get_data_formatted',
+    'load_xarray',
+    'save_attributes_h5',
+    'save_xarray',
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/dssc_misc.py b/src/toolbox_scs/detectors/dssc_misc.py
index 96f5254d4e1c4af936f2a87da42bea19573441e0..db89aa76db27e22545ab23662a25ee2ec50ec483 100644
--- a/src/toolbox_scs/detectors/dssc_misc.py
+++ b/src/toolbox_scs/detectors/dssc_misc.py
@@ -14,6 +14,14 @@ import extra_data as ed
 from .xgm import get_xgm
 from .digitizers import get_tim_peaks
 
+__all__ = [
+    'create_dssc_bins',
+    'get_xgm_formatted',
+    'load_dssc_info',
+    'load_mask',
+    'quickmask_DSSC_ASIC',
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/dssc_processing.py b/src/toolbox_scs/detectors/dssc_processing.py
index 2858308f6da108605b4d8950c3b0b317ff95d71c..a95607db058883662eb332041f72083fc374b210 100644
--- a/src/toolbox_scs/detectors/dssc_processing.py
+++ b/src/toolbox_scs/detectors/dssc_processing.py
@@ -15,6 +15,10 @@ import extra_data as ed
 from ..mnemonics_machinery import mnemonics_for_run
 from .dssc_data import save_xarray
 
+__all__ = [
+    'process_dssc_data'
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/fccd.py b/src/toolbox_scs/detectors/fccd.py
index 0396df5549d8d3c4c476d351fe8627a0d1c9d8d6..f0cb5de04f8f5c3846ebe4331ac3a05a4d19abee 100644
--- a/src/toolbox_scs/detectors/fccd.py
+++ b/src/toolbox_scs/detectors/fccd.py
@@ -1,6 +1,5 @@
 from joblib import Parallel, delayed, parallel_backend
 from time import strftime
-import tempfile
 import shutil
 from tqdm.auto import tqdm
 import os
@@ -17,11 +16,11 @@ import h5py
 from glob import glob
 from imageio import imread
 
-import ToolBox as tb
 from ..constants import mnemonics as _mnemonics
 from .azimuthal_integrator import AzimuthalIntegrator
 from ..misc.laser_utils import positionToDelay
 
+
 class FastCCD:
     
     def __init__(self, proposal, distance=1, raw=False):
diff --git a/src/toolbox_scs/detectors/pes.py b/src/toolbox_scs/detectors/pes.py
index 49d73f7d9935659e5aa5cf04723fb82e6e96893c..cb36e497dfd4c555ce0c72500660b30e46bc3193 100644
--- a/src/toolbox_scs/detectors/pes.py
+++ b/src/toolbox_scs/detectors/pes.py
@@ -16,6 +16,12 @@ from ..mnemonics_machinery import (mnemonics_to_process,
                                    mnemonics_for_run)
 
 
+__all__ = [
+    'get_pes_params',
+    'get_pes_tof',
+]
+
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/detectors/xgm.py b/src/toolbox_scs/detectors/xgm.py
index cdb84dc20ccf05410d18078634fb5f3acccc297f..944dcc501130ca9cdc7cf340982c11c3bc8f23ee 100644
--- a/src/toolbox_scs/detectors/xgm.py
+++ b/src/toolbox_scs/detectors/xgm.py
@@ -16,6 +16,11 @@ from ..misc.bunch_pattern_external import is_sase_1, is_sase_3
 from ..mnemonics_machinery import (mnemonics_to_process,
                                    mnemonics_for_run)
 
+__all__ = [
+    'calibrate_xgm',
+    'get_xgm',
+]
+
 
 log = logging.getLogger(__name__)
 
diff --git a/src/toolbox_scs/load.py b/src/toolbox_scs/load.py
index 48360c79ec152c8221a2d705949d13d20743e3be..d51b5b1933d2f17b22e5d5080992e2ab15846677 100644
--- a/src/toolbox_scs/load.py
+++ b/src/toolbox_scs/load.py
@@ -21,6 +21,13 @@ from .mnemonics_machinery import mnemonics_for_run
 from .util.exceptions import ToolBoxValueError
 import toolbox_scs.detectors as tbdet
 
+__all__ = [
+    'concatenateRuns',
+    'get_array',
+    'load',
+    'run_by_path',
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/misc/__init__.py b/src/toolbox_scs/misc/__init__.py
index 0f4edde6c50e746b723ee7072d80998414d0534f..3ff302d5efa9d33103e834353fd4f36a0eff5dcd 100644
--- a/src/toolbox_scs/misc/__init__.py
+++ b/src/toolbox_scs/misc/__init__.py
@@ -1,25 +1,9 @@
-from .bunch_pattern import (extractBunchPattern, pulsePatternInfo,
-    repRate)
-from .bunch_pattern_external import (is_sase_3, is_sase_1,
-    is_ppl, is_pulse_at)
-from .laser_utils import positionToDelay, degToRelPower
-
+from .bunch_pattern import *
+from .bunch_pattern_external import *
+from .laser_utils import *
 
 __all__ = (
-    # Functions
-    "extractBunchPattern",
-    "pulsePatternInfo",
-    "repRate",
-    "sortBAMdata",
-    "is_sase_3",
-    "is_sase_1",
-    "is_ppl",
-    "is_pulse_at",
-    "get_index_ppl",
-    "get_index_sase1",
-    "get_index_sase3",
-    "positionToDelay",
-    "degToRelPower",
-    # Classes
-    # Variables
+    bunch_pattern.__all__
+    + bunch_pattern_external.__all__
+    + laser_utils.__all__
 )
diff --git a/src/toolbox_scs/misc/bunch_pattern.py b/src/toolbox_scs/misc/bunch_pattern.py
index 3f5939b2a9c11e1b237b5b0b8b9ca3e8821ce4e5..852f9ed71adce12faaf0365f5722d18922fa295f 100644
--- a/src/toolbox_scs/misc/bunch_pattern.py
+++ b/src/toolbox_scs/misc/bunch_pattern.py
@@ -16,6 +16,12 @@ from extra_data import RunDirectory
 # import and hide variable, such that it does not alter namespace.
 from ..constants import mnemonics as _mnemonics_bp
 
+__all__ = [
+    'extractBunchPattern',
+    'pulsePatternInfo',
+    'repRate'
+]
+
 
 def extractBunchPattern(bp_table=None, key='sase3', runDir=None):
     ''' generate the bunch pattern and number of pulses of a source directly from the
diff --git a/src/toolbox_scs/misc/bunch_pattern_external.py b/src/toolbox_scs/misc/bunch_pattern_external.py
index 993b58414ee475f61528e1bf4af0874c624b90a0..70d6afce8025f0d2ff271091cb23bb0be1f0e417 100644
--- a/src/toolbox_scs/misc/bunch_pattern_external.py
+++ b/src/toolbox_scs/misc/bunch_pattern_external.py
@@ -11,6 +11,13 @@ import logging
 
 import euxfel_bunch_pattern as ebp
 
+__all__ = [
+    'is_sase_3',
+    'is_sase_1',
+    'is_ppl',
+    'is_pulse_at',
+]
+
 PPL_SCS = ebp.LASER_SEED6
 log = logging.getLogger(__name__)
 
diff --git a/src/toolbox_scs/misc/laser_utils.py b/src/toolbox_scs/misc/laser_utils.py
index 55e44a39839904268223b15df6cb537af77727e9..b284999e94af2921cdd4313f5be08bd996a335d5 100644
--- a/src/toolbox_scs/misc/laser_utils.py
+++ b/src/toolbox_scs/misc/laser_utils.py
@@ -1,3 +1,9 @@
+__all__ = [
+    'degToRelPower',
+    'positionToDelay',
+]
+
+
 def positionToDelay(pos, origin=0, invert = False, reflections=1):
     ''' converts a motor position in mm into optical delay in picosecond
         Inputs:
diff --git a/src/toolbox_scs/mnemonics_machinery.py b/src/toolbox_scs/mnemonics_machinery.py
index f09e14bc32b8de35bdb916b1151d069e1735d677..a3aa8f03d230542ed426c0ca985d43619e65f5c9 100644
--- a/src/toolbox_scs/mnemonics_machinery.py
+++ b/src/toolbox_scs/mnemonics_machinery.py
@@ -10,6 +10,10 @@ import logging
 
 from .constants import mnemonics as _mnemonics
 
+__all__ = [
+    'mnemonics_for_run'
+]
+
 log = logging.getLogger(__name__)
 
 
diff --git a/src/toolbox_scs/routines/XAS.py b/src/toolbox_scs/routines/XAS.py
index 1c9ca1758f2f6f15e30b75ba21224007127c30db..3bf52a58037535ca166795abf956d5e514a20de8 100644
--- a/src/toolbox_scs/routines/XAS.py
+++ b/src/toolbox_scs/routines/XAS.py
@@ -14,6 +14,11 @@ import matplotlib.gridspec as gridspec
 import matplotlib.pyplot as plt
 import re
 
+__all__ = [
+    'xas',
+    'xasxmcd',
+]
+
 
 def absorption(T, Io, fluorescence=False):
     """ Compute the absorption A = -ln(T/Io) (or A = T/Io
diff --git a/src/toolbox_scs/routines/__init__.py b/src/toolbox_scs/routines/__init__.py
index de3ef3887b34da7e763a4a8aa556f8a131193da1..d8fbb2647fd36ecd3b9381dd554fabed3f3cd180 100644
--- a/src/toolbox_scs/routines/__init__.py
+++ b/src/toolbox_scs/routines/__init__.py
@@ -1,29 +1,10 @@
-from .XAS import (
-    xas, xasxmcd)
-from .knife_edge import knife_edge
+from .XAS import *
+
+# Module name is the same as a child function, we use alias to avoid conflict
+import toolbox_scs.routines.knife_edge as knife_edge_module
+from .knife_edge import *
 
 __all__ = (
-    # Functions
-    "xas",
-    "xasxmcd",
-    "knife_edge"
+    knife_edge_module.__all__
+    + XAS.__all__
 )
-
-# -----------------------------------------------------------------------------
-# Clean namespace
-#     -> certain filenames we dont need in the namespace. Especially not those
-#     that are marked as private by using an underscore (_<filename>.py).
-# -----------------------------------------------------------------------------
-
-clean_ns = [
-    # filenames
-    'XAS',
-    ]
-
-
-for name in dir():
-    if name in clean_ns:
-        del globals()[name]
-
-del globals()['clean_ns']
-del globals()['name']
diff --git a/src/toolbox_scs/routines/knife_edge.py b/src/toolbox_scs/routines/knife_edge.py
index 191213dd0b64eb96d08d9ebdaa45815a4d7ab020..fccc153f0ede2287051c06afd051677d8bf5d781 100644
--- a/src/toolbox_scs/routines/knife_edge.py
+++ b/src/toolbox_scs/routines/knife_edge.py
@@ -11,6 +11,10 @@ from scipy.special import erfc
 from scipy.optimize import curve_fit
 import bisect
 
+__all__ = [
+    'knife_edge'
+]
+
 
 def knife_edge(ds, axisKey='scannerX',
                signalKey='FastADC4peaks',