diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d40c31e06fc9f5a87e6494477fb20bbd38774ebd..70d94f562bc914d3edd8ac04fd1eca313c8e5975 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -40,9 +40,14 @@ simple_test:
     # dev_master might have the same version numbers which will prevent
     # pip from upgrading them.
     - pip uninstall -y ScopeSIM
-    - pip install --upgrade git+https://github.com/AstarVienna/ScopeSim.git@dev_master
+    - pip   install    ScopeSIM==0.5.4
+    #- pip install --upgrade git+https://github.com/AstarVienna/ScopeSim.git@master
     - pip uninstall -y ScopeSIM_Templates
-    - pip install --upgrade git+https://github.com/AstarVienna/ScopeSim_Templates.git@dev_master
+    - pip   install    ScopeSIM_Templates==0.4.2
+    #- pip install --upgrade git+https://github.com/AstarVienna/ScopeSim_Templates.git@dev_master
+    - pip uninstall -y irdb
+    #- pip install --upgrade git+https://github.com/AstarVienna/irdb.git@master
+    - python -c 'import scopesim; scopesim.download_packages(["Armazones", "ELT", "MICADO", "LFOA", "MAORY"])'
   script:
     - PYTHONPATH=src bash conda-recipe/run_test.sh
 
diff --git a/.gitmodules b/.gitmodules
index 80b24cdb60900ca4689fc32d8da8e909c4be6259..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +0,0 @@
-[submodule "irdb"]
-	path = irdb
-	url = https://github.com/AstarVienna/irdb.git
diff --git a/build.sh b/build.sh
index 40efe773d6e5f6e599277e691d85c4124d8ee079..26ae4976371ab06f97a0f42147be606565208c6a 100755
--- a/build.sh
+++ b/build.sh
@@ -26,13 +26,6 @@ while [[ $# -gt 0 ]]; do
   esac
 done
 
-# TODO: Ensure conda environment is okay.
-# conda install openjdk
-
-#if ! command -v pajv; then
-#    npm install -g pajv
-#fi
-
 # Ensure that the MicadoWISE code in the current directory is used.
 export PYTHONPATH="${PYTHONPATH-$(pwd)/src}"
 
@@ -61,6 +54,13 @@ if [ "${DELETE}" = "YES" ] ; then
     rm -f src/micado/templates/*.tsf
 fi
 
+# download the irdb packages, line below downloads zip files
+python -c 'import scopesim; scopesim.download_packages(["Armazones", "ELT", "MICADO", "LFOA", "MAORY"])'
+# TODO git checkout the irdb repo and point to it
+#rm -Rf inst_pkgs
+#git clone https://github.com/AstarVienna/irdb.git
+#ln -s irdb inst_pkgs
+
 python src/micado/toolbox/yaml_from_did.py
 python src/micado/toolbox/python_from_vodml.py
 black src/micado
@@ -116,12 +116,5 @@ pushd docs/latex || exit
 SOURCE_DATE_EPOCH=32373732 tectonic MicadoWISE_DataModel.tex
 popd || exit
 
-#pushd src/datainterface || exit
-#pajv -s dicschema.hierarchical.json -d "yaml/*.hierarch.*" -m metaschema.json;
-#pajv -s dicschema.flat.json -d "yaml/*.flat.*" -m metaschema.json;
-#popd || exit
-
-#pushd docs || exit
-#make html
-#popd || exit
-
+# This directory has been created by the call scopesim.download_packages()
+rm -Rf inst_pkgs irdb
diff --git a/conda-recipe/build.sh b/conda-recipe/build.sh
index c1cfa5bfff7f3df0f29886817d46b65dccb7ceb7..9261a440ce8057b117feeef78276e798ec640b61 100644
--- a/conda-recipe/build.sh
+++ b/conda-recipe/build.sh
@@ -7,10 +7,5 @@
 mkdir -p ${SP_DIR}
 cp -r src/* ${SP_DIR}
 
-# TODO: This copies the entire IRDB to the SP_DIR, perhaps that is not the
-# best location.
-# Copy the IRDB.
-cp -r irdb ${SP_DIR}
-
 # Install additional files (binaries and environment (de)activation).
 cp -r prefix/* "${PREFIX}"
diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml
index 7f37f1bc9f06514e2eb0a183ee740733fc66facd..d4c03831d83bc736a4f4ee39a5abb67ca4646f70 100644
--- a/conda-recipe/meta.yaml
+++ b/conda-recipe/meta.yaml
@@ -13,19 +13,21 @@ source:
     folder: notebooks
   - path: prefix
     folder: prefix
-  - path: ../irdb
-    folder: irdb
+  # TODO what does this? remove ??
+  #- path: ../irdb
+  #  folder: irdb
 
 requirements:
   run:
-    - python
+    - python ==3.10
     - numpy
-    - python-dateutil
+    # TODO remove? not used ?!
+    #- python-dateutil
     - matplotlib
     - astropy
     # To propagate changes in the digital design:
     - lxml
-    - nodejs
+    # - nodejs TODO not used ?
     # Pin openjdk version because this makes the figure generation
     # consistent. However, it could be due to harfbuzz and not openjdk itself.
     # Known to be compatible with current figures:
@@ -35,6 +37,7 @@ requirements:
     # However, the new figures are perhaps nicer, so maybe switch at some point.
     # Note that it is also necessary to apt-get install emacs to get the right
     # figures, see install_run_as_user.sh
+    # TODO remove ?
     - openjdk ==11.0.9.1
     # For generation of documentation:
     - sphinx
@@ -46,14 +49,13 @@ requirements:
     - jupytext ==1.13.1
     # For PostgreSQL backend:
     - psycopg2
-    # For (disabled) sqlalchemy backend:
+    # TODO remove ?
     - sqlalchemy
-    # For scopesim:
-    - synphot
+    # - synphot RM included by scopesim
     - photutils
     - pyyaml
-    - beautifulsoup4
-    - soupsieve
+    #- beautifulsoup4
+    #- soupsieve
     - curl
     # For cpl:
     - make
@@ -69,6 +71,7 @@ requirements:
     - cppcheck
     - binutils # for ar
     - cpl
+    # TODO replace python-cpl with https://www.eso.org/sci/software/pycpl/, when version 1.0 is out ?
     - python-cpl
     # MicadoWISE does not actually depend on wcslib, but micadopipeline
     # does, but that needs 7.3, which it does not have as a dependencies.
@@ -79,12 +82,12 @@ requirements:
     - pytest
     - coverage
     - mock
-    - flake8
-    - flake8-docstrings
-    - black ==22.3.0
+    #- flake8
+    #- flake8-docstrings
+    - black
     # For development, e.g. in container.
-    - ripgrep
-    - vim
+    #- ripgrep
+    #- vim
     # tmux 3.3 causes problems with debian 10, see
     # https://github.com/conda-forge/tmux-feedstock/issues/29
     #- tmux ==3.2a
diff --git a/conda-recipe/run_test.sh b/conda-recipe/run_test.sh
index 584404239ff806b1e51b23fe8230f492f4e5f4cc..113e979203ceb0b1ec5336d144070b2646a21903 100755
--- a/conda-recipe/run_test.sh
+++ b/conda-recipe/run_test.sh
@@ -45,7 +45,6 @@ SRC_DIR="${SRC_DIR-$(pwd)}"
 coverage erase
 
 
-
 ##################################
 # Install optional dependencies. #
 ##################################
@@ -54,17 +53,26 @@ coverage erase
 # packages.
 # TODO: Ensure MicadoWISE works without these as well.
 python -c "import skycalc_ipy" || pip install skycalc_ipy
-# ScopeSIM 0.2.0 and 0.4.0 cannot simulate a large cluster.
-# However, dev_master should work.
-# TODO: Replace dev_master with actual release when it exists.
-# python -c "import scopesim" || pip install "ScopeSIM==0.1.4"
-python -c "import scopesim" || pip install git+https://github.com/AstarVienna/ScopeSim.git@dev_master
+
+# ScopeSIM should have a conda package
+#python -c "import scopesim" || pip install git+https://github.com/AstarVienna/ScopeSim.git@master
+python -c "import scopesim" || pip install "ScopeSIM==0.5.4"
 
 # ScopeSim_Templates fetches data from the internet, which does not work
 # when using conda-build.
-python -c "import scopesim_templates" || pip install git+https://github.com/AstarVienna/ScopeSim_Templates.git@dev_micado
+#python -c "import scopesim_templates" || pip install git+https://github.com/AstarVienna/ScopeSim_Templates.git@dev_master
+python -c "import scopesim_templates" || pip install "ScopeSIM_Templates==0.4.2"
 # TODO: Fetch ScopeSim data package.
 
+# IRDB
+python -c 'import scopesim; scopesim.download_packages(["Armazones", "ELT", "MICADO", "LFOA", "MAORY"])'
+# or install via pip install ?
+#pip install git+https://github.com/AstarVienna/irdb.git@master
+# or use git clone ?
+#rm -Rf inst_pkgs
+#git clone https://github.com/AstarVienna/irdb.git
+#ln -s irdb inst_pkgs
+
 
 if [[ -n ${MICADO_INTEGRATION_TESTS:+x} ]]; then
     echo "MICADO_INTEGRATION_TESTS set, installing optional dependencies."
@@ -116,7 +124,6 @@ if [[ -n ${MICADO_INTEGRATION_TESTS:+x} ]]; then
 fi
 
 
-
 ####################
 # Start the tests. #
 ####################
@@ -126,6 +133,7 @@ fi
 echo "Running functional tests."
 coverage run --branch --source="${MICADO_DIR}" -m pytest \
     "${SRC_DIR}/src/micado/test/functional"
+#python -m pytest "${SRC_DIR}/src/micado/test/functional"
 
 # Do integration tests, in particular database and CPL tests.
 # These tests are not required to build the package, only in CI.
@@ -160,7 +168,6 @@ coverage run --branch --append --source="${MICADO_DIR}" "${SRC_DIR}"/notebooks/R
 coverage report -m
 
 
-
 ###############
 # Check Style #
 ###############
@@ -186,4 +193,8 @@ black --check "${SRC_DIR}/src/micado"
 # TODO: Re-enable sourcery for CI only.
 # sourcery refactor --check "${SRC_DIR}/src/micado"
 
+# This directory has been created by the call scopesim.download_packages()
+rm -Rf inst_pkgs irdb
+
+
 } 2>&1
diff --git a/docs/source/conf.py b/docs/source/conf.py
index debda1ea09f9755237ce3abc81daff51b6df1f43..429594398ef1555d8151c8db8bba26332dedc86a 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -19,14 +19,14 @@
 
 # -- Project information -----------------------------------------------------
 
-project = 'MicadoWISE'
-copyright = '2019, OmegaCEN'
-author = 'Hugo Buddelmeijer'
+project = "MicadoWISE"
+copyright = "2019, OmegaCEN"
+author = "Hugo Buddelmeijer"
 
 # The short X.Y version
-version = '0.1'
+version = "0.1"
 # The full version, including alpha/beta/rc tags
-release = '0.1'
+release = "0.1"
 
 
 # -- General configuration ---------------------------------------------------
@@ -47,10 +47,10 @@ templates_path = []
 # You can specify multiple suffix as a list of string:
 #
 # source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -82,7 +82,7 @@ html_context = {
     "gitlab_user": "micado",
     "gitlab_repo": "micadowise",
     "gitlab_version": "master",
-    "conf_py_path": "/docs/source/"
+    "conf_py_path": "/docs/source/",
 }
 
 # Theme options are theme-specific and customize the look and feel of a theme
@@ -90,11 +90,11 @@ html_context = {
 # documentation.
 #
 html_theme_options = {
-    'style_external_links': True,
-    'style_nav_header_background': '#009cef'
+    "style_external_links": True,
+    "style_nav_header_background": "#009cef",
 }
 
-html_logo = 'images/omegacen-icon.svg'
+html_logo = "images/omegacen-icon.svg"
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
@@ -115,7 +115,7 @@ html_static_path = []
 # -- Options for HTMLHelp output ---------------------------------------------
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'MicadoWISEdoc'
+htmlhelp_basename = "MicadoWISEdoc"
 
 
 # -- Options for LaTeX output ------------------------------------------------
@@ -124,15 +124,12 @@ latex_elements = {
     # The paper size ('letterpaper' or 'a4paper').
     #
     # 'papersize': 'letterpaper',
-
     # The font size ('10pt', '11pt' or '12pt').
     #
     # 'pointsize': '10pt',
-
     # Additional stuff for the LaTeX preamble.
     #
     # 'preamble': '',
-
     # Latex figure (float) alignment
     #
     # 'figure_align': 'htbp',
@@ -142,8 +139,7 @@ latex_elements = {
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-    (master_doc, 'MicadoWISE.tex', 'MicadoWISE Documentation',
-     author, 'manual'),
+    (master_doc, "MicadoWISE.tex", "MicadoWISE Documentation", author, "manual"),
 ]
 
 
@@ -151,10 +147,7 @@ latex_documents = [
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
-man_pages = [
-    (master_doc, 'MicadoWISE', 'MicadoWISE Documentation',
-     [author], 1)
-]
+man_pages = [(master_doc, "MicadoWISE", "MicadoWISE Documentation", [author], 1)]
 
 
 # -- Options for Texinfo output ----------------------------------------------
@@ -163,9 +156,15 @@ man_pages = [
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-    (master_doc, 'conda-wise', 'conda-wise Documentation',
-     author, 'conda-wise', 'One line description of project.',
-     'Miscellaneous'),
+    (
+        master_doc,
+        "conda-wise",
+        "conda-wise Documentation",
+        author,
+        "conda-wise",
+        "One line description of project.",
+        "Miscellaneous",
+    ),
 ]
 
 
@@ -184,7 +183,7 @@ epub_title = project
 # epub_uid = ''
 
 # A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
+epub_exclude_files = ["search.html"]
 
 
 # -- Extension configuration -------------------------------------------------
diff --git a/irdb b/irdb
deleted file mode 160000
index 3464429e2275bf595d433673fc9c7c7050b3ec0e..0000000000000000000000000000000000000000
--- a/irdb
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 3464429e2275bf595d433673fc9c7c7050b3ec0e
diff --git a/micadowise.yml b/micadowise.yml
index e29552e348aa0bc85f777786045b8abe7f2d0ef5..2b2e500929470c3c4c69e967415fbed1b1a238e9 100644
--- a/micadowise.yml
+++ b/micadowise.yml
@@ -18,9 +18,13 @@ dependencies:
     - pip
     - pip:
         - skycalc_ipy
+        - "ScopeSim==0.5.3"
+        - "scopesim_templates==0.4.2"
         # ScopeSIM 0.2.0 breaks simulating a cluster for large detectors.
         # - ScopeSim==0.1.4
         # dev_master should work again
-        - git+https://github.com/AstarVienna/ScopeSim.git@dev_master
+        #- git+https://github.com/AstarVienna/ScopeSim.git@master
         # - ScopeSim_Templates
-        - git+https://github.com/AstarVienna/ScopeSim_Templates.git@dev_master
+        #- git+https://github.com/AstarVienna/ScopeSim_Templates.git@dev_master
+        # - IRDB
+        #- git+https://github.com/AstarVienna/irdb.git@master
diff --git a/reflex/micado_si_wkf.py b/reflex/micado_si_wkf.py
index b3f83b43c9deb458057a9223aebd44b41d4f2b54..badb0a997a8ec095ee5f35cfccdaf10c38b6d28e 100644
--- a/reflex/micado_si_wkf.py
+++ b/reflex/micado_si_wkf.py
@@ -16,9 +16,9 @@ raw = (
 
 
 def is_raw_dark(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "DARK"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "DARK"
 
-raw_dark_class = ClassificationRule("DARK_RAW", is_raw_dark)
+raw_dark_class = ClassificationRule("I_DARK_RAW", is_raw_dark)
 
 raw_dark = (
     data_source()
@@ -35,7 +35,7 @@ raw_dark = (
 def is_cat_photomref(f):
     return f["pro.catg"] == "CAT_PHOTOMREF"
 
-cat_photomref_class = ClassificationRule("REF_PHOTOM_CAT", is_cat_photomref)
+cat_photomref_class = ClassificationRule("REF_I_PHOTOM_CAT", is_cat_photomref)
 
 cat_photomref = (
     data_source()
@@ -48,9 +48,9 @@ cat_photomref = (
 
 
 def is_raw_opt_flat(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "FLAT"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "FLAT,LAMP"
 
-raw_opt_flat_class = ClassificationRule("FLAT_RAW", is_raw_opt_flat)
+raw_opt_flat_class = ClassificationRule("I_FLAT_RAW", is_raw_opt_flat)
 
 raw_opt_flat = (
     data_source()
@@ -60,9 +60,9 @@ raw_opt_flat = (
 
 
 def is_raw_opt_nonlin(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "NONLIN"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "NONLIN,LAMP"
 
-raw_opt_nonlin_class = ClassificationRule("NONLIN_RAW", is_raw_opt_nonlin)
+raw_opt_nonlin_class = ClassificationRule("I_NONLIN_RAW", is_raw_opt_nonlin)
 
 raw_opt_nonlin = (
     data_source()
@@ -72,11 +72,10 @@ raw_opt_nonlin = (
 
 
 
-
 def is_cat_distortionref_astromref(f):
     return f["pro.catg"] == "CAT_DISTORTIONREF_ASTROMREF"
 
-cat_distortionref_astromref_class = ClassificationRule("REF_ASTROM_CAT", is_cat_distortionref_astromref)
+cat_distortionref_astromref_class = ClassificationRule("REF_I_ASTROM_CAT", is_cat_distortionref_astromref)
 
 cat_distortionref_astromref = (
     data_source()
@@ -88,7 +87,7 @@ cat_distortionref_astromref = (
 def is_cat_distortionref_wamref(f):
     return f["pro.catg"] == "CAT_DISTORTIONREF_WAMREF"
 
-cat_distortionref_wamref_class = ClassificationRule("REF_WAM_CAT", is_cat_distortionref_wamref)
+cat_distortionref_wamref_class = ClassificationRule("REF_I_WAM_CAT", is_cat_distortionref_wamref)
 
 cat_distortionref_wamref = (
     data_source()
@@ -102,9 +101,9 @@ cat_distortionref_wamref = (
 
 
 def is_raw_opt_sky_astromfield(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "ASTROM"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "STD,ASTROMETRY"
 
-raw_opt_sky_astromfield_class = ClassificationRule("ASTROMFIELD_RAW", is_raw_opt_sky_astromfield)
+raw_opt_sky_astromfield_class = ClassificationRule("I_ASTROMFIELD_RAW", is_raw_opt_sky_astromfield)
 
 raw_opt_sky_astromfield = (
     data_source()
@@ -114,9 +113,9 @@ raw_opt_sky_astromfield = (
 
 
 def is_raw_opt_sky_bkgfield(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "BCKGRND"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,AI" and f["dpr.type"] == "OBJECT,BCKGRND"
 
-raw_opt_sky_bkgfield_class = ClassificationRule("BKGFIELD_RAW", is_raw_opt_sky_bkgfield)
+raw_opt_sky_bkgfield_class = ClassificationRule("I_BKGFIELD_RAW", is_raw_opt_sky_bkgfield)
 
 raw_opt_sky_bkgfield = (
     data_source()
@@ -126,9 +125,9 @@ raw_opt_sky_bkgfield = (
 
 
 def is_raw_opt_wamcam_cam(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "CAM"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,AI" and f["dpr.type"] == "PINHOLE,CAM"
 
-raw_opt_wamcam_cam_class = ClassificationRule("CAM_RAW", is_raw_opt_wamcam_cam)
+raw_opt_wamcam_cam_class = ClassificationRule("I_CAM_RAW", is_raw_opt_wamcam_cam)
 
 raw_opt_wamcam_cam = (
     data_source()
@@ -138,9 +137,9 @@ raw_opt_wamcam_cam = (
 
 
 def is_raw_opt_sky_illum(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "ILLUM"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "STD,ILLUM"
 
-raw_opt_sky_illum_class = ClassificationRule("ILLUM_RAW", is_raw_opt_sky_illum)
+raw_opt_sky_illum_class = ClassificationRule("I_ILLUM_RAW", is_raw_opt_sky_illum)
 
 raw_opt_sky_illum = (
     data_source()
@@ -150,9 +149,9 @@ raw_opt_sky_illum = (
 
 
 def is_raw_opt_sky_stdfield(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "PHOTOM"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "STD,PHOTOM"
 
-raw_opt_sky_stdfield_class = ClassificationRule("STDFIELD_RAW", is_raw_opt_sky_stdfield)
+raw_opt_sky_stdfield_class = ClassificationRule("I_STDFIELD_RAW", is_raw_opt_sky_stdfield)
 
 raw_opt_sky_stdfield = (
     data_source()
@@ -162,9 +161,9 @@ raw_opt_sky_stdfield = (
 
 
 def is_raw_opt_wamcam_wam(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "WAM"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE,AI" and f["dpr.type"] == "PINHOLE,WAM"
 
-raw_opt_wamcam_wam_class = ClassificationRule("WAM_RAW", is_raw_opt_wamcam_wam)
+raw_opt_wamcam_wam_class = ClassificationRule("I_WAM_RAW", is_raw_opt_wamcam_wam)
 
 raw_opt_wamcam_wam = (
     data_source()
@@ -174,13 +173,10 @@ raw_opt_wamcam_wam = (
 
 
 
-
-
-
 def is_raw_opt_sky_skysiai_science(f):
-    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "OBJECT"
+    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "IMAGE,SI" and f["dpr.type"] == "OBJECT,SKY"
 
-raw_opt_sky_skysiai_science_class = ClassificationRule("SCIENCE_RAW", is_raw_opt_sky_skysiai_science)
+raw_opt_sky_skysiai_science_class = ClassificationRule("I_SCI_RAW", is_raw_opt_sky_skysiai_science)
 
 raw_opt_sky_skysiai_science = (
     data_source()
@@ -190,9 +186,9 @@ raw_opt_sky_skysiai_science = (
 
 
 def is_raw_opt_sky_skysiai_scienceai(f):
-    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "OBJECTAI"
+    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "IMAGE,AI" and f["dpr.type"] == "OBJECT,SKY"
 
-raw_opt_sky_skysiai_scienceai_class = ClassificationRule("SCIENCEAI_RAW", is_raw_opt_sky_skysiai_scienceai)
+raw_opt_sky_skysiai_scienceai_class = ClassificationRule("I_SCI_AI_RAW", is_raw_opt_sky_skysiai_scienceai)
 
 raw_opt_sky_skysiai_scienceai = (
     data_source()
@@ -210,14 +206,10 @@ raw_opt_sky_skysiai_scienceai = (
 
 
 
-
-
-
-
 def is_raw_opt_sky_skyhci_coro_corobackground(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "HCIBG"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "CORONOGRAPHY" and f["dpr.type"] == "BACKGROUND"
 
-raw_opt_sky_skyhci_coro_corobackground_class = ClassificationRule("COROBACKGROUND_RAW", is_raw_opt_sky_skyhci_coro_corobackground)
+raw_opt_sky_skyhci_coro_corobackground_class = ClassificationRule("I_CORO_BGD_RAW", is_raw_opt_sky_skyhci_coro_corobackground)
 
 raw_opt_sky_skyhci_coro_corobackground = (
     data_source()
@@ -227,9 +219,9 @@ raw_opt_sky_skyhci_coro_corobackground = (
 
 
 def is_raw_opt_sky_skyhci_coro_corooffset(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "HCIOFF"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "CORONOGRAPHY" and f["dpr.type"] == "STAR"
 
-raw_opt_sky_skyhci_coro_corooffset_class = ClassificationRule("COROOFFSET_RAW", is_raw_opt_sky_skyhci_coro_corooffset)
+raw_opt_sky_skyhci_coro_corooffset_class = ClassificationRule("I_CORO_OFFSET_RAW", is_raw_opt_sky_skyhci_coro_corooffset)
 
 raw_opt_sky_skyhci_coro_corooffset = (
     data_source()
@@ -239,9 +231,9 @@ raw_opt_sky_skyhci_coro_corooffset = (
 
 
 def is_raw_opt_sky_skyhci_coro_sciencecoropupil(f):
-    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "HCIPUPIL"
+    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "CORONOGRAPHY" and f["dpr.type"] == "PUPIL"
 
-raw_opt_sky_skyhci_coro_sciencecoropupil_class = ClassificationRule("SCIENCECOROPUPIL_RAW", is_raw_opt_sky_skyhci_coro_sciencecoropupil)
+raw_opt_sky_skyhci_coro_sciencecoropupil_class = ClassificationRule("I_SCI_CORO_PUPIL_RAW", is_raw_opt_sky_skyhci_coro_sciencecoropupil)
 
 raw_opt_sky_skyhci_coro_sciencecoropupil = (
     data_source()
@@ -251,9 +243,9 @@ raw_opt_sky_skyhci_coro_sciencecoropupil = (
 
 
 def is_raw_opt_sky_skyhci_coro_sciencecorowaffle(f):
-    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "WAFFLE"
+    return f["dpr.catg"] == "SCIENCE" and f["dpr.tech"] == "CORONOGRAPHY,WAFFLE" and f["dpr.type"] == "OBJECT"
 
-raw_opt_sky_skyhci_coro_sciencecorowaffle_class = ClassificationRule("SCIENCECOROWAFFLE_RAW", is_raw_opt_sky_skyhci_coro_sciencecorowaffle)
+raw_opt_sky_skyhci_coro_sciencecorowaffle_class = ClassificationRule("I_SCI_CORO_WAFFLE_RAW", is_raw_opt_sky_skyhci_coro_sciencecorowaffle)
 
 raw_opt_sky_skyhci_coro_sciencecorowaffle = (
     data_source()
@@ -266,12 +258,10 @@ raw_opt_sky_skyhci_coro_sciencecorowaffle = (
 
 
 
-
-
 def is_raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt(f):
-    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "IMAGE" and f["dpr.type"] == "HCIOPT"
+    return f["dpr.catg"] == "CALIB" and f["dpr.tech"] == "CORONOGRAPHY" and f["dpr.type"] == "HCIOPT"
 
-raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt_class = ClassificationRule("DPSICSOPT_RAW", is_raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt)
+raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt_class = ClassificationRule("I_DPSICS_OPT_RAW", is_raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt)
 
 raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt = (
     data_source()
@@ -281,83 +271,44 @@ raw_opt_sky_skyhci_skyhcionline_dpsicsoptsci_dpsicsopt = (
 
 
 
-img_persistence = (
-    task('micado_det_persistence')
-    .with_main_input(raw)
-    .with_associated_input(raw)
-    .build()
-)
-
-
-img_dp_dpopt_dpsky_dpsiai_dpscience = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_sky_skysiai_science)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
-img_dp_dpdark = (
-    task('micado_det_depersist')
-    .with_main_input(raw_dark)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
 img_masterdark = (
     task('micado_det_dark')
-    .with_main_input(img_dp_dpdark)
-
-    .build()
-)
-
+    .with_main_input(raw_dark)
 
-img_dp_dpopt_dpflat = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_flat)
-    .with_associated_input(img_persistence)
     .build()
 )
 
 
 img_masterflat = (
     task('micado_img_flat')
-    .with_main_input(img_dp_dpopt_dpflat)
+    .with_main_input(raw_opt_flat)
     .with_associated_input(img_masterdark)
     .build()
 )
 
 
-img_dp_dpopt_dpnonlin = (
-    task('micado_det_depersist')
+img_nonlinearity = (
+    task('micado_img_nonlinearity')
     .with_main_input(raw_opt_nonlin)
-    .with_associated_input(img_persistence)
+
     .build()
 )
 
 
-img_nonlinearity = (
-    task('micado_img_nonlinearity')
-    .with_main_input(img_dp_dpopt_dpnonlin)
-    .with_associated_input(raw_opt_nonlin)
+img_persistence = (
+    task('micado_det_persistence')
+    .with_main_input(raw)
+    .with_associated_input(raw)
     .build()
 )
 
 
 img_fnl_catalogable_dt_dtsiai_dt = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpsky_dpsiai_dpscience)
+    .with_main_input(raw_opt_sky_skysiai_science)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
-    .build()
-)
-
-
-img_dp_dpopt_dpsky_dpbkgfield = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_sky_bkgfield)
     .with_associated_input(img_persistence)
     .build()
 )
@@ -365,10 +316,11 @@ img_dp_dpopt_dpsky_dpbkgfield = (
 
 img_fnl_catalogable_dt_dtbkgfield = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpsky_dpbkgfield)
+    .with_main_input(raw_opt_sky_bkgfield)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
+    .with_associated_input(img_persistence)
     .build()
 )
 
@@ -381,20 +333,13 @@ img_background = (
 )
 
 
-img_dp_dpopt_dpsky_dpillum = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_sky_illum)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
 img_fnl_catalogable_dt_dtillum = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpsky_dpillum)
+    .with_main_input(raw_opt_sky_illum)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
+    .with_associated_input(img_persistence)
     .build()
 )
 
@@ -416,20 +361,13 @@ img_fnl_catalogable_dtfnl_dtfnlsiai_dtfnl = (
 )
 
 
-img_dp_dpopt_dpsky_dpsiai_dpscienceai = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_sky_skysiai_scienceai)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
 img_fnl_catalogable_dt_dtsiai_dtai = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpsky_dpsiai_dpscienceai)
+    .with_main_input(raw_opt_sky_skysiai_scienceai)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
+    .with_associated_input(img_persistence)
     .build()
 )
 
@@ -443,20 +381,13 @@ img_fnl_catalogable_dtfnl_dtfnlsiai_dtfnlai = (
 )
 
 
-img_dp_dpopt_dpwam = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_wamcam_wam)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
 img_fnl_catalogable_dt_dtwam = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpwam)
+    .with_main_input(raw_opt_wamcam_wam)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
+    .with_associated_input(img_persistence)
     .build()
 )
 
@@ -478,20 +409,13 @@ hdr_distortion_distortionwam = (
 )
 
 
-img_dp_dpopt_dpsky_dpastromfield = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_sky_astromfield)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
 img_fnl_catalogable_dt_dtastromfield = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpsky_dpastromfield)
+    .with_main_input(raw_opt_sky_astromfield)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
+    .with_associated_input(img_persistence)
     .build()
 )
 
@@ -532,20 +456,13 @@ hdr_photom_photomscience = (
 )
 
 
-img_dp_dpopt_dpsky_dpstdfield = (
-    task('micado_det_depersist')
-    .with_main_input(raw_opt_sky_stdfield)
-    .with_associated_input(img_persistence)
-    .build()
-)
-
-
 img_fnl_catalogable_dt_dtstdfield = (
     task('micado_img_detrend')
-    .with_main_input(img_dp_dpopt_dpsky_dpstdfield)
+    .with_main_input(raw_opt_sky_stdfield)
     .with_associated_input(img_masterdark)
     .with_associated_input(img_masterflat)
     .with_associated_input(img_nonlinearity)
+    .with_associated_input(img_persistence)
     .build()
 )
 
diff --git a/setup.cfg b/setup.cfg
index 79cceb4854c896871277f42d9d936299f5217fae..5211331a456ad96db2f277fd7f0c0d376a397ed0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -23,4 +23,3 @@ filterwarnings =
     ignore:numpy.ndarray size changed, may indicate binary incompatibility. Expected:RuntimeWarning
     # Triggered by astropy
     ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning
-
diff --git a/src/micado/__init__.py b/src/micado/__init__.py
index dab456114127be456d2839c9a81e337fad451a1c..84421c902ae68fe1d5d1c44b055e4748386002dd 100644
--- a/src/micado/__init__.py
+++ b/src/micado/__init__.py
@@ -1,3 +1,13 @@
 """Main Python package for MicadoWISE and the MICADO Imaging Digital Design."""
 
 __version__ = "develop"
+
+
+# have the log handlers already been set ?
+import logging
+
+if not logging.getLogger().handlers:
+    # from common.log.PythonLogging import init_python_logging
+    from micado.util.Logging import init_python_logging
+
+    init_python_logging()
diff --git a/src/micado/config/Environment.cfg b/src/micado/config/Environment.cfg
index b8542e9271b65f2fc9aa28ac0191145a41eed13f..44a71fcc68ca1f5254481a11a065488d46c56e06 100644
--- a/src/micado/config/Environment.cfg
+++ b/src/micado/config/Environment.cfg
@@ -64,3 +64,14 @@ mockcommon          :
 
 ; Whether to use MDBObjectMeta._find_existing().
 use_find_existing   :
+
+; use python logging
+use_python_logging : 1
+; python logging level; DEBUG, INFO, WARNING, ERROR, CRITICAL
+; This variable must be set before awe is started
+; During an awe session use: logging.getLogger().setLevel(<level>)
+python_logging_level : INFO
+; formatting of lines with python logging
+python_logging_format : %(asctime)s [%(levelname)s] %(name)s: %(message)s
+; formatting of dates with python logging
+python_logging_format_date : %Y-%m-%d %H:%M:%S
diff --git a/src/micado/main/BaseFrameExtra.py b/src/micado/main/BaseFrameExtra.py
index 19145a8ea6d074a301e5ecb7b7da782e1a51b522..94029084bd0cf1925268bc4cb928d7e31ef619e2 100644
--- a/src/micado/main/BaseFrameExtra.py
+++ b/src/micado/main/BaseFrameExtra.py
@@ -4,6 +4,7 @@
 It represents a single-layer image.
 """
 
+import logging
 import tempfile
 
 from astropy.io import fits
@@ -25,6 +26,16 @@ class BaseFrameExtra(DataItem):
     header_org: fits.Header = None
     # The original FITS header, if any.
 
+    @classmethod
+    def compare_fits_header_entry(cls, name, value, value_compare):
+        """compare the fits header entry with name and value against value_compare"""
+        if name == "FNSRC0" and "(" in value_compare:
+            # the called methods on scopesim can contain arguments that are not set
+            # on the WISE side, remove the arguments from the ()
+            element1, element2 = value_compare.rsplit("(", 1)
+            value_compare = element1 + "()"
+        return value == value_compare
+
     def save_fits(self, filename: str = None):
         """Save as FITS file."""
         # TODO: Ensure the path where FITS files are stored and read from
@@ -38,7 +49,7 @@ class BaseFrameExtra(DataItem):
                     delete=False,
                 ).name
             filename = self.filename
-
+        logging.getLogger(__name__).info(f"save_fits to {filename}")
         header_primary_auto = fits.Header(self.fits_keywords)
         if self.header_org:
             header_primary = self.header_org.copy()
@@ -50,12 +61,12 @@ class BaseFrameExtra(DataItem):
             for key, value in header_primary_auto.items():
                 key2 = key.replace("WISE ", "ESO ")
                 if key in header_primary:
-                    assert (
-                        value == header_primary[key]
+                    assert self.compare_fits_header_entry(
+                        key, value, header_primary[key]
                     ), f"{key}: {value} != {header_primary[key]}"
                 elif key2 in header_primary:
-                    assert (
-                        value == header_primary[key2]
+                    assert self.compare_fits_header_entry(
+                        key, value, header_primary[key2]
                     ), f"{key2}: {value} != {header_primary[key2]}"
                 else:
                     # TODO: raise an exception here once ScopeSIM can produce
diff --git a/src/micado/main/HardwareThingExtra.py b/src/micado/main/HardwareThingExtra.py
index 3ef153be5e47d5bb63d29f2b30ba08767a120a42..49286d2db5ce469275616652c3345a76ff7cfa30 100644
--- a/src/micado/main/HardwareThingExtra.py
+++ b/src/micado/main/HardwareThingExtra.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 """Hardware that represents a thing. E.g. a Detector."""
+
 from micado.main.Hardware import Hardware
 
 
diff --git a/src/micado/main/MDBObjectMeta.py b/src/micado/main/MDBObjectMeta.py
index 475fb11bf2a1dfac42ea6901dd0496e241b858b5..3e26f2cfec5a77a8d46dcec5e9d4e0258404347e 100644
--- a/src/micado/main/MDBObjectMeta.py
+++ b/src/micado/main/MDBObjectMeta.py
@@ -9,26 +9,34 @@ The extra functionality might at some point be ported back to common.
 """
 
 import itertools
+import logging
 import os
 import re
+
 from collections import OrderedDict
+from dataclasses import dataclass, field
 from pathlib import Path
+from pprint import pformat
 from typing import List, Dict, Union, Tuple, Optional
-from dataclasses import dataclass, field
 
 import yaml
+
 from astropy.io import fits
 from astropy.io.fits import Header
+
 from micado.config.Environment import Env
 from micado.main.commonwrapper import (
-    link_list_property,
+    classcache,
+    DBSelect,
+    DBObjectMeta,
     desc_list_property,
     desc_property,
+    link_list_property,
 )
 
-from micado.main.commonwrapper import DBSelect
-from micado.main.commonwrapper import classcache
-from micado.main.commonwrapper import DBObjectMeta
+# from micado.main.commonwrapper import classcache
+# from micado.main.commonwrapper import DBSelect
+# from micado.main.commonwrapper import DBObjectMeta
 from micado.main.FakePropertyDict import FakePropertyDict
 
 PATH_TEXT_YAML = Path(__file__).resolve().parent.parent.parent / "text"
@@ -144,6 +152,8 @@ class MDBObjectMeta(DBObjectMeta):
         cls.text_raw, cls.text_pro, cls.text_recipestep = get_meta(name)
         return cls
 
+    # TODO remove autocommit; let the user decide to call commit() after object creation
+    # TODO remove default_objects; make explicit in the header if object needs to be None
     def __call__(
         cls,
         autocommit: bool = False,
@@ -168,7 +178,6 @@ class MDBObjectMeta(DBObjectMeta):
         - _construct_object_from_fitsfile(): filename of FITS file is given.
         - _construct_object_from_fitsheader(): FITS header is given.
         - _construct_object_from_attributes(): attributes are given as kwargs.
-        - _call_other_cls(): class overide is given in CLS (for Templates).
 
         _construct_object_from_fitsheader() is called for each extension in the
         FITS file, as well as the primary HDU. The FITS keywords hierarchically
@@ -189,28 +198,16 @@ class MDBObjectMeta(DBObjectMeta):
 
         TODO: Fix autocommit, see also _find_existing().
         """
-        if "CLS" in kwargs:
-            # TODO: This cannot happen anymore, replace this logic with
-            #       DPR.TYPE/DPR.CATG/DPR.TECH or PRO.CATG checking.
-            assert False
-            # The CLS is the name of a derived class. See Template
-            cls_id = kwargs["CLS"]
-            kwargs2 = {k: v for k, v in kwargs.items() if k not in ["CLS"]}
-            s = cls._call_other_cls(
-                cls_id=cls_id,
-                *args,
-                **kwargs2,
-            )
-        elif "object_id" in kwargs:
+        if "object_id" in kwargs:
             # A specific object id is given, delegate to super class.
-            # s will be None if object_id is None, which happens when
+            # obj will be None if object_id is None, which happens when
             # instantiating an object from the database that has a
             # link_property of None.
-            s = DBObjectMeta.__call__(cls, *args, **kwargs)
+            obj = DBObjectMeta.__call__(cls, *args, **kwargs)
         elif kwargs.keys() == {"filename"}:
             filename = kwargs["filename"]
             if filename:
-                s = cls._construct_object_from_fitsfile(filename=filename)
+                obj = cls._construct_object_from_fitsfile(filename=filename)
             else:
                 # There are no other kwargs, but an empty filename. This is only
                 # sensible for Effects that have no attributes, like
@@ -225,20 +222,7 @@ class MDBObjectMeta(DBObjectMeta):
                 from micado.main.Recipe import Recipe
 
                 assert not attr_names or issubclass(cls, Recipe)
-                s = DBObjectMeta.__call__(cls)
-        elif "header" in kwargs and "CLS" in kwargs["header"]:
-            # TODO: This does not work anymore, need to use ID or something.
-            assert False
-            # A different class is specified than this one, need to construct
-            # an instance of that.
-            # TODO: ESO uses ID where we use CLS, switch to that.
-            header = kwargs["header"]
-            cls_id = header["CLS"]
-            header2 = {k: v for k, v in header.items() if k not in ["CLS"]}
-            kwargs2 = {k: v for k, v in kwargs.items() if k not in ["header"]}
-            kwargs2["header"] = header2
-            kwargs2["CLS"] = cls_id
-            s = cls(autocommit=False, *args, **kwargs2)
+                obj = DBObjectMeta.__call__(cls)
         elif "header" in kwargs:
             header1 = kwargs["header"]
             kwargs2 = {
@@ -246,15 +230,14 @@ class MDBObjectMeta(DBObjectMeta):
                 for k, v in kwargs.items()
                 if k not in ["header", "detectors_from_fits"]
             }
-            detectors_from_fits = kwargs.get("detectors_from_fits", None)
-            s = cls._construct_object_from_fitsheader(
+            obj = cls._construct_object_from_fitsheader(
                 header=header1,
-                detectors_from_fits=detectors_from_fits,
+                detectors_from_fits=kwargs.get("detectors_from_fits", None),
                 *args,
                 **kwargs2,
             )
         elif kwargs:
-            s = cls._construct_object_from_attributes(
+            obj = cls._construct_object_from_attributes(
                 default_objects=default_objects,
                 *args,
                 **kwargs,
@@ -263,7 +246,7 @@ class MDBObjectMeta(DBObjectMeta):
             # This is probably an attempt to construct an DBObject by
             # setting the properties manually. Therefore, do not commit.
             # Or this is called by _construct_object_from_attributes().
-            s = DBObjectMeta.__call__(cls)
+            obj = DBObjectMeta.__call__(cls)
             autocommit = False
             from micado.main.MObjectWISE import MObject
 
@@ -271,27 +254,27 @@ class MDBObjectMeta(DBObjectMeta):
             # E.g. when no LinearityCurve is mentioned in the headers, then
             # do not use the default, instead use None.
             if not default_objects:
-                for attr in s.get_persistent():
-                    val = getattr(s, attr)
+                for attr in obj.get_persistent():
+                    val = getattr(obj, attr)
                     if isinstance(val, MObject):
-                        setattr(s, attr, None)
+                        setattr(obj, attr, None)
 
         # This happens when an object with a link_property with a None value
         # is retrieved from the database.
-        if s is None:
-            return s
+        if obj is None:
+            return obj
 
         # Commit the object if necessary.
-        if not autocommit or s.persists():
-            return s
+        if not autocommit or obj.persists():
+            return obj
 
-        s.commit()
+        obj.commit()
         # Re-retrieve the object to ensure the id is always identical.
-        if s.persists():
-            return cls(object_id=s.object_id.binary())
+        if obj.persists():
+            return cls(object_id=obj.object_id.binary())
         else:
             # There probably is no database backend.
-            return s
+            return obj
 
     def _construct_object_from_fitsfile(cls, filename: str = None):
         """Create an instance from file.
@@ -320,6 +303,8 @@ class MDBObjectMeta(DBObjectMeta):
         if os.path.islink(filename) and not filename.endswith(".fits"):
             filename = os.readlink(filename)
 
+        logging.getLogger(__name__).info(f"_construct_object_from_fitsfile {cls}")
+        logging.getLogger(__name__).info(f"_construct_object_from_fitsfile {filename}")
         # Assume it's a fits file.
         with fits.open(filename) as hdulist:
             hduprimary = hdulist[0]
@@ -337,6 +322,9 @@ class MDBObjectMeta(DBObjectMeta):
                 for hdu in hdus
             }
             extensionnumbers = sorted(set(k for k, _ in hdusd))
+            logging.getLogger(__name__).info(
+                f"_construct_object_from_fitsfile ext nrs {extensionnumbers}"
+            )
             # E.g. ("1", "2", ..., "9")
             if hasattr(cls, "extensions"):
                 prop = getattr(cls, "extensions")
@@ -349,6 +337,14 @@ class MDBObjectMeta(DBObjectMeta):
                     extensions.append(extension)
                     if hasattr(cls, "detector"):
                         detectors.append(extension.detector)
+                # if the detector list could not be determined from the header, use dedault
+                from micado.hardware.DetectorArray import (
+                    default_detector_array_list_list,
+                )
+
+                # set default_detector_array_list when all None
+                if len([det for det in detectors if det]) == 0:
+                    detectors = default_detector_array_list_list
 
                 # Committing will be dealt with by the calling function.
                 if hasattr(cls, "detector"):
@@ -419,6 +415,24 @@ class MDBObjectMeta(DBObjectMeta):
         Returns:
             An MObject as defined by the header.
         """
+
+        logging.getLogger(__name__).info(f"_construct_object_from_fitsheader {cls}")
+        logging.getLogger(__name__).debug(
+            f"_construct_object_from_fitsheader header\n{pformat(header)}"
+        )
+        if detectors_from_fits:
+            logging.getLogger(__name__).info(
+                f"_construct_object_from_fitsheader detectors_from_fits {detectors_from_fits}"
+            )
+        if args:
+            logging.getLogger(__name__).debug(
+                f"_construct_object_from_fitsheader args {args}"
+            )
+        if kwargs:
+            logging.getLogger(__name__).debug(
+                f"_construct_object_from_fitsheader kwargs {kwargs}"
+            )
+
         # kwargs might contain 'extensions', so we copy it instead of creating
         # one from scratch. See call_filename and also Raw.__init__
         kwargs2 = kwargs.copy()
@@ -557,26 +571,31 @@ class MDBObjectMeta(DBObjectMeta):
             # Should be sorted:
             assert sorted(header_rec_d) == list(header_rec_d)
             attr_prog, cls_prog = cls.get_progenitor_attr_class()
+            logging.getLogger(__name__).info(
+                f"_construct_object_from_fitsfile progenitor {attr_prog} {cls_prog}"
+            )
             # Ensure the progenitor class is correct.
             # TODO: Only name_oca() should be used here.
-            assert {d["CATG"] for k, d in header_rec_d.items() if "RAW" in k} <= {
-                cls_prog.name_oca(),
-                cls_prog.name_eso(),
-            }
+            if cls_prog is not None:
+                assert {d["CATG"] for k, d in header_rec_d.items() if "RAW" in k} <= {
+                    cls_prog.name_oca(),
+                    cls_prog.name_eso(),
+                }
 
             # Convert the ESO-style headers back to a MicadoWISE-style dictionary.
             # TODO: It would be better to have one place to create this alias.
             #       For now, search for :3 to find them all.
-            attr_alias = attr_prog.attribute.upper().replace("_", "")[:3]
-            kwargs_progenitor = {
-                # f"{attr_alias}{i} FILENAME": d['NAME']
-                f"{attr_alias}{i}": OrderedDict(
-                    [(f"{attr_alias}{i} FILENAME", d["NAME"])]
-                )
-                for i, (k, d) in enumerate(header_rec_d.items(), 1)
-                if "RAW" in k
-            }
-            header_hierarchical.update(kwargs_progenitor)
+            if attr_prog is not None:
+                attr_alias = attr_prog.attribute.upper().replace("_", "")[:3]
+                kwargs_progenitor = {
+                    # f"{attr_alias}{i} FILENAME": d['NAME']
+                    f"{attr_alias}{i}": OrderedDict(
+                        [(f"{attr_alias}{i} FILENAME", d["NAME"])]
+                    )
+                    for i, (k, d) in enumerate(header_rec_d.items(), 1)
+                    if "RAW" in k
+                }
+                header_hierarchical.update(kwargs_progenitor)
 
             # TODO: Make this less fragile. It now depends on the order
             # of the CALIB keywords and it is not clear whether this is
@@ -650,6 +669,11 @@ class MDBObjectMeta(DBObjectMeta):
         # for hardware that is not mentioned in the FITS headers at all.
         return cls(autocommit=False, default_objects=False, *args, **kwargs2)
 
+    @classmethod
+    def attr_value_to_wise(cls, name, value):
+        """translate value of named attribute to wise value space, derived classes can implement"""
+        return value
+
     def _construct_object_from_attributes(cls, default_objects=True, *args, **kwargs):
         """Create an MObject by listing all the attribute values in the kwargs.
 
@@ -677,6 +701,18 @@ class MDBObjectMeta(DBObjectMeta):
         from micado.main.Recipe import Recipe
         from micado.main.DataItem import DataItem
 
+        logging.getLogger(__name__).info(
+            f"_construct_object_from_attributes {cls} default_objects={default_objects}"
+        )
+        if args:
+            logging.getLogger(__name__).debug(
+                f"_construct_object_from_attributes args {args}"
+            )
+        if kwargs:
+            logging.getLogger(__name__).debug(
+                f"_construct_object_from_attributes kwargs {kwargs}"
+            )
+
         args_fits = ["image", "uncertainty", "quality", "header"]
         args_do = ["object_id", "filename", "globalname"]
         attrs_persistent = [
@@ -719,18 +755,16 @@ class MDBObjectMeta(DBObjectMeta):
         # E.g. 'scopesim_templates.micado.empty_sky()' -> 'empty_sky'
         # See also _wise_key_from_fits_header_key and ObservingBlockExtra.
         # TODO: Generalize this. Perhaps finally use pydantic or so?
-        if "target" in kwargs and cls is ObservingBlock:
-            src = kwargs["target"]
-            sstart = "scopesim_templates.micado."
-            ssend = "()"
-            if src.startswith(sstart) and src.endswith(ssend):
-                kwargs["target"] = src[len(sstart) : -len(ssend)]
+        # if "target" in kwargs and cls is ObservingBlock:
+        #    target = kwargs["target"]
+        #    if target.startswith(ObservingBlock.target_prepend) and target.endswith(ObservingBlock.target_prepend):
+        #        kwargs["target"] = target[len(ObservingBlock.target_prepend) : -len(ObservingBlock.append)]
 
         # Try to find an existing object.
         # This is different from other WISE-implementations.
-        s_existing = cls._find_existing(**kwargs)
-        if s_existing is not None:
-            return s_existing
+        # s_existing = cls._find_existing(**kwargs)
+        # if s_existing is not None:
+        #    return s_existing
 
         # Create a new object. Do not commit, because properties need to be set.
         s1 = cls(autocommit=False, default_objects=default_objects)
@@ -744,6 +778,9 @@ class MDBObjectMeta(DBObjectMeta):
                 assert len(value) == 1
                 value = value[0]
 
+            # translation to wise value space
+            value = cls.attr_value_to_wise(name, value)
+
             # Mainly prevents setting None values.
             if getattr(s1, name) is not value:
 
@@ -792,7 +829,6 @@ class MDBObjectMeta(DBObjectMeta):
             >>> from micado.templates.MicadoImgCalDark import \
                 MicadoImgCalDark
             >>> header = {'DET__DIT': 1, 'DET__NDIT': 1}
-            >>> template = Template(CLS="MicadoImgCalDark", header=header)
             >>> assert isinstance(template, MicadoImgCalDark)
 
         Args:
@@ -845,6 +881,8 @@ class MDBObjectMeta(DBObjectMeta):
         are fixed.
         """
 
+        # TODO instead of doing this on kwargs, use use an (not committed) object to query for existing
+
         # Only use _find_existing if explicitly requested.
         if not Env["use_find_existing"]:
             return None
@@ -1264,7 +1302,8 @@ class MDBObjectMeta(DBObjectMeta):
         """Get the input data that is not the progenitor."""
         inputdata = cls.get_inputdata_full()
         prog_attr, _ = cls.get_progenitor_attr_class()
-        inputdata.pop(prog_attr)
+        if prog_attr is not None:
+            inputdata.pop(prog_attr)
         return inputdata
 
     def get_all_input_classes(cls):
@@ -1399,7 +1438,7 @@ def _wise_key_from_fits_header_key(key: str) -> str:
 
     # Convert internal ScopeSIM source keyword to MicadoWISE.
 
-    if key == "SIM SRC0 function_call":
+    if key == "FNSRC0":
         key = "OBS TARGET"
 
     if key.startswith("ESO "):
diff --git a/src/micado/main/MObjectExtra.py b/src/micado/main/MObjectExtra.py
index 805296730fe74729e82be858e983e751ab2b198f..42eede2143cf4d26a777a29d72f782cd9e4d31ae 100644
--- a/src/micado/main/MObjectExtra.py
+++ b/src/micado/main/MObjectExtra.py
@@ -30,9 +30,9 @@ def fix_key(key):
         if "PRO" in key:
             # Always use ESO compliance for PRO keywords.
             key = f"HIERARCH ESO {key}"
+        # else:
         elif not key.startswith("SIM"):
             # Some of the ScopeSIM keywords can be reused as is.
-            # Currently only used for "SIM SRC0 function_call".
             key = f"HIERARCH WISE {key}"
     # TODO: Generalize this translation to other attributes.
     if key == "MJDOBS":
diff --git a/src/micado/main/ObservingBlockExtra.py b/src/micado/main/ObservingBlockExtra.py
index 7ec5fa72df001ab31a03846a7e3b042773eca651..714f99f6e5531475898ec4a38e5187a94bac61eb 100644
--- a/src/micado/main/ObservingBlockExtra.py
+++ b/src/micado/main/ObservingBlockExtra.py
@@ -1,6 +1,8 @@
 # -*- coding: utf-8 -*-
 """Observing Blocks."""
 
+import logging
+
 from typing import List, Optional
 
 from micado.main.MObject import MObject
@@ -9,6 +11,24 @@ from micado.main.MObject import MObject
 class ObservingBlockExtra(MObject):
     """An Observing Block."""
 
+    prepend_append = {
+        "empty_sky": ("scopesim_templates.calibration.calibration.", "()"),
+        "cluster": ("scopesim_templates.stellar.clusters.", "()"),
+    }
+
+    @classmethod
+    def attr_value_to_wise(cls, name, value):
+        """for attribute target translate value"""
+        if isinstance(value, str):
+            for prepend, append in cls.prepend_append.values():
+                if value.startswith(prepend) and value.endswith(append):
+                    value_corrected = value[len(prepend) : -len(append)]
+                    logging.getLogger(__name__).info(
+                        f"corrected {value} to {value_corrected}"
+                    )
+                    return value_corrected
+        return value
+
     def real_fits_keywords(self, prefixes: Optional[List] = None):
         """Overloaded to not list the TPL keywords explicitly.
 
@@ -17,14 +37,20 @@ class ObservingBlockExtra(MObject):
         """
         # TODO: Only one template is allowed for now and should also be
         #       referenced in the raw.
-        attrs1 = MObject.real_fits_keywords(self, prefixes=prefixes)
-        attrs2 = {
-            k: v for k, v in attrs1.items() if "TPL" not in k and "TARGET" not in k
+        attrs = {
+            k: v
+            for k, v in super().real_fits_keywords(prefixes=prefixes).items()
+            if "TPL" not in k and "TARGET" not in k
         }
-        # Instead of TARGET, use "SIM SRC0 function_call" for now.
+        # Instead of TARGET, use "FNSRC0"
         # Conversion other way in _wise_key_from_fits_header_key
-        attrs2["SIM SRC0 function_call"] = f"scopesim_templates.micado.{self.target}()"
-        return attrs2
+        # attrs2["FNSRC0"] = self.target_prepend + self.target + self.target_append
+        if self.target in self.prepend_append:
+            prepend, append = self.prepend_append[self.target]
+            attrs["FNSRC0"] = prepend + self.target + append
+        else:
+            attrs["OBS TARGET"] = self.target
+        return attrs
 
     @property
     def scopesim_dictionary(self):
diff --git a/src/micado/main/RawExtra.py b/src/micado/main/RawExtra.py
index 401ea52b20ebeca084f4fa892ce211345d4ba518..920040515a54ac8fe5dc30ff83baa1460e211bd1 100644
--- a/src/micado/main/RawExtra.py
+++ b/src/micado/main/RawExtra.py
@@ -1,8 +1,10 @@
 """Module with persistent Raw classes."""
 
+import logging
 import socket
+
 from datetime import datetime
-import pprint
+from pprint import pformat
 from typing import List, Tuple, Optional
 
 from astropy.io import fits
@@ -19,7 +21,7 @@ from micado.main.BaseFrame import BaseFrame
 from micado.main.Simulator import SimulatorRun
 from micado.main.Template import Template
 
-from micado.util.irdb import PATH_IRDB_DEV, PATH_IRDB_PROD
+from micado.util.irdb import PATH_IRDB
 
 
 # TODO: Replace this with default_relayoptics directly once that works.
@@ -192,26 +194,25 @@ class RawExtra(BaseFrame):
         # The download is not necessary anymore, because the files
         # are now available in a submodule.
         # TODO: Find a nicer solution for this.
-        scopesim.rc.__search_path__ += [
-            str(PATH_IRDB_DEV),
-            str(PATH_IRDB_PROD),
-        ]
-        for name_package in [
-            "MICADO",
-            "ELT",
-            "Armazones",
-            # LFOA is necessary for the V filter for ScopeSIM_Templates.
-            "LFOA",
-        ]:
-            scopesim.rc.__search_path__ += [
-                str(PATH_IRDB_DEV / name_package),
-                str(PATH_IRDB_PROD / name_package),
-                # Also add the filters directory to find the V filter for
-                # the cluster template. This does not work either, because
-                # the .dat is not added.
-                str(PATH_IRDB_DEV / name_package / "filters"),
-                str(PATH_IRDB_PROD / name_package / "filters"),
-            ]
+        # TODO this should not be necessary anymore, PATH_IRDB is taken from scopesim.rc.__search_path__
+        # scopesim.rc.__search_path__ += [
+        #    str(PATH_IRDB),
+        # ]
+        # TODO is this still necessary ?
+        # for name_package in [
+        #    "MICADO",
+        #    "ELT",
+        #    "Armazones",
+        #    # LFOA is necessary for the V filter for ScopeSIM_Templates.
+        #    "LFOA",
+        # ]:
+        #    scopesim.rc.__search_path__ += [
+        #        str(PATH_IRDB / name_package),
+        #        # Also add the filters directory to find the V filter for
+        #        # the cluster template. This does not work either, because
+        #        # the .dat is not added.
+        #        str(PATH_IRDB / name_package / "filters"),
+        #    ]
 
         # TODO: Ensure observing_block has a role.
         #       E.g. the OB should set the template start.
@@ -221,7 +222,9 @@ class RawExtra(BaseFrame):
 
         assert isinstance(self, Raw)
 
-        pprint.pprint(self.scopesim_dictionaries)
+        logging.getLogger(__name__).info(
+            "scopesim_dictionaries: " + pformat(self.scopesim_dictionaries, width=200)
+        )
 
         target = self.observing_block.target
 
diff --git a/src/micado/main/TemplateExtra.py b/src/micado/main/TemplateExtra.py
index 8de787d14fc8368fff1772dd1b9b90962413cae1..19bef4dfc13d13f033b263f0485f81b6db4f0a29 100644
--- a/src/micado/main/TemplateExtra.py
+++ b/src/micado/main/TemplateExtra.py
@@ -61,22 +61,6 @@ class TemplateExtra(MObject):
             assert cls is Template
             return "Unknown"
 
-    def real_fits_keywords(self, prefixes: Optional[List] = None):
-        """Overloaded to add CLS.
-
-        Args:
-            prefixes: List of prefixes.
-        """
-        # TODO: or should this be a regular property?
-        # TODO: Align with use of ID in ESO templates, conficts with Detector
-        # TODO: Or infer this from the raw class instead, and we know that
-        #       due to the DPR keywords.
-        kws = super().real_fits_keywords(prefixes=prefixes)
-        # prefixes = prefixes if prefixes is not None else []
-        # k = " ".join(prefixes + ["CLS"])
-        # kws[k.upper()] = self.__class__.name_eso()
-        return kws
-
     @property
     def scopesim_dictionary(self):
         """Create ScopeSIM configuration dictionary."""
diff --git a/src/micado/main/commonmock.py b/src/micado/main/commonmock.py
index 85a87ad18ae38d63afd89115a96fca8f62cdad7b..b77366350285f70647cfcb65a4d8a8069d0e78f8 100644
--- a/src/micado/main/commonmock.py
+++ b/src/micado/main/commonmock.py
@@ -1,8 +1,10 @@
-from configparser import ConfigParser
-from copy import copy
-from dataclasses import dataclass
 import hashlib
 import inspect
+import logging
+
+from configparser import ConfigParser, InterpolationError
+from copy import copy
+from dataclasses import dataclass
 
 from micado.main.FakePropertyDict import FakePropertyDict
 
@@ -14,7 +16,13 @@ class ConfigFile(dict):
         super().__init__()
         parser = ConfigParser()
         parser.read(filename)
-        self.update(parser["global"])
+        # self.update(parser["global"])
+        section = "global"
+        for option in parser.options(section):
+            try:
+                self[option] = parser.get(section, option)
+            except InterpolationError:
+                self[option] = parser.get(section, option, raw=True)
         self["mockcommon"] = "True"
 
     def as_dict(self):
diff --git a/src/micado/test/functional/dark_test.py b/src/micado/test/functional/dark_test.py
index 55c39ffd5be9fadb9222a5ca0290e9a5090817c2..e965189276bf1a03f67e1da5f2f4c2baf30a3f79 100644
--- a/src/micado/test/functional/dark_test.py
+++ b/src/micado/test/functional/dark_test.py
@@ -5,6 +5,7 @@ TODO: Add tests for different det_dit and MJDOBS values.
 """
 
 import datetime
+import logging
 import os
 import shutil
 import sys
@@ -89,29 +90,27 @@ def generate_dark(
     return dark1
 
 
-def compare_raws(dark1: Raw, dark2: Raw):
+def compare_raws(raw1: Raw, raw2: Raw):
     """Compare two Raws."""
-    assert numpy.all(dark2.extensions[0].image == dark1.extensions[0].image)
-    assert dark1.extensions[0].NAXIS1 == dark2.extensions[0].NAXIS1
-    assert dark1.extensions[0].NAXIS2 == dark2.extensions[0].NAXIS2
-    assert dark1.detector == dark2.detector
-    assert dark1.template == dark2.template
-    assert dark1.observing_block == dark2.observing_block
-    ext1 = dark1.extensions[0]
-    ext2 = dark2.extensions[0]
+    assert numpy.all(raw2.extensions[0].image == raw1.extensions[0].image)
+    assert raw1.extensions[0].NAXIS1 == raw2.extensions[0].NAXIS1
+    assert raw1.extensions[0].NAXIS2 == raw2.extensions[0].NAXIS2
+    assert raw1.detector == raw2.detector
+    assert raw1.template == raw2.template
+    assert raw1.observing_block == raw2.observing_block
+    ext1 = raw1.extensions[0]
+    ext2 = raw2.extensions[0]
     assert ext1.detector == ext2.detector
     assert ext1 == ext2, ext1.get_differences(ext2)
-    assert dark2 == dark1
+    assert raw2 == raw1
 
 
 def test_dark():
     """Test creation of a Dark."""
-    Env["use_python_logging"] = True
     # Set the real dark current and create a DetectorArray.
     dark_real = 10000.0
 
     dark1 = generate_dark(dark_real=dark_real)
-
     dark1.save_fits()
     fn = dark1.filename
     verify_fitsheaders(fn)
@@ -144,7 +143,6 @@ def test_dark():
 
 def test_dark_multi():
     """Test creation of a Dark."""
-    Env["use_python_logging"] = True
     # Set the real dark current and create a DetectorArray.
     dark_real = 10000.0
     mydetectorarray = generate_detectorarray(dark=dark_real, size=32, n_det=2)
@@ -197,56 +195,9 @@ def test_dark_multi():
     remove_file_and_links(dark1.filename)
 
 
-@pytest.mark.xfail(
-    reason="TPL CLS is not supported anymore and should be replaced by DPR.* keyword logic."
-)
-@pytest.mark.skipif(sys.platform.startswith("win"), reason="Test will fail on Windows")
-def test_unknown_template():
-    """Test an unknown template.
-
-    This should just be ignored with a warning.
-    """
-    # TODO: Fix this test on Windows.
-    Env["use_python_logging"] = True
-
-    # Generate an image with only 32 by 32 pixels.
-    dark1 = generate_dark(size=32)
-    dark1.save_fits()
-
-    # Update the header to refer to a non-existing template.
-    hdus = fits.open(os.path.realpath(dark1.filename), mode="update")
-    assert hdus[0].header["WISE TPL CLS"] == MicadoImgCalDark.name_eso()
-    hdus[0].header["WISE TPL CLS"] = "MCD_does_not_exist"
-    hdus.close()
-
-    # And try to reopen the file, should print
-    # Warning: cannot find class MCD_does_not_exist
-    dark2 = Dark(filename=dark1.filename)
-    assert dark1 == dark2
-
-    # Create a Dark without an extension. This is the ESO standard for files
-    # with only one layer.
-    hdus = fits.open(os.path.realpath(dark1.filename), mode="update")
-    hdus[0].header.update(hdus[1].header)
-    hdus[0].data = hdus[1].data
-    # Need to fix the output because the header order is wrong.
-    hdus.close(output_verify="fix")
-
-    # Try to read it.
-    dark3 = Dark(filename=dark1.filename)
-    # TODO: Ensure dark1 and dark3 are the same.
-    #   Not an pytest.xfail because the cleanup is not in a fixture yet.
-    with pytest.raises(AssertionError):
-        assert dark1 == dark3
-
-    # Cleanup.
-    remove_file_and_links(dark1.filename)
-
-
 @pytest.mark.skipif(sys.platform.startswith("win"), reason="Test will fail on Windows")
 def test_template():
     """Test reading a template from FITS."""
-    Env["use_python_logging"] = True
 
     dark_template = MicadoImgCalDark(det__dit=1)
 
diff --git a/src/micado/test/functional/detector_test.py b/src/micado/test/functional/detector_test.py
index 89baf6c8f270c3c89a73304edda2bceaeec0fde4..09b9d80b215fa624ad86dc25e082ac39c064bcf9 100644
--- a/src/micado/test/functional/detector_test.py
+++ b/src/micado/test/functional/detector_test.py
@@ -45,7 +45,6 @@ def generate_detectorarray(dark: float = 2.0, size: int = 32, n_det=1) -> Detect
 
 def test_extra_parameters():
     """Test whether there is an error when extra parameters are specified."""
-    Env["use_python_logging"] = True
 
     with pytest.raises(AttributeError):
         _ = Detector(
diff --git a/src/micado/test/functional/detrend_test.py b/src/micado/test/functional/detrend_test.py
index d278e1bd95a84956bde9da206c083af7731538b7..e05f2d2f040c9c5e80352bf74072a1c5432d13c2 100644
--- a/src/micado/test/functional/detrend_test.py
+++ b/src/micado/test/functional/detrend_test.py
@@ -28,7 +28,6 @@ from .masterdark_test import create_masterdark
 
 def test_processing():
     """Test processing of Detrend."""
-    Env["use_python_logging"] = True
     mymasterdark, dark_real, myraws_raw = create_masterdark()
 
     # TODO: Do not reuse the MasterDark as MasterFlat.
diff --git a/src/micado/test/functional/flat_test.py b/src/micado/test/functional/flat_test.py
index 731b72678d9a509a7161aa2af63661c29dd0d5c9..406dabb1c02e7f83501fe0e496be898263ee8381 100644
--- a/src/micado/test/functional/flat_test.py
+++ b/src/micado/test/functional/flat_test.py
@@ -78,7 +78,6 @@ def generate_flat(dark: float = 2.0, size: int = 32):
 
 def test_flat():
     """Test creation of a Flat."""
-    Env["use_python_logging"] = True
     dark = 0.0
     flat1 = generate_flat(dark=dark)
 
diff --git a/src/micado/test/functional/masterdark_test.py b/src/micado/test/functional/masterdark_test.py
index 77dd2ab51410cc83104b8b9a9947bcec40e9da1e..cafc8625544522c284ae245a4d783eaa849d4cc3 100644
--- a/src/micado/test/functional/masterdark_test.py
+++ b/src/micado/test/functional/masterdark_test.py
@@ -143,7 +143,6 @@ def compare_pros(dataitem1: Img, dataitem2: Img):
 
 def test_processing():
     """Test creation of MasterDark."""
-    Env["use_python_logging"] = True
     mymasterdark, dark_real, mydarks_raw = create_masterdark()
 
     # Create image statistics.
@@ -188,7 +187,6 @@ def test_processing():
 
 def test_none_mobject_fits():
     """Test an '' reference in a FITS file."""
-    Env["use_python_logging"] = True
 
     masterdark1, _, mydarks_raw = create_masterdark(simple=True)
 
diff --git a/src/micado/test/functional/masterflat_test.py b/src/micado/test/functional/masterflat_test.py
index c59dae7b9534ba0e417fbfda82ff33920ed2787a..7db89718cf4725d119f8dec9c48cbab81f7095b8 100644
--- a/src/micado/test/functional/masterflat_test.py
+++ b/src/micado/test/functional/masterflat_test.py
@@ -65,7 +65,6 @@ def create_masterflat(simple: bool = False):
 
 def test_processing():
     """Test creation of MasterFlat."""
-    Env["use_python_logging"] = True
     mymasterflat, myflats_raw, mydarks = create_masterflat()
 
     # Create image statistics.
diff --git a/src/micado/test/functional/mdbobject_test.py b/src/micado/test/functional/mdbobject_test.py
index 3641f255f0279721209b0759d2786c7606b1b127..c2c34c55c76d8c0b9cacee7bcd29c9a411086b63 100644
--- a/src/micado/test/functional/mdbobject_test.py
+++ b/src/micado/test/functional/mdbobject_test.py
@@ -9,8 +9,6 @@ from micado.hardware.Detector import Detector
 
 def test_getraw():
     """Test getting raw dataproducts."""
-    Env["use_python_logging"] = True
-
     assert MasterDark.get_raw_attr_class() == ("darks", Dark)
     assert Dark.get_raw_class() == Dark
     assert Detector.get_raw_attr_class() == (None, None)
diff --git a/src/micado/test/functional/observingblock_test.py b/src/micado/test/functional/observingblock_test.py
index 42c6bb4c86ea716d5f97a27f4516f618d64dd0e4..e9f0876247d2efff11ce84e2460592c546343212 100644
--- a/src/micado/test/functional/observingblock_test.py
+++ b/src/micado/test/functional/observingblock_test.py
@@ -4,6 +4,7 @@
 from collections import OrderedDict
 from pathlib import Path
 
+from micado.main.ObservingBlockExtra import ObservingBlockExtra
 from micado.templates.MicadoImgCalDark import MicadoImgCalDark
 from micado.toolbox.obx_from_python import create_dark_ob
 
@@ -15,7 +16,8 @@ def test_ob_keywords():
     dark_ob = create_dark_ob()
 
     keywords_actual = dark_ob.fits_keywords
-
+    target = "empty_sky"
+    prepend, append = ObservingBlockExtra.prepend_append[target]
     keywords_desired = OrderedDict(
         [
             ("HIERARCH WISE OBS NAME", "MyDarkTest"),
@@ -24,11 +26,10 @@ def test_ob_keywords():
             # _construct_object_from_attributes
             # ObservingBlockExtra
             # ("HIERARCH WISE OBS TARGET", "empty_sky"),
-            ("SIM SRC0 function_call", "scopesim_templates.micado.empty_sky()"),
+            ("FNSRC0", prepend + target + append),
             ("HIERARCH WISE OBS INSTRUME", "MICADO"),
         ]
     )
-
     assert dict(keywords_actual) == dict(keywords_desired)
 
 
diff --git a/src/micado/test/functional/science_test.py b/src/micado/test/functional/science_test.py
index 1459c69d11ab7541b110637cbe59bf9ae509f15a..bd330a6ce0c19cfd7ef2604b9de4fb1d894a1d54 100644
--- a/src/micado/test/functional/science_test.py
+++ b/src/micado/test/functional/science_test.py
@@ -175,7 +175,6 @@ def get_science(size=32, dark_current=100):
 
 def test_science():
     """Test creation of a Raw Science image."""
-    Env["use_python_logging"] = True
 
     science1 = get_science()
     science1.make_simulation()
@@ -215,7 +214,6 @@ def test_science():
 
 def test_science_multi():
     """Test creation of a multi-extension raw image."""
-    Env["use_python_logging"] = True
     # Set the dark current and create a DetectorArray.
     dark_current = 100.0
     mydarkcurrent = DarkCurrent(value=dark_current)
diff --git a/src/micado/test/functional/stack_test.py b/src/micado/test/functional/stack_test.py
index a86aacdb11df5ba93a4bfa676a25b9722a2b1da1..b5659b12b697f4db27c2720a1600be1cc977aae7 100644
--- a/src/micado/test/functional/stack_test.py
+++ b/src/micado/test/functional/stack_test.py
@@ -31,7 +31,6 @@ from micado.test.functional.science_test import get_filt_inst_ro, get_atmo_teles
 )
 def test_stack():
     """Test stacking of images."""
-    Env["use_python_logging"] = True
 
     scopesim.server.download_package("telescopes/ELT")
     scopesim.server.download_package("instruments/MICADO")
diff --git a/src/micado/toolbox/python_from_vodml.py b/src/micado/toolbox/python_from_vodml.py
index 641a90a5143e7e4f791939874de2c74ef83a4aaf..cc6f330cb13dc3dc3f2da5cbc58021172cfb0f27 100644
--- a/src/micado/toolbox/python_from_vodml.py
+++ b/src/micado/toolbox/python_from_vodml.py
@@ -22,7 +22,8 @@ from micado.config.Environment import Env
 from micado.util.esokeywords import esokeywords
 from micado.util.irdb import irdb_from_class_attr
 
-USE_SQLALCHEMY = Env["database_engine"] == "sqlalchemy"
+# USE_SQLALCHEMY = Env["database_engine"] == "sqlalchemy"
+USE_SQLALCHEMY = False
 
 S_GENERATED = "This file is automatically generated."
 
diff --git a/src/micado/util/Logging.py b/src/micado/util/Logging.py
new file mode 100644
index 0000000000000000000000000000000000000000..fea110f66bf3946ea44e6c98ca92e185c184273b
--- /dev/null
+++ b/src/micado/util/Logging.py
@@ -0,0 +1,15 @@
+"""
+    Module with Logging utils
+"""
+
+import logging
+
+
+def init_python_logging():
+    """initialize the python logging facility"""
+    log = logging.getLogger()
+    # start with no handlers, previous handlers are removed
+    log.handlers = []
+    log.setLevel("INFO")
+    # add a console logger
+    logging.getLogger().addHandler(logging.StreamHandler())
diff --git a/src/micado/util/esokeywords.py b/src/micado/util/esokeywords.py
index 2eca8b4b0bd5f6266626e0c6ab66a57f2485524a..346b184dd8472e3742b4b5b559051fe026d071f7 100644
--- a/src/micado/util/esokeywords.py
+++ b/src/micado/util/esokeywords.py
@@ -47,7 +47,7 @@ def verify_fitsheaders(filename: str):
 
         errors = []
 
-        key_src = "HIERARCH SIM SRC0 function_call"
+        key_src = "FNSRC0"
         # The source is allowed to be 'scopesim_templates.micado.empty_sky()'
         # but not 'scopesim_templates.micado.cluster(mass=5)'
         if key_src in ffits[0].header:
@@ -56,7 +56,7 @@ def verify_fitsheaders(filename: str):
                 errors.append(f"{key_src} should not have an =-sign: {value_src}")
 
         for hk in ffits[0].header:
-            if hk.startswith("SIM SRC"):
+            if hk.startswith("SIM SRC") or hk.startswith("FNSRC"):
                 # Internal ScopeSIM header.
                 continue
             hk2 = hk[4:] if hk.startswith("ESO ") else hk
diff --git a/src/micado/util/irdb.py b/src/micado/util/irdb.py
index c64295c572f74251983e3698c599a6720ba05165..b02ac6299ae646e55303857eb4da7ca51977e652 100644
--- a/src/micado/util/irdb.py
+++ b/src/micado/util/irdb.py
@@ -2,26 +2,43 @@
 import os
 from pathlib import Path
 
-import yaml
-
+# import irdb
 import scopesim.rc
+import yaml
 
-PATH_HERE = Path(__file__).resolve().parent
+# PATH_HERE = Path(__file__).resolve().parent
 # Path in the repository where the IRDB git-submodule is installed.
-PATH_IRDB_DEV = PATH_HERE.parent.parent.parent / "irdb"
+# PATH_IRDB_DEV = PATH_HERE.parent.parent.parent / "irdb"
 # Path in site-packages where the IRDB is copied to.
-PATH_IRDB_PROD = PATH_HERE.parent.parent / "irdb"
+# PATH_IRDB_PROD = PATH_HERE.parent.parent / "irdb"
+
+# if os.path.exists(PATH_IRDB_DEV):
+#    PATH_IRDB = PATH_IRDB_DEV
+# elif os.path.exists(PATH_IRDB_PROD):
+#    PATH_IRDB = PATH_IRDB_PROD
+# else:
+#    raise ValueError(f"Cannot find IRDB: {PATH_IRDB_DEV} or {PATH_IRDB_PROD}")
+
+# PATH_IRDB = Path(irdb.__path__[0])
+
+
+def get_path_irdb(needed=["Armazones", "ELT", "MICADO", "LFOA", "MAORY"]):
+    """return path to irdb"""
+    for test_path in scopesim.rc.__search_path__:
+        if os.path.exists(test_path):
+            entries = os.listdir(test_path)
+            # are X needed entries present in the test_path?
+            if len(set(entries)) - len(set(entries) - set(needed)) == len(needed):
+                return Path(test_path)
+    raise NotImplementedError(f"irdb path not found for packages: {str(needed)}")
+
 
-if os.path.exists(PATH_IRDB_DEV):
-    PATH_IRDB = PATH_IRDB_DEV
-elif os.path.exists(PATH_IRDB_PROD):
-    PATH_IRDB = PATH_IRDB_PROD
-else:
-    raise ValueError(f"Cannot find IRDB: {PATH_IRDB_DEV} or {PATH_IRDB_PROD}")
+PATH_IRDB = get_path_irdb()
 
 # Fill search path so relevant .dat files can be found in python_from_vodml.py
-for hwd in ["MICADO", "Armazones", "ELT", "MICADO"]:
-    scopesim.rc.__search_path__.append(str(PATH_IRDB / hwd))
+for name in ["MICADO", "Armazones", "ELT", "MICADO"]:
+    scopesim.rc.__search_path__.append(str(PATH_IRDB / name))
+    scopesim.rc.__search_path__.append(str(PATH_IRDB / name / "filters"))
 
 # TODO: Get all yaml files from from MICADO_default.yaml.
 INSTRUMENT = yaml.safe_load(open(PATH_IRDB / "MICADO" / "MICADO.yaml"))