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"))