├── .gitignore ├── CMakeLists.txt ├── INSTALL.md ├── LICENSE ├── README.md ├── bin ├── cvif ├── govif ├── gvif ├── ovif ├── provif └── vif ├── cmake ├── FindCFITSIO.cmake ├── FindFFTW.cmake ├── FindGSL.cmake ├── FindGooglePerfTools.cmake ├── FindLAPACK.cmake ├── FindLibClang.cmake ├── FindLibDwarf.cmake ├── FindLibElf.cmake ├── FindLibUnwind.cmake ├── FindWCSLib.cmake └── Findvif.cmake ├── doc ├── .gitignore ├── 2html │ ├── 2html_category.cpp │ ├── 2html_functions.cpp │ ├── build.sh │ ├── common.hpp │ ├── footer.html │ ├── footer.tex │ ├── header.html │ ├── header.tex │ ├── make_index.cpp │ ├── pygments.css │ ├── section-link.png │ └── vectorized.png ├── latex │ ├── category_support_01_intro.tex │ ├── category_support_02_generic.tex │ ├── category_support_03_cmd.tex │ ├── category_support_04_string.tex │ ├── category_support_05_os.tex │ ├── category_support_06_file.tex │ ├── category_support_07_print.tex │ ├── category_support_08_time.tex │ ├── category_support_09_math.tex │ ├── category_support_10_thread.tex │ ├── category_support_11_fits.tex │ ├── category_support_12_image.tex │ ├── category_support_13_astro.tex │ ├── compile.sh │ ├── functions_support_astro_catalog.tex │ ├── functions_support_astro_cosmo.tex │ ├── functions_support_astro_flux.tex │ ├── functions_support_astro_psffit.tex │ ├── functions_support_astro_sedfit.tex │ ├── functions_support_astro_sky.tex │ ├── functions_support_astro_stack.tex │ ├── functions_support_cmd.tex │ ├── functions_support_file_ascii.tex │ ├── functions_support_file_system.tex │ ├── functions_support_fits_header.tex │ ├── functions_support_fits_image.tex │ ├── functions_support_fits_table.tex │ ├── functions_support_fits_wcs.tex │ ├── functions_support_generic_dim.tex │ ├── functions_support_generic_error.tex │ ├── functions_support_generic_find.tex │ ├── functions_support_generic_index.tex │ ├── functions_support_generic_range.tex │ ├── functions_support_generic_rearrange.tex │ ├── functions_support_generic_sequence.tex │ ├── functions_support_generic_vectorize.tex │ ├── functions_support_image.tex │ ├── functions_support_math_algebra.tex │ ├── functions_support_math_calculus.tex │ ├── functions_support_math_fit.tex │ ├── functions_support_math_geometry.tex │ ├── functions_support_math_interpol.tex │ ├── functions_support_math_lowlevel.tex │ ├── functions_support_math_random.tex │ ├── functions_support_math_reduce.tex │ ├── functions_support_math_sequence.tex │ ├── functions_support_os.tex │ ├── functions_support_print.tex │ ├── functions_support_string_convert.tex │ ├── functions_support_string_modify.tex │ ├── functions_support_thread.tex │ ├── functions_support_time.tex │ ├── phypp.pdf │ └── phypp.tex └── sphinx │ ├── Makefile │ ├── argv.rst │ ├── astro.rst │ ├── conf.py │ ├── filesystem-paths.rst │ ├── filesystem-system.rst │ ├── filesystem.rst │ ├── fits_hierarchy.svg │ ├── generic-error.rst │ ├── generic-find.rst │ ├── generic-function-guidelines.rst │ ├── generic-indices.rst │ ├── generic-range.rst │ ├── generic-rearrange.rst │ ├── generic-sequence.rst │ ├── generic.rst │ ├── icon_black_text.svg │ ├── idl.rst │ ├── image.rst │ ├── index.rst │ ├── indexing.rst │ ├── io-ascii.rst │ ├── io-fits-hdu.rst │ ├── io-fits-image.rst │ ├── io-fits-keywords.rst │ ├── io-fits-open.rst │ ├── io-fits-overview.rst │ ├── io-fits-raw.rst │ ├── io-fits-table.rst │ ├── io-fits.rst │ ├── known-issues.rst │ ├── math.rst │ ├── os-process.rst │ ├── os-sysvar.rst │ ├── os.rst │ ├── overview.rst │ ├── print.rst │ ├── string-base.rst │ ├── string-conversion.rst │ ├── string-find-replace.rst │ ├── string-format.rst │ ├── string-hash.rst │ ├── string-regex.rst │ ├── string-split.rst │ ├── string.rst │ ├── support-intro.rst │ ├── thread.rst │ ├── time.rst │ ├── vector.rst │ └── view.rst ├── icons ├── icon_black.svg ├── icon_black_text.svg ├── icon_explorations.svg ├── icon_white.svg └── icon_white_text.svg ├── include ├── vif.hpp └── vif │ ├── astro │ ├── astro.hpp │ ├── catalog_merge.hpp │ ├── ds9.hpp │ ├── image.hpp │ ├── qstack.hpp │ ├── qxmatch.hpp │ ├── template_fit.hpp │ └── wcs.hpp │ ├── core │ ├── bits │ │ ├── access.hpp │ │ ├── helpers.hpp │ │ ├── initializer_list.hpp │ │ ├── iterator.hpp │ │ ├── operators.hpp │ │ └── vectorize.hpp │ ├── error.hpp │ ├── iterator_base.hpp │ ├── main.hpp │ ├── meta.hpp │ ├── print.hpp │ ├── range.hpp │ ├── string_conversion.hpp │ ├── typedefs.hpp │ └── vec.hpp │ ├── io │ ├── ascii.hpp │ ├── filesystem.hpp │ ├── fits.hpp │ └── fits │ │ ├── base.hpp │ │ ├── file.hpp │ │ ├── image.hpp │ │ └── table.hpp │ ├── math │ ├── base.hpp │ ├── bits │ │ ├── matrix-functions.hpp │ │ └── matrix-types.hpp │ ├── complex.hpp │ ├── convex_hull.hpp │ ├── fourier.hpp │ ├── histogram.hpp │ ├── interpolate.hpp │ ├── lapack.hpp │ ├── linfit.hpp │ ├── matrix.hpp │ ├── mpfit.hpp │ ├── optimize.hpp │ ├── random.hpp │ ├── reduce.hpp │ └── transform.hpp │ ├── reflex │ ├── reflex.hpp │ └── reflex_helpers.hpp │ ├── test │ └── unit_test.hpp │ └── utility │ ├── argv.hpp │ ├── bits │ ├── generic-dims.hpp │ ├── generic-find.hpp │ ├── generic-indices.hpp │ ├── generic-rearrange.hpp │ ├── generic-sequences.hpp │ ├── string-base.hpp │ ├── string-find-replace.hpp │ ├── string-format.hpp │ ├── string-hash.hpp │ ├── string-regex.hpp │ ├── string-split.hpp │ ├── thread-parallel-for.hpp │ ├── thread-queue.hpp │ ├── thread-thread.hpp │ ├── thread-utils.hpp │ ├── thread-worker-pool.hpp │ └── thread-worker.hpp │ ├── generic.hpp │ ├── os.hpp │ ├── string.hpp │ ├── thread.hpp │ └── time.hpp ├── python └── pycolfits.py ├── sublime └── vif │ ├── DataFile.tmLanguage │ └── vif.sublime-snippet ├── test ├── .gitignore ├── data │ ├── image.fits │ ├── psf.fits │ ├── sources.fits │ ├── stack1.fits │ ├── stack2.fits │ ├── table.fits │ └── table.txt ├── fits │ └── test.cpp ├── speed │ ├── median.cpp │ └── run_dim.cpp ├── speed_test.cpp ├── unit │ ├── .gitignore │ ├── math │ │ ├── .gitignore │ │ ├── bounds.cpp │ │ └── fft.cpp │ └── vec.cpp └── unit_test.cpp └── tools ├── CMakeLists.txt ├── angcorrel ├── CMakeLists.txt └── angcorrel.cpp ├── catinfo ├── CMakeLists.txt └── catinfo.cpp ├── deg2sex ├── CMakeLists.txt └── deg2sex.cpp ├── findsrc ├── CMakeLists.txt ├── findsrc.ans └── findsrc.cpp ├── fits2ascii ├── CMakeLists.txt └── fits2ascii.cpp ├── fitstool ├── CMakeLists.txt └── fitstool.cpp ├── fluxcube ├── CMakeLists.txt └── fluxcube.cpp ├── getgal ├── CMakeLists.txt └── getgal.cpp ├── imgtool ├── CMakeLists.txt └── imgtool.cpp ├── photinfo ├── CMakeLists.txt └── photinfo.cpp ├── pixfit ├── CMakeLists.txt ├── pixfit-addflx.cpp ├── pixfit-addtdcst.cpp ├── pixfit-combine.cpp ├── pixfit-common.hpp ├── pixfit-cutout.cpp ├── pixfit-extract.cpp ├── pixfit-findprior.cpp ├── pixfit-gfit.cpp ├── pixfit-prep.cpp ├── pixfit-reg2fits.cpp ├── pixfit-residual.cpp └── pixfit-show.cpp ├── psffit ├── CMakeLists.txt └── psffit.cpp ├── qaper ├── CMakeLists.txt └── qaper.cpp ├── qconvol ├── CMakeLists.txt └── qconvol.cpp ├── qmask ├── CMakeLists.txt └── qmask.cpp ├── qregrid ├── CMakeLists.txt └── qregrid.cpp ├── qstack2 ├── CMakeLists.txt └── qstack2.cpp ├── qxmatch2 ├── CMakeLists.txt └── qxmatch2.cpp ├── radec2pix ├── CMakeLists.txt └── radec2pix.cpp ├── randsrc ├── CMakeLists.txt └── randsrc.cpp ├── refgen ├── CMakeLists.txt └── refgen.cpp ├── sex2deg ├── CMakeLists.txt └── sex2deg.cpp └── subsrc ├── CMakeLists.txt └── subsrc.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | code 2 | data 3 | lib 4 | bak 5 | phypp.sublime-workspace 6 | build/ 7 | doc/2html/2html_category 8 | doc/2html/2html_functions 9 | doc/2html/make_index 10 | -------------------------------------------------------------------------------- /bin/govif: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Source local vif configuration if running from root ("sudo" only) 4 | if [ -z "${VIF_COMPILER}" ]; then 5 | if [ "$(id -u)" -eq "0" ]; then 6 | if [ ! -z "${SUDO_USER}" ]; then 7 | eval source "~${SUDO_USER}/.phypprc" 8 | fi 9 | fi 10 | fi 11 | 12 | if [ -z "${VIF_COMPILER}" ]; then 13 | echo "error: the vif library is not installed for this user" 14 | exit 15 | fi 16 | 17 | if [ -f $1 ]; then 18 | if [ $1 -ot $1.cpp ]; then 19 | echo "vif: re-compiling '$1'..." 20 | RECOMPILE=1 21 | else 22 | RECOMPILE=0 23 | for f in ${VIF_PATH}/include/*; do 24 | if [ -f $f ] && [ "$f" -nt $1 ]; then 25 | echo "$f is more recent than program, re-compiling '$1'..." 26 | RECOMPILE=1 27 | break 28 | fi 29 | done 30 | if [ ${RECOMPILE} -eq 0 ]; then 31 | for f in ${VIF_PATH}/lib/*; do 32 | if [ -f $f ] && [ "$f" -nt $1 ]; then 33 | echo "$f is more recent than program, re-compiling '$1'..." 34 | RECOMPILE=1 35 | break 36 | fi 37 | done 38 | fi 39 | fi 40 | else 41 | echo "vif: compiling '$1'..." 42 | RECOMPILE=1 43 | fi 44 | 45 | if [ ${RECOMPILE} -eq 1 ]; then 46 | cvif time optimize debug $1.cpp 47 | if [ $? -ne 0 ]; then 48 | exit 49 | fi 50 | fi 51 | 52 | # Start the debugger and run the program 53 | a=./$1 54 | echo "vif: starting debugger..." 55 | shift 56 | (echo "run " $@; cat) | gdb ./$a 57 | -------------------------------------------------------------------------------- /bin/gvif: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Source local vif configuration if running from root ("sudo" only) 4 | if [ -z "${VIF_COMPILER}" ]; then 5 | if [ "$(id -u)" -eq "0" ]; then 6 | if [ ! -z "${SUDO_USER}" ]; then 7 | eval source "~${SUDO_USER}/.phypprc" 8 | fi 9 | fi 10 | fi 11 | 12 | if [ -z "${VIF_COMPILER}" ]; then 13 | echo "error: the vif library is not installed for this user" 14 | exit 15 | fi 16 | 17 | if [ -f $1 ]; then 18 | if [ $1 -ot $1.cpp ]; then 19 | echo "vif: re-compiling '$1'..." 20 | RECOMPILE=1 21 | else 22 | RECOMPILE=0 23 | for f in ${VIF_PATH}/include/*; do 24 | if [ -f $f ] && [ "$f" -nt $1 ]; then 25 | echo "$f is more recent than program, re-compiling '$1'..." 26 | RECOMPILE=1 27 | break 28 | fi 29 | done 30 | if [ ${RECOMPILE} -eq 0 ]; then 31 | for f in ${VIF_PATH}/lib/*; do 32 | if [ -f $f ] && [ "$f" -nt $1 ]; then 33 | echo "$f is more recent than program, re-compiling '$1'..." 34 | RECOMPILE=1 35 | break 36 | fi 37 | done 38 | fi 39 | fi 40 | else 41 | echo "vif: compiling '$1'..." 42 | RECOMPILE=1 43 | fi 44 | 45 | if [ ${RECOMPILE} -eq 1 ]; then 46 | cvif time debug $1.cpp 47 | if [ $? -ne 0 ]; then 48 | exit 49 | fi 50 | fi 51 | 52 | # TODO: http://stackoverflow.com/questions/1805840/arrow-key-via-stdin 53 | # Start the debugger and run the program 54 | a=./$1 55 | echo "vif: starting debugger..." 56 | shift 57 | (echo "run " $@; cat) | gdb ./$a 58 | -------------------------------------------------------------------------------- /bin/ovif: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Source local vif configuration if running from root ("sudo" only) 4 | if [ -z "${VIF_COMPILER}" ]; then 5 | if [ "$(id -u)" -eq "0" ]; then 6 | if [ ! -z "${SUDO_USER}" ]; then 7 | eval source "~${SUDO_USER}/.phypprc" 8 | fi 9 | fi 10 | fi 11 | 12 | if [ -z "${VIF_COMPILER}" ]; then 13 | echo "error: the vif library is not installed for this user" 14 | exit 15 | fi 16 | 17 | if [ -f $1 ]; then 18 | if [ $1 -ot $1.cpp ]; then 19 | echo "vif: re-compiling '$1'..." 20 | RECOMPILE=1 21 | else 22 | RECOMPILE=0 23 | for f in ${VIF_PATH}/include/*; do 24 | if [ -f $f ] && [ "$f" -nt $1 ]; then 25 | echo "$f is more recent than program, re-compiling '$1'..." 26 | RECOMPILE=1 27 | break 28 | fi 29 | done 30 | if [ ${RECOMPILE} -eq 0 ]; then 31 | for f in ${VIF_PATH}/lib/*; do 32 | if [ -f $f ] && [ "$f" -nt $1 ]; then 33 | echo "$f is more recent than program, re-compiling '$1'..." 34 | RECOMPILE=1 35 | break 36 | fi 37 | done 38 | fi 39 | fi 40 | else 41 | echo "vif: compiling '$1'..." 42 | RECOMPILE=1 43 | fi 44 | 45 | if [ ${RECOMPILE} -eq 1 ]; then 46 | cvif time optimize $1.cpp 47 | if [ $? -ne 0 ]; then 48 | exit 49 | fi 50 | fi 51 | 52 | # Run the program 53 | a=./$1 54 | shift 55 | $a "$@" 56 | -------------------------------------------------------------------------------- /bin/provif: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Source local vif configuration if running from root ("sudo" only) 4 | if [ -z "${VIF_COMPILER}" ]; then 5 | if [ "$(id -u)" -eq "0" ]; then 6 | if [ ! -z "${SUDO_USER}" ]; then 7 | eval source "~${SUDO_USER}/.phypprc" 8 | fi 9 | fi 10 | fi 11 | 12 | if [ -z "${VIF_COMPILER}" ]; then 13 | echo "error: the vif library is not installed for this user" 14 | exit 15 | fi 16 | 17 | if [ -f $1 ]; then 18 | if [ $1 -ot $1.cpp ]; then 19 | echo "vif: re-compiling '$1'..." 20 | RECOMPILE=1 21 | else 22 | RECOMPILE=0 23 | for f in ${VIF_PATH}/include/*; do 24 | if [ -f $f ] && [ "$f" -nt $1 ]; then 25 | echo "$f is more recent than program, re-compiling '$1'..." 26 | RECOMPILE=1 27 | break 28 | fi 29 | done 30 | if [ ${RECOMPILE} -eq 0 ]; then 31 | for f in ${VIF_PATH}/lib/*; do 32 | if [ -f $f ] && [ "$f" -nt $1 ]; then 33 | echo "$f is more recent than program, re-compiling '$1'..." 34 | RECOMPILE=1 35 | break 36 | fi 37 | done 38 | fi 39 | fi 40 | else 41 | echo "vif: compiling '$1'..." 42 | RECOMPILE=1 43 | fi 44 | 45 | if [ ${RECOMPILE} -eq 1 ]; then 46 | cvif time optimize profile $1.cpp 47 | if [ $? -ne 0 ]; then 48 | exit 49 | fi 50 | fi 51 | 52 | # Run the program 53 | a=$1 54 | shift 55 | OUTPROF=${VIF_TEMP_DIR}/._prof_$(basename $a).prof 56 | env CPUPROFILE=${OUTPROF} ./$a "$@" 57 | 58 | # Feed profiling data to the renderer 59 | ${VIF_PROFILER} --gv ./$a ${OUTPROF} 60 | -------------------------------------------------------------------------------- /bin/vif: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Source local vif configuration if running from root ("sudo" only) 4 | if [ -z "${VIF_COMPILER}" ]; then 5 | if [ "$(id -u)" -eq "0" ]; then 6 | if [ ! -z "${SUDO_USER}" ]; then 7 | eval source "~${SUDO_USER}/.phypprc" 8 | fi 9 | fi 10 | fi 11 | 12 | if [ -z "${VIF_COMPILER}" ]; then 13 | echo "error: the vif library is not installed for this user" 14 | exit 15 | fi 16 | 17 | if [ -f $1 ]; then 18 | if [ $1 -ot $1.cpp ]; then 19 | echo "vif: re-compiling '$1'..." 20 | RECOMPILE=1 21 | else 22 | RECOMPILE=0 23 | for f in ${VIF_PATH}/include/*; do 24 | if [ -f $f ] && [ "$f" -nt $1 ]; then 25 | echo "$f is more recent than program, re-compiling '$1'..." 26 | RECOMPILE=1 27 | break 28 | fi 29 | done 30 | if [ ${RECOMPILE} -eq 0 ]; then 31 | for f in ${VIF_PATH}/lib/*; do 32 | if [ -f $f ] && [ "$f" -nt $1 ]; then 33 | echo "$f is more recent than program, re-compiling '$1'..." 34 | RECOMPILE=1 35 | break 36 | fi 37 | done 38 | fi 39 | fi 40 | else 41 | echo "vif: compiling '$1'..." 42 | RECOMPILE=1 43 | fi 44 | 45 | if [ ${RECOMPILE} -eq 1 ]; then 46 | cvif time $1.cpp 47 | if [ $? -ne 0 ]; then 48 | exit 49 | fi 50 | fi 51 | 52 | # Run the program 53 | a=./$1 54 | shift 55 | $a "$@" 56 | -------------------------------------------------------------------------------- /cmake/FindCFITSIO.cmake: -------------------------------------------------------------------------------- 1 | # +-----------------------------------------------------------------------------+ 2 | # | Copyright (C) 2011 | 3 | # | Lars B"ahren (lbaehren@gmail.com) | 4 | # | | 5 | # | This program is free software; you can redistribute it and/or modify | 6 | # | it under the terms of the GNU General Public License as published by | 7 | # | the Free Software Foundation; either version 2 of the License, or | 8 | # | (at your option) any later version. | 9 | # | | 10 | # | This program is distributed in the hope that it will be useful, | 11 | # | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | # | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | # | GNU General Public License for more details. | 14 | # | | 15 | # | You should have received a copy of the GNU General Public License | 16 | # | along with this program; if not, write to the | 17 | # | Free Software Foundation, Inc., | 18 | # | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | # +-----------------------------------------------------------------------------+ 20 | 21 | # - Check for the presence of CFITSIO 22 | # 23 | # The following variables are set when CFITSIO is found: 24 | # CFITSIO_FOUND = Set to true, if all components of CFITSIO have been found. 25 | # CFITSIO_INCLUDES = Include path for the header files of CFITSIO 26 | # CFITSIO_LIBRARIES = Link these to use CFITSIO 27 | # CFITSIO_LFLAGS = Linker flags (optional) 28 | 29 | if (NOT CFITSIO_FOUND) 30 | 31 | if (NOT CFITSIO_ROOT_DIR) 32 | set (CFITSIO_ROOT_DIR ${CMAKE_INSTALL_PREFIX}) 33 | endif (NOT CFITSIO_ROOT_DIR) 34 | 35 | ##_____________________________________________________________________________ 36 | ## Check for the header files 37 | 38 | find_path (CFITSIO_INCLUDES fitsio.h fitsio2.h 39 | HINTS ${CFITSIO_ROOT_DIR} 40 | PATHS /sw /usr /usr/local /opt/local 41 | PATH_SUFFIXES include include/fitsio include/cfitsio 42 | ) 43 | 44 | ##_____________________________________________________________________________ 45 | ## Check for the library 46 | 47 | find_library (CFITSIO_LIBRARIES cfitsio 48 | HINTS ${CFITSIO_ROOT_DIR} 49 | PATHS /sw /usr /usr/local /opt/local 50 | PATH_SUFFIXES lib 51 | ) 52 | 53 | ##_____________________________________________________________________________ 54 | ## Check for CURL dependency 55 | 56 | find_package(CURL) 57 | 58 | ##_____________________________________________________________________________ 59 | ## Actions taken when all components have been found 60 | 61 | if (CFITSIO_INCLUDES AND CFITSIO_LIBRARIES) 62 | set (CFITSIO_FOUND TRUE) 63 | else (CFITSIO_INCLUDES AND CFITSIO_LIBRARIES) 64 | set (CFITSIO_FOUND FALSE) 65 | if (NOT CFITSIO_FIND_QUIETLY) 66 | if (NOT CFITSIO_INCLUDES) 67 | message (STATUS "Unable to find CFITSIO header files!") 68 | endif (NOT CFITSIO_INCLUDES) 69 | if (NOT CFITSIO_LIBRARIES) 70 | message (STATUS "Unable to find CFITSIO library files!") 71 | endif (NOT CFITSIO_LIBRARIES) 72 | endif (NOT CFITSIO_FIND_QUIETLY) 73 | endif (CFITSIO_INCLUDES AND CFITSIO_LIBRARIES) 74 | 75 | if (CURL_FOUND) 76 | list(APPEND CFITSIO_LIBRARIES ${CURL_LIBRARIES}) 77 | endif (CURL_FOUND) 78 | 79 | if (CFITSIO_FOUND) 80 | if (NOT CFITSIO_FIND_QUIETLY) 81 | message (STATUS "Found components for CFITSIO") 82 | if (CURL_FOUND) 83 | message (STATUS "HTTPS support (CURL)") 84 | endif (CURL_FOUND) 85 | message (STATUS "CFITSIO_INCLUDES = ${CFITSIO_INCLUDES}") 86 | message (STATUS "CFITSIO_LIBRARIES = ${CFITSIO_LIBRARIES}") 87 | endif (NOT CFITSIO_FIND_QUIETLY) 88 | else (CFITSIO_FOUND) 89 | if (CFITSIO_FIND_REQUIRED) 90 | message (FATAL_ERROR "Could not find CFITSIO!") 91 | endif (CFITSIO_FIND_REQUIRED) 92 | endif (CFITSIO_FOUND) 93 | 94 | ##_____________________________________________________________________________ 95 | ## Mark advanced variables 96 | 97 | mark_as_advanced ( 98 | CFITSIO_INCLUDES 99 | CFITSIO_LIBRARIES 100 | ) 101 | 102 | endif (NOT CFITSIO_FOUND) 103 | -------------------------------------------------------------------------------- /cmake/FindFFTW.cmake: -------------------------------------------------------------------------------- 1 | # - Find the FFTW library 2 | # 3 | # Usage: 4 | # find_package(FFTW [REQUIRED] [QUIET] ) 5 | # 6 | # It sets the following variables: 7 | # FFTW_FOUND ... true if fftw is found on the system 8 | # FFTW_LIBRARIES ... full path to fftw library 9 | # FFTW_INCLUDES ... fftw include directory 10 | # 11 | # The following variables will be checked by the function 12 | # FFTW_USE_STATIC_LIBS ... if true, only static libraries are found 13 | # FFTW_ROOT ... if set, the libraries are exclusively searched 14 | # under this path 15 | # FFTW_LIBRARY ... fftw library to use 16 | # FFTW_INCLUDE_DIR ... fftw include directory 17 | # 18 | 19 | #If environment variable FFTWDIR is specified, it has same effect as FFTW_ROOT 20 | if( NOT FFTW_ROOT AND ENV{FFTWDIR} ) 21 | set( FFTW_ROOT $ENV{FFTWDIR} ) 22 | endif() 23 | 24 | # Check if we can use PkgConfig 25 | find_package(PkgConfig) 26 | 27 | #Determine from PKG 28 | if( PKG_CONFIG_FOUND AND NOT FFTW_ROOT ) 29 | pkg_check_modules( PKG_FFTW QUIET "fftw3" ) 30 | endif() 31 | 32 | #Check whether to search static or dynamic libs 33 | set( CMAKE_FIND_LIBRARY_SUFFIXES_SAV ${CMAKE_FIND_LIBRARY_SUFFIXES} ) 34 | 35 | if( ${FFTW_USE_STATIC_LIBS} ) 36 | set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} ) 37 | else() 38 | set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX} ) 39 | endif() 40 | 41 | if( FFTW_ROOT ) 42 | 43 | #find libs 44 | find_library( 45 | FFTW_LIB 46 | NAMES "fftw3" 47 | PATHS ${FFTW_ROOT} 48 | PATH_SUFFIXES "lib" "lib64" 49 | NO_DEFAULT_PATH 50 | ) 51 | 52 | find_library( 53 | FFTWF_LIB 54 | NAMES "fftw3f" 55 | PATHS ${FFTW_ROOT} 56 | PATH_SUFFIXES "lib" "lib64" 57 | NO_DEFAULT_PATH 58 | ) 59 | 60 | find_library( 61 | FFTWL_LIB 62 | NAMES "fftw3l" 63 | PATHS ${FFTW_ROOT} 64 | PATH_SUFFIXES "lib" "lib64" 65 | NO_DEFAULT_PATH 66 | ) 67 | 68 | #find includes 69 | find_path( 70 | FFTW_INCLUDES 71 | NAMES "fftw3.h" 72 | PATHS ${FFTW_ROOT} 73 | PATH_SUFFIXES "include" 74 | NO_DEFAULT_PATH 75 | ) 76 | 77 | else() 78 | 79 | find_library( 80 | FFTW_LIB 81 | NAMES "fftw3" 82 | PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} 83 | ) 84 | 85 | find_library( 86 | FFTWF_LIB 87 | NAMES "fftw3f" 88 | PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} 89 | ) 90 | 91 | find_library( 92 | FFTWL_LIB 93 | NAMES "fftw3l" 94 | PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR} 95 | ) 96 | 97 | find_path( 98 | FFTW_INCLUDES 99 | NAMES "fftw3.h" 100 | PATHS ${PKG_FFTW_INCLUDE_DIRS} ${INCLUDE_INSTALL_DIR} 101 | ) 102 | 103 | endif( FFTW_ROOT ) 104 | 105 | set(FFTW_LIBRARIES ${FFTW_LIB}) 106 | 107 | if(FFTWF_LIB) 108 | set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTWF_LIB}) 109 | endif() 110 | 111 | if(FFTWL_LIB) 112 | set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTWL_LIB}) 113 | endif() 114 | 115 | set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV} ) 116 | 117 | include(FindPackageHandleStandardArgs) 118 | find_package_handle_standard_args(FFTW DEFAULT_MSG FFTW_INCLUDES FFTW_LIBRARIES) 119 | 120 | mark_as_advanced(FFTW_INCLUDES FFTW_LIBRARIES) 121 | -------------------------------------------------------------------------------- /cmake/FindGooglePerfTools.cmake: -------------------------------------------------------------------------------- 1 | # -*- cmake -*- 2 | 3 | # - Find Google perftools 4 | # Find the Google perftools includes and libraries 5 | # This module defines 6 | # GOOGLE_PERFTOOLS_INCLUDE_DIR, where to find heap-profiler.h, etc. 7 | # GOOGLE_PERFTOOLS_FOUND, If false, do not try to use Google perftools. 8 | # also defined for general use are 9 | # TCMALLOC_LIBRARIES, where to find the tcmalloc library. 10 | # STACKTRACE_LIBRARIES, where to find the stacktrace library. 11 | # PROFILER_LIBRARIES, where to find the profiler library. 12 | # 13 | # Modified by C. Schreiber to fix finding profiler and stack trace libraries, 14 | # as well as displaying the libraries that were found. 15 | # A patch has been submitted to the original authors: 16 | # http://code.google.com/p/emeraldviewer/issues/detail?id=13&thanks=13&ts=1391277811 17 | 18 | FIND_PATH(GOOGLE_PERFTOOLS_INCLUDE_DIR google/heap-profiler.h 19 | HINTS ${TCMALLOC_ROOT_DIR} PATH_SUFFIXES lib 20 | ) 21 | 22 | SET(TCMALLOC_NAMES ${TCMALLOC_NAMES} tcmalloc) 23 | FIND_LIBRARY(TCMALLOC_LIBRARY 24 | NAMES ${TCMALLOC_NAMES} 25 | HINTS ${TCMALLOC_ROOT_DIR} PATH_SUFFIXES lib 26 | ) 27 | 28 | IF (TCMALLOC_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 29 | SET(TCMALLOC_LIBRARIES ${TCMALLOC_LIBRARY}) 30 | SET(GOOGLE_PERFTOOLS_FOUND "YES") 31 | ELSE (TCMALLOC_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 32 | SET(GOOGLE_PERFTOOLS_FOUND "NO") 33 | ENDIF (TCMALLOC_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 34 | 35 | SET(STACKTRACE_NAMES ${STACKTRACE_NAMES} stacktrace) 36 | FIND_LIBRARY(STACKTRACE_LIBRARY 37 | NAMES ${STACKTRACE_NAMES} 38 | HINTS ${TCMALLOC_ROOT_DIR} PATH_SUFFIXES lib 39 | ) 40 | 41 | IF (STACKTRACE_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 42 | SET(STACKTRACE_LIBRARIES ${STACKTRACE_LIBRARY}) 43 | ENDIF (STACKTRACE_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 44 | 45 | SET(PROFILER_NAMES ${PROFILER_NAMES} profiler) 46 | FIND_LIBRARY(PROFILER_LIBRARY 47 | NAMES ${PROFILER_NAMES} 48 | HINTS ${TCMALLOC_ROOT_DIR} PATH_SUFFIXES lib 49 | ) 50 | 51 | IF (PROFILER_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 52 | SET(PROFILER_LIBRARIES ${PROFILER_LIBRARY}) 53 | ENDIF (PROFILER_LIBRARY AND GOOGLE_PERFTOOLS_INCLUDE_DIR) 54 | 55 | FIND_PROGRAM(PROFILER_BINARY NAMES google-pprof pprof 56 | HINTS ${TCMALLOC_ROOT_DIR} PATH_SUFFIXES bin 57 | ) 58 | 59 | IF (GOOGLE_PERFTOOLS_FOUND) 60 | IF (NOT GOOGLE_PERFTOOLS_FIND_QUIETLY) 61 | MESSAGE(STATUS "Found Google perftools: ${TCMALLOC_LIBRARIES} ${STACKTRACE_LIBRARIES} ${PROFILER_LIBRARIES}") 62 | ENDIF (NOT GOOGLE_PERFTOOLS_FIND_QUIETLY) 63 | ELSE (GOOGLE_PERFTOOLS_FOUND) 64 | IF (GOOGLE_PERFTOOLS_FIND_REQUIRED) 65 | MESSAGE(FATAL_ERROR "Could not find Google perftools library") 66 | ENDIF (GOOGLE_PERFTOOLS_FIND_REQUIRED) 67 | ENDIF (GOOGLE_PERFTOOLS_FOUND) 68 | 69 | MARK_AS_ADVANCED( 70 | TCMALLOC_LIBRARY 71 | STACKTRACE_LIBRARY 72 | PROFILER_LIBRARY 73 | PROFILER_BINARY 74 | GOOGLE_PERFTOOLS_INCLUDE_DIR 75 | ) 76 | -------------------------------------------------------------------------------- /cmake/FindLAPACK.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find LAPACK 2 | # Variables used by this module: 3 | # LAPACK_ROOT_DIR - LAPACK root directory 4 | # Variables defined by this module: 5 | # LAPACK_FOUND - system has LAPACK 6 | # LAPACK_LIBRARY - the LAPACK library (cached) 7 | # LAPACK_LIBRARIES - the LAPACK libraries 8 | 9 | if(NOT LAPACK_FOUND) 10 | 11 | find_library(LAPACK_LIBRARY lapack 12 | HINTS ${LAPACK_ROOT_DIR} PATH_SUFFIXES lib) 13 | mark_as_advanced(LAPACK_INCLUDE_DIR LAPACK_LIBRARY) 14 | 15 | include(FindPackageHandleStandardArgs) 16 | find_package_handle_standard_args(LAPACK DEFAULT_MSG 17 | LAPACK_LIBRARY) 18 | 19 | set(LAPACK_LIBRARIES ${LAPACK_LIBRARY}) 20 | 21 | endif(NOT LAPACK_FOUND) 22 | -------------------------------------------------------------------------------- /cmake/FindLibClang.cmake: -------------------------------------------------------------------------------- 1 | if(NOT DEFINED CLANG_ROOT) 2 | set(CLANG_ROOT $ENV{CLANG_ROOT}) 3 | endif() 4 | 5 | file(GLOB CLANG_INCLUDE_HINTS /usr/lib/llvm-*/include /opt/local/libexec/llvm-*/include) 6 | 7 | find_path(CLANG_INCLUDE clang-c/Index.h 8 | HINTS 9 | ${CLANG_ROOT}/include 10 | ${CLANG_INCLUDE_HINTS} 11 | NO_DEFAULT_PATH) 12 | find_path(CLANG_INCLUDE clang-c/Index.h) 13 | 14 | find_path(CLANG_COMPILATION_INCLUDE clang-c/CXCompilationDatabase.h 15 | HINTS 16 | ${CLANG_ROOT}/include 17 | ${CLANG_INCLUDE_HINTS} 18 | NO_DEFAULT_PATH) 19 | find_path(CLANG_COMPILATION_INCLUDE clang-c/CXCompilationDatabase.h) 20 | 21 | if (EXISTS ${CLANG_INCLUDE}) 22 | if ("${CLANG_ROOT}" STREQUAL "") 23 | string(REGEX REPLACE "\\/include" "" CLANG_ROOT ${CLANG_INCLUDE}) 24 | endif() 25 | endif() 26 | if (EXISTS "${CLANG_ROOT}/lib/libclang.so") 27 | set(CLANG_LIBS "${CLANG_ROOT}/lib/libclang.so") 28 | elseif (EXISTS "${CLANG_ROOT}/lib/libclang.dylib") 29 | set(CLANG_LIBS "${CLANG_ROOT}/lib/libclang.dylib") 30 | else () 31 | find_library(CLANG_LIBS NAMES clang HINTS ${CLANG_ROOT}/lib/ ${CLANG_ROOT}/lib64/llvm/) 32 | endif() 33 | 34 | if (EXISTS ${CLANG_INCLUDE}) 35 | if (EXISTS "${CLANG_INCLUDE}/clang/Basic/Version.inc") 36 | file(READ "${CLANG_INCLUDE}/clang/Basic/Version.inc" CLANG_VERSION_DATA) 37 | string(REGEX REPLACE ";" "\\\\;" CLANG_VERSION_DATA ${CLANG_VERSION_DATA}) 38 | string(REGEX REPLACE "\n" ";" CLANG_VERSION_DATA ${CLANG_VERSION_DATA}) 39 | foreach (line ${CLANG_VERSION_DATA}) 40 | string(REGEX REPLACE "^#define CLANG_VERSION ([0-9]+\\.[0-9]+(\\.[0-9]+)?)$" "\\1" CLANG_VERSION_STRING ${line}) 41 | if (DEFINED CLANG_VERSION_STRING) 42 | string(REGEX REPLACE "^([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" CLANG_VERSION_MAJOR ${CLANG_VERSION_STRING}) 43 | string(REGEX REPLACE "^[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" CLANG_VERSION_MINOR ${CLANG_VERSION_STRING}) 44 | if (${CLANG_VERSION_STRING} MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+") 45 | string(REGEX REPLACE "^[0-9]+\\.[0-9]+(\\.([0-9]+))?" "\\2" CLANG_VERSION_PATCH ${CLANG_VERSION_STRING}) 46 | else () 47 | set(CLANG_VERSION_PATCH "") 48 | endif () 49 | if (NOT ${CLANG_VERSION_MAJOR} STREQUAL "" AND NOT ${CLANG_VERSION_MINOR} STREQUAL "") 50 | if (NOT ${CLANG_VERSION_PATCH} STREQUAL "") 51 | set(CLANG_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCH}") 52 | else () 53 | set(CLANG_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}") 54 | endif () 55 | break() 56 | endif () 57 | endif () 58 | endforeach () 59 | endif () 60 | if ("${CLANG_VERSION}" STREQUAL "") 61 | message(FATAL_ERROR "Unable to parse ClangVersion from ${CLANG_INCLUDE}/clang/Basic/Version.inc") 62 | endif () 63 | 64 | message(STATUS "Using libclang version ${CLANG_VERSION} from ${CLANG_INCLUDE}/clang-c/") 65 | 66 | if (EXISTS "${CLANG_INCLUDE}/clang/${CLANG_VERSION}/include/limits.h") 67 | set(CLANG_SYSTEM_INCLUDE "${CLANG_INCLUDE}/clang/${CLANG_VERSION}/include/") 68 | else () 69 | set(CLANG_SYSTEM_INCLUDE ${CLANG_LIBS}) 70 | string(REGEX REPLACE "\\/libclang\\.[dylibso]+$" "" CLANG_SYSTEM_INCLUDE ${CLANG_SYSTEM_INCLUDE}) 71 | if (EXISTS "${CLANG_SYSTEM_INCLUDE}/clang/${CLANG_VERSION}/include/limits.h") 72 | set(CLANG_SYSTEM_INCLUDE "${CLANG_SYSTEM_INCLUDE}/clang/${CLANG_VERSION}/include/") 73 | else () 74 | set(CLANG_SYSTEM_INCLUDE "") 75 | if (EXISTS "${CLANG_ROOT}/lib/clang/${CLANG_VERSION}/include/limits.h") 76 | set(CLANG_SYSTEM_INCLUDE "${CLANG_ROOT}/lib/clang/${CLANG_VERSION}/include/") 77 | else () 78 | message(FATAL_ERROR "Couldn't find limits.h in either ${CLANG_INCLUDE}/clang/${CLANG_VERSION}/include/ or ${CLANG_SYSTEM_INCLUDE}/clang/${CLANG_VERSION}/include/") 79 | endif () 80 | endif () 81 | endif () 82 | endif() 83 | 84 | include(FindPackageHandleStandardArgs) 85 | find_package_handle_standard_args(CLANG DEFAULT_MSG CLANG_LIBS CLANG_INCLUDE) 86 | 87 | mark_as_advanced(CLANG_INCLUDE CLANG_LIBS) 88 | -------------------------------------------------------------------------------- /cmake/FindLibDwarf.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find libdwarf 2 | # Once done this will define 3 | # 4 | # LIBDWARF_FOUND - system has libdwarf 5 | # LIBDWARF_INCLUDE_DIRS - the libdwarf include directory 6 | # LIBDWARF_LIBRARIES - Link these to use libdwarf 7 | # LIBDWARF_DEFINITIONS - Compiler switches required for using libdwarf 8 | # 9 | 10 | if (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS) 11 | set (LibDwarf_FIND_QUIETLY TRUE) 12 | endif (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS) 13 | 14 | find_path (DWARF_INCLUDE_DIR 15 | NAMES 16 | libdwarf.h dwarf.h 17 | PATHS 18 | /usr/include 19 | /usr/include/libdwarf 20 | /usr/local/include 21 | /usr/local/include/libdwarf 22 | /opt/local/include 23 | /sw/include 24 | ENV CPATH) # PATH and INCLUDE will also work 25 | 26 | if (DWARF_INCLUDE_DIR) 27 | set (LIBDWARF_INCLUDE_DIRS ${DWARF_INCLUDE_DIR}) 28 | endif () 29 | 30 | find_library (LIBDWARF_LIBRARIES 31 | NAMES 32 | dwarf libdwarf 33 | PATHS 34 | /usr/lib 35 | /usr/local/lib 36 | /opt/local/lib 37 | /sw/lib 38 | ENV LIBRARY_PATH # PATH and LIB will also work 39 | ENV LD_LIBRARY_PATH) 40 | include (FindPackageHandleStandardArgs) 41 | 42 | 43 | # handle the QUIETLY and REQUIRED arguments and set LIBDWARF_FOUND to TRUE 44 | # if all listed variables are TRUE 45 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDwarf DEFAULT_MSG 46 | LIBDWARF_LIBRARIES 47 | LIBDWARF_INCLUDE_DIRS) 48 | 49 | if (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS) 50 | set(LIBDWARF_LIBRARIES ${LIBDWARF_LIBRARIES}) 51 | set(LIBDWARF_INCLUDE_DIRS ${LIBDWARF_INCLUDE_DIRS}) 52 | 53 | set(CMAKE_REQUIRED_INCLUDES ${LIBDWARF_INCLUDE_DIRS}) 54 | set(CMAKE_REQUIRED_LIBRARIES ${LIBDWARF_LIBRARIES}) 55 | 56 | # libdwarf makes breaking changes occasionally and doesn't provide an easy 57 | # way to test for them. The following checks should detect the changes and 58 | # pass that information on accordingly. 59 | INCLUDE(CheckCXXSourceCompiles) 60 | INCLUDE(CheckFunctionExists) 61 | 62 | MACRO(CHECK_LIBDWARF_INIT init params var) 63 | # Check for the existence of this particular init function. 64 | unset(INIT_EXISTS CACHE) 65 | CHECK_FUNCTION_EXISTS(${init} INIT_EXISTS) 66 | if (INIT_EXISTS) 67 | set(LIBDWARF_USE_INIT_C ${var}) 68 | 69 | # Check to see if we can use a const name. 70 | unset(DW_CONST CACHE) 71 | 72 | if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 73 | # -std=c++11 is already set in HPHPCompiler.cmake, don't 74 | # add -std=c++0x on top of that or clang will give errors 75 | set(CMAKE_REQUIRED_FLAGS "-std=c++0x") 76 | endif() 77 | 78 | CHECK_CXX_SOURCE_COMPILES(" 79 | #include 80 | #include 81 | int dwarfCallback(const char * a, int b, Dwarf_Unsigned c, 82 | Dwarf_Unsigned d, Dwarf_Unsigned e, Dwarf_Unsigned f, 83 | Dwarf_Unsigned * g, Dwarf_Ptr h, int * i) {} 84 | int main() { ${init}(${params}); return 0; }" DW_CONST) 85 | if (DW_CONST) 86 | set(LIBDWARF_CONST_NAME 1) 87 | else() 88 | set(LIBDWARF_CONST_NAME 0) 89 | endif() 90 | endif() 91 | ENDMACRO(CHECK_LIBDWARF_INIT) 92 | 93 | # Order is important, last one is used. 94 | CHECK_LIBDWARF_INIT("dwarf_producer_init" 95 | "0, dwarfCallback, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr" 0) 96 | CHECK_LIBDWARF_INIT("dwarf_producer_init_c" "0, dwarfCallback, nullptr, nullptr, nullptr, nullptr" 1) 97 | endif() 98 | 99 | if(LIBDWARF_CONST_NAME) 100 | message(STATUS "libdwarf uses const char* type") 101 | else() 102 | message(STATUS "libdwarf uses char* type") 103 | endif() 104 | if(LIBDWARF_USE_INIT_C) 105 | message(STATUS "libdwarf has dwarf_producer_init_c") 106 | else() 107 | message(STATUS "libdwarf does not have dwarf_producer_init_c, using dwarf_producer_init") 108 | endif() 109 | 110 | mark_as_advanced(LIBDW_INCLUDE_DIR DWARF_INCLUDE_DIR) 111 | mark_as_advanced(LIBDWARF_INCLUDE_DIRS LIBDWARF_LIBRARIES) 112 | mark_as_advanced(LIBDWARF_CONST_NAME LIBDWARF_USE_INIT_C) 113 | -------------------------------------------------------------------------------- /cmake/FindLibElf.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find libelf 2 | # Once done this will define 3 | # 4 | # LIBELF_FOUND - system has libelf 5 | # LIBELF_INCLUDE_DIRS - the libelf include directory 6 | # LIBELF_LIBRARIES - Link these to use libelf 7 | # LIBELF_DEFINITIONS - Compiler switches required for using libelf 8 | # 9 | # Copyright (c) 2008 Bernhard Walle 10 | # 11 | # Redistribution and use is allowed according to the terms of the New 12 | # BSD license. 13 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 14 | # 15 | 16 | 17 | if (LIBELF_LIBRARIES AND LIBELF_INCLUDE_DIRS) 18 | set (LibElf_FIND_QUIETLY TRUE) 19 | endif (LIBELF_LIBRARIES AND LIBELF_INCLUDE_DIRS) 20 | 21 | find_path (LIBELF_INCLUDE_DIRS 22 | NAMES 23 | libelf.h 24 | PATHS 25 | /usr/include 26 | /usr/include/libelf 27 | /usr/local/include 28 | /usr/local/include/libelf 29 | /opt/local/include 30 | /opt/local/include/libelf 31 | /sw/include 32 | /sw/include/libelf 33 | ENV CPATH) 34 | 35 | find_library (LIBELF_LIBRARIES 36 | NAMES 37 | elf 38 | PATHS 39 | /usr/lib 40 | /usr/local/lib 41 | /opt/local/lib 42 | /sw/lib 43 | ENV LIBRARY_PATH 44 | ENV LD_LIBRARY_PATH) 45 | 46 | include (FindPackageHandleStandardArgs) 47 | 48 | 49 | # handle the QUIETLY and REQUIRED arguments and set LIBELF_FOUND to TRUE if all listed variables are TRUE 50 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibElf DEFAULT_MSG 51 | LIBELF_LIBRARIES 52 | LIBELF_INCLUDE_DIRS) 53 | 54 | SET(CMAKE_REQUIRED_LIBRARIES elf) 55 | INCLUDE(CheckCXXSourceCompiles) 56 | CHECK_CXX_SOURCE_COMPILES("#include 57 | int main() { 58 | Elf *e = (Elf*)0; 59 | size_t sz; 60 | elf_getshdrstrndx(e, &sz); 61 | return 0; 62 | }" ELF_GETSHDRSTRNDX) 63 | 64 | mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES ELF_GETSHDRSTRNDX) 65 | -------------------------------------------------------------------------------- /cmake/FindLibUnwind.cmake: -------------------------------------------------------------------------------- 1 | # Find the libunwind library 2 | # 3 | # LIBUNWIND_FOUND - True if libunwind was found. 4 | # LIBUNWIND_LIBRARIES - The libraries needed to use libunwind 5 | # LIBUNWIND_INCLUDE_DIR - Location of unwind.h and libunwind.h 6 | 7 | FIND_PATH(LIBUNWIND_INCLUDE_DIR libunwind.h) 8 | if(NOT LIBUNWIND_INCLUDE_DIR) 9 | message(STATUS "failed to find libunwind.h") 10 | elseif(NOT EXISTS "${LIBUNWIND_INCLUDE_DIR}/unwind.h") 11 | message(STATUS "libunwind.h was found, but unwind.h was not found in that directory.") 12 | SET(LIBUNWIND_INCLUDE_DIR "") 13 | endif() 14 | 15 | FIND_LIBRARY(LIBUNWIND_GENERIC_LIBRARY "unwind") 16 | if(NOT LIBUNWIND_GENERIC_LIBRARY) 17 | MESSAGE(STATUS "failed to find unwind generic library") 18 | endif() 19 | SET(LIBUNWIND_LIBRARIES ${LIBUNWIND_GENERIC_LIBRARY}) 20 | 21 | # For some reason, we have to link to two libunwind shared object files: 22 | # one arch-specific and one not. 23 | if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") 24 | SET(LIBUNWIND_ARCH "arm") 25 | elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") 26 | SET(LIBUNWIND_ARCH "x86_64") 27 | elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$") 28 | SET(LIBUNWIND_ARCH "x86") 29 | endif() 30 | 31 | if(LIBUNWIND_ARCH) 32 | FIND_LIBRARY(LIBUNWIND_SPECIFIC_LIBRARY "unwind-${LIBUNWIND_ARCH}") 33 | if (NOT LIBUNWIND_SPECIFIC_LIBRARY) 34 | MESSAGE(STATUS "failed to find unwind-${LIBUNWIND_ARCH}") 35 | endif() 36 | SET(LIBUNWIND_LIBRARIES ${LIBUNWIND_LIBRARIES} ${LIBUNWIND_SPECIFIC_LIBRARY}) 37 | endif(LIBUNWIND_ARCH) 38 | 39 | MARK_AS_ADVANCED(LIBUNWIND_LIBRARIES LIBUNWIND_INCLUDE_DIR) 40 | 41 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUnwind DEFAULT_MSG 42 | LIBUNWIND_LIBRARIES LIBUNWIND_INCLUDE_DIR) 43 | -------------------------------------------------------------------------------- /cmake/FindWCSLib.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find WCSLIB: the FITS "World Coordinate System" library 2 | # Variables used by this module: 3 | # WCSLIB_ROOT_DIR - WCSLIB root directory 4 | # Variables defined by this module: 5 | # WCSLIB_FOUND - system has WCSLIB 6 | # WCSLIB_INCLUDE_DIR - the WCSLIB include directory (cached) 7 | # WCSLIB_INCLUDE_DIRS - the WCSLIB include directories 8 | # (identical to WCSLIB_INCLUDE_DIR) 9 | # WCSLIB_LIBRARY - the WCSLIB library (cached) 10 | # WCSLIB_LIBRARIES - the WCSLIB libraries 11 | # (identical to WCSLIB_LIBRARY) 12 | 13 | # Copyright (C) 2009 14 | # ASTRON (Netherlands Institute for Radio Astronomy) 15 | # P.O.Box 2, 7990 AA Dwingeloo, The Netherlands 16 | # 17 | # This file is part of the LOFAR software suite. 18 | # The LOFAR software suite is free software: you can redistribute it and/or 19 | # modify it under the terms of the GNU General Public License as published 20 | # by the Free Software Foundation, either version 3 of the License, or 21 | # (at your option) any later version. 22 | # 23 | # The LOFAR software suite is distributed in the hope that it will be useful, 24 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | # GNU General Public License for more details. 27 | # 28 | # You should have received a copy of the GNU General Public License along 29 | # with the LOFAR software suite. If not, see . 30 | # 31 | # $Id$ 32 | 33 | if(NOT WCSLIB_FOUND) 34 | 35 | find_path(WCSLIB_INCLUDE_DIR wcslib/wcs.h 36 | HINTS ${WCSLIB_ROOT_DIR} PATH_SUFFIXES include) 37 | find_library(WCSLIB_LIBRARY wcs 38 | HINTS ${WCSLIB_ROOT_DIR} PATH_SUFFIXES lib) 39 | find_library(M_LIBRARY m) 40 | 41 | if(EXISTS ${WCSLIB_INCLUDE_DIR}) 42 | file(STRINGS "${WCSLIB_INCLUDE_DIR}/wcslib/wcsconfig.h" TLINE 43 | REGEX "^#[\t ]*define[\t ]+WCSLIB_VERSION[\t ]+[0-9.]+$") 44 | 45 | string(REGEX REPLACE "^#[\t ]*define[\t ]+WCSLIB_VERSION[\t ]+([0-9.]+)$" "\\1" 46 | WCSLIB_VERSION_STRING "${TLINE}") 47 | 48 | if(NOT "${WCSLIB_VERSION_STRING}" STREQUAL "") 49 | message(STATUS "Found WCSLIB version ${WCSLIB_VERSION_STRING}") 50 | endif() 51 | endif() 52 | 53 | mark_as_advanced(WCSLIB_INCLUDE_DIR WCSLIB_LIBRARY WCSLIB_VERSION_STRING M_LIBRARY) 54 | 55 | include(FindPackageHandleStandardArgs) 56 | find_package_handle_standard_args(WCSLIB DEFAULT_MSG 57 | WCSLIB_LIBRARY M_LIBRARY WCSLIB_INCLUDE_DIR WCSLIB_VERSION_STRING) 58 | 59 | set(WCSLIB_INCLUDE_DIRS ${WCSLIB_INCLUDE_DIR}) 60 | set(WCSLIB_LIBRARIES ${WCSLIB_LIBRARY} ${M_LIBRARY}) 61 | 62 | endif(NOT WCSLIB_FOUND) 63 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | _minted-phypp 2 | *.aux 3 | *.log 4 | *.out 5 | *.toc 6 | *.idx 7 | *.ilg 8 | *.ind 9 | -------------------------------------------------------------------------------- /doc/2html/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Define output options 4 | OUT_DIR=../html/ 5 | 6 | # Initialize 7 | mkdir -p $OUT_DIR 8 | cp pygments.css $OUT_DIR/pygments.css 9 | cp section-link.png $OUT_DIR/section-link.png 10 | cp vectorized.png $OUT_DIR/vectorized.png 11 | 12 | # Parse LaTeX files and build HTML 13 | for f in ../latex/category_*.tex; do 14 | ophy++ 2html_category $f out_dir=$OUT_DIR 15 | done 16 | 17 | for f in ../latex/functions_*.tex; do 18 | ophy++ 2html_functions $f out_dir=$OUT_DIR 19 | done 20 | 21 | # Compile all parsing into the menu 22 | ophy++ make_index $OUT_DIR 23 | 24 | # Rebuild HTML to integrate new menu 25 | for f in ../latex/category_*.tex; do 26 | ophy++ 2html_category $f out_dir=$OUT_DIR 27 | done 28 | 29 | for f in ../latex/functions_*.tex; do 30 | ophy++ 2html_functions $f out_dir=$OUT_DIR 31 | done 32 | -------------------------------------------------------------------------------- /doc/2html/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /doc/2html/footer.tex: -------------------------------------------------------------------------------- 1 | \begin{document} 2 | \setbox0\hbox{\formula} 3 | \begin{preview} 4 | \formula 5 | \end{preview} 6 | \newwrite\outputstream 7 | \immediate\openout\outputstream=tmp.dat 8 | \immediate\write\outputstream{box_height=\the\ht0,box_depth=\the\dp0,box_width=\the\wd0} 9 | \immediate\closeout\outputstream 10 | \end{document} 11 | -------------------------------------------------------------------------------- /doc/2html/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | phy++ API 7 | 8 | 9 | 10 | 11 | 12 |
13 | phy++ documentation 14 |
15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /doc/2html/header.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \pagestyle{empty} 3 | \usepackage[utf8]{inputenc} 4 | % \usepackage{lmodern} 5 | \usepackage{amssymb} 6 | \usepackage[active]{preview} 7 | -------------------------------------------------------------------------------- /doc/2html/make_index.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "common.hpp" 3 | 4 | int phypp_main(int argc, char* argv[]) { 5 | std::string out_dir = file::directorize(argv[1]); 6 | 7 | sorted_cache_t funindex; 8 | for (auto& f : file::list_files(out_dir+"cache/functions*_index.cache")) { 9 | read_cache(funindex, out_dir+"cache/"+f); 10 | } 11 | 12 | std::vector catindex; 13 | vec1s catfiles = file::list_files(out_dir+"cache/category*_index.cache"); 14 | inplace_sort(catfiles); 15 | for (auto& f : catfiles) { 16 | cache_t tmp; 17 | read_cache(tmp, out_dir+"cache/"+f); 18 | catindex.push_back(std::move(tmp)); 19 | } 20 | 21 | print("found ", funindex.size(), " functions"); 22 | print("found ", catindex.size(), " categories"); 23 | 24 | std::string header = file::to_string("header.html"); 25 | std::string footer = file::to_string("footer.html"); 26 | 27 | std::ofstream out(out_dir+"menu-left.js"); 28 | 29 | out << "document.write('\\\n"; 30 | out << "
    \\\n"; 31 | out << "
  • Categories

    \\\n"; 32 | out << "
      \\\n"; 33 | for (auto& c : catindex) { 34 | if (c.empty()) continue; 35 | 36 | bool first = true; 37 | for (auto& i : c) { 38 | std::string tit, link; 39 | link = replace_block(i.value, "__(", ")__", [&](std::string s) { 40 | tit = s; 41 | return ""; 42 | }); 43 | 44 | if (c.size() != 1) { 45 | if (first) { 46 | out << "
    • "+tit+" \\\n"; 47 | out << "
        \\\n"; 48 | } else { 49 | out << "
      • "+tit+"
      • \\\n"; 50 | } 51 | } else { 52 | out << "
      • "+tit+"
      • \\\n"; 53 | } 54 | 55 | first = false; 56 | } 57 | 58 | if (c.size() != 1) { 59 | out << "
    • \\\n"; 60 | } 61 | } 62 | 63 | out << "
  • \\\n"; 64 | out << "
\\\n"; 65 | out << "');"; 66 | 67 | out.close(); 68 | out.open(out_dir+"menu-right.js"); 69 | 70 | out << "document.write('\\\n"; 71 | out << "
    \\\n"; 72 | out << "
  • Alphabetical list

    \\\n"; 73 | out << "
      \\\n"; 74 | char last = '\0'; 75 | for (auto& kv : funindex) { 76 | if (kv.first[0] != last) { 77 | if (last != '\0') { 78 | out << "

  • \\\n"; 79 | } 80 | 81 | out << "
  • "+toupper(kv.first).substr(0,1)+"
    \\\n"; 82 | out << "
      \\\n"; 83 | 84 | last = kv.first[0]; 85 | } 86 | 87 | out << "
    • "+kv.first+"
    • \\\n"; 88 | } 89 | 90 | out << "
  • \\\n"; 91 | out << "
\\\n"; 92 | out << " \\\n"; 93 | out << "');"; 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /doc/2html/section-link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/doc/2html/section-link.png -------------------------------------------------------------------------------- /doc/2html/vectorized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/doc/2html/vectorized.png -------------------------------------------------------------------------------- /doc/latex/category_support_02_generic.tex: -------------------------------------------------------------------------------- 1 | \section{Generic vector functions \label{SEC:support:generic}} 2 | 3 | The vector and view classes are useful and complete tools. However, there are a number of tasks that one repeatedly need to do, like generating a sequence of indices, or sorting a vector, and that would be tedious to write each time they are needed. For this reason, the \phypp library comes with a large set of utility functions to sort, rearrange, and select data inside vectors. In this section we list these functions and algorithms. 4 | 5 | This support library also introduces a global constant called \cppinline{npos}\itt{npos}. This is an unsigned integer whose value is the largest possible integer that the \cppinline{uint_t} type can hold. It is meant to be used as an error value, or the value to return if no normal value would make sense. It is very similar in concept to the \cppinline{std::string::npos} provided by the C++ standard library. In particular, it is worth noting that converting \cppinline{npos} to a \emph{signed} integer produces the value \cppinline{-1}. 6 | 7 | We now describe the functions provided by this library, sorted by categories. 8 | 9 | \subsection{Range-based iteration \label{SEC:support:generic:range}} 10 | 11 | \loadfunctions{functions_support_generic_range.tex} 12 | 13 | \subsection{Index manipulation \label{SEC:support:generic:index}} 14 | 15 | \loadfunctions{functions_support_generic_index.tex} 16 | 17 | \subsection{Integer sequences \label{SEC:support:generic:sequence}} 18 | 19 | \loadfunctions{functions_support_generic_sequence.tex} 20 | 21 | \subsection{Rearranging elements \label{SEC:support:generic:rearrange}} 22 | 23 | \loadfunctions{functions_support_generic_rearrange.tex} 24 | 25 | \subsection{Finding elements \label{SEC:support:generic:find}} 26 | 27 | \loadfunctions{functions_support_generic_find.tex} 28 | 29 | \subsection{Modifying dimensions \label{SEC:support:generic:dims}} 30 | 31 | \loadfunctions{functions_support_generic_dim.tex} 32 | 33 | \subsection{Error checking \label{SEC:support:generic:error}} 34 | 35 | \loadfunctions{functions_support_generic_error.tex} 36 | 37 | \subsection{Vectorization \label{SEC:support:generic:vectorization}} 38 | 39 | \loadfunctions{functions_support_generic_vectorize.tex} 40 | -------------------------------------------------------------------------------- /doc/latex/category_support_03_cmd.tex: -------------------------------------------------------------------------------- 1 | \section{Parsing command line arguments \label{SEC:support:cmd}} 2 | 3 | \loadfunctions{functions_support_cmd.tex} 4 | -------------------------------------------------------------------------------- /doc/latex/category_support_04_string.tex: -------------------------------------------------------------------------------- 1 | \section{String manipulation \label{SEC:support:string}} 2 | 3 | \subsection{String conversions \label{SEC:support:string:convert}} 4 | 5 | \loadfunctions{functions_support_string_convert.tex} 6 | 7 | \subsection{String operations \label{SEC:support:string:modify}} 8 | 9 | \loadfunctions{functions_support_string_modify.tex} 10 | -------------------------------------------------------------------------------- /doc/latex/category_support_05_os.tex: -------------------------------------------------------------------------------- 1 | \section{OS interaction \label{SEC:support:os}} 2 | 3 | \loadfunctions{functions_support_os.tex} 4 | -------------------------------------------------------------------------------- /doc/latex/category_support_06_file.tex: -------------------------------------------------------------------------------- 1 | \section{File input/output \label{SEC:support:file}} 2 | 3 | \subsection{File system \label{SEC:support:file:system}} 4 | 5 | This section describes the function provided by the \phypp library that are related to file system management, i.e., getting informations, creating or copying files and directories. All paths can be either absolute, or relative to the working directory. 6 | 7 | \loadfunctions{functions_support_file_system.tex} 8 | 9 | \subsection{ASCII table input/output \label{SEC:support:file:ascii}} 10 | 11 | \loadfunctions{functions_support_file_ascii.tex} 12 | -------------------------------------------------------------------------------- /doc/latex/category_support_07_print.tex: -------------------------------------------------------------------------------- 1 | \section{Printing to the terminal \label{SEC:support:print}} 2 | 3 | \loadfunctions{functions_support_print.tex} 4 | -------------------------------------------------------------------------------- /doc/latex/category_support_08_time.tex: -------------------------------------------------------------------------------- 1 | \section{Measuring time \label{SEC:support:time}} 2 | 3 | \loadfunctions{functions_support_time.tex} 4 | -------------------------------------------------------------------------------- /doc/latex/category_support_10_thread.tex: -------------------------------------------------------------------------------- 1 | \section{Parallel execution \label{SEC:support:thread}} 2 | 3 | \loadfunctions{functions_support_thread.tex} 4 | -------------------------------------------------------------------------------- /doc/latex/category_support_11_fits.tex: -------------------------------------------------------------------------------- 1 | \section{FITS input/output \label{SEC:support:fits}} 2 | 3 | The FITS (Flexible Image Transport System) format is a general purpose file format developed for astrophysics data. In particular, FITS files can store images with floating point pixel values, image cubes, but also binary data tables with an arbitrary number of columns and rows. Using a meta-data system (FITS keywords), FITS files usually carry a number of important additional informations about their content. E.g., for images files, the mapping between image pixels and sky coordinates (WCS coordinates), or the physical unit of the pixel values. 4 | 5 | Storying data tables in binary inside FITS files is a space-efficient and fast way to store and read non-image data. FITS tables come in two fashions: row-oriented and column-oriented tables. In row-oriented tables, all the data about one row (e.g., about one galaxy in the table) is stored contiguously on disk. This means that it is very fast to retrieve all the information about a given object. In column-oriented tables however, a whole column is stored contiguously in memory. This means that it is very fast to read a given column for all the objects in the table. Due to the way the \phypp library is designed, it is more efficient to use the latter format, since a given column of the file will be represented by a single \phypp vector. It also brings the nice advantage of allowing to store columns of different lengths, e.g.~to combine two tables in the same file, or to carry meta-data that would be hard to store in the standard FITS keywords. The column-oriented format is not well known, but most softwares and libraries do support it\footnote{Topcat does. In IDL, column-oriented FITS files are supported by the \cppinline{mrdfits} and \cppinline{mwrfits} procedures.}. 6 | 7 | Finally, note that this support library introduces a new type: \cppinline{fits::header} (that we will shorten to \cppinline{header} in the following). This type is used to store the header of any FITS file. For now, it is actually just a raw \cppinline{std::string}, but that might change in the future. 8 | 9 | We now describe the various functions offered by this library, split into categories. 10 | 11 | \subsection{Generic header functions \label{SEC:support:fits:header}} 12 | 13 | \loadfunctions{functions_support_fits_header.tex} 14 | 15 | \subsection{FITS images input/output \label{SEC:support:fits:image}} 16 | 17 | \loadfunctions{functions_support_fits_image.tex} 18 | 19 | \subsection{WCS coordinates \label{SEC:support:fits:wcs}} 20 | 21 | \loadfunctions{functions_support_fits_wcs.tex} 22 | 23 | \subsection{FITS tables input/output \label{SEC:support:fits:table}} 24 | 25 | \loadfunctions{functions_support_fits_table.tex} 26 | -------------------------------------------------------------------------------- /doc/latex/category_support_12_image.tex: -------------------------------------------------------------------------------- 1 | \section{Image processing \label{SEC:support:image}} 2 | 3 | \loadfunctions{functions_support_image.tex} 4 | -------------------------------------------------------------------------------- /doc/latex/category_support_13_astro.tex: -------------------------------------------------------------------------------- 1 | \section{Astrophysics \label{SEC:support:astro}} 2 | 3 | \subsection{PSF fitting \label{SEC:support:astro:psffit}} 4 | 5 | \loadfunctions{functions_support_astro_psffit.tex} 6 | 7 | \subsection{Cosmology \label{SEC:support:astro:cosmo}} 8 | 9 | \loadfunctions{functions_support_astro_cosmo.tex} 10 | 11 | \subsection{Fluxes, magnitudes and luminosities \label{SEC:support:astro:flux}} 12 | 13 | \loadfunctions{functions_support_astro_flux.tex} 14 | 15 | \subsection{Sky coordinates \label{SEC:support:astro:sky}} 16 | 17 | \loadfunctions{functions_support_astro_sky.tex} 18 | 19 | \subsection{Catalog management \label{SEC:support:astro:cat}} 20 | 21 | \loadfunctions{functions_support_astro_catalog.tex} 22 | 23 | \subsection{Image stacking \label{SEC:support:astro:stack}} 24 | 25 | \loadfunctions{functions_support_astro_stack.tex} 26 | 27 | \subsection{Template fitting \label{SEC:support:astro:sedfit}} 28 | 29 | \loadfunctions{functions_support_astro_sedfit.tex} 30 | -------------------------------------------------------------------------------- /doc/latex/compile.sh: -------------------------------------------------------------------------------- 1 | pdflatex -shell-escape phypp 2 | makeindex phypp 3 | pdflatex -shell-escape phypp 4 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_catalog.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|bool get_band(auto cat, string band, uint_t& b)| \itt{get_band} 2 | 3 | \cppinline|bool get_band(auto cat, string band, note, uint_t& b)| \itt{get_band} 4 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_cosmo.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|auto get_cosmo()| \itt{get_cosmo} 2 | 3 | \cppinline|vec1s cosmo_list()| \itt{cosmo_list} 4 | 5 | \cppinline|auto cosmo_wmap()| \itt{cosmo_wmap} 6 | 7 | \cppinline|auto cosmo_plank()| \itt{cosmo_plank} 8 | 9 | \cppinline|auto cosmo_std()| \itt{cosmo_std} 10 | 11 | \funcitem \vectorfunc \cppinline|T lumdist(T z, auto cosmo)| \itt{lumdist} 12 | 13 | \funcitem \vectorfunc \cppinline|T lookback_time(T z, auto cosmo)| \itt{lookback_time} 14 | 15 | \funcitem \vectorfunc \cppinline|T vuniverse(T z, auto cosmo)| \itt{vuniverse} 16 | 17 | \funcitem \vectorfunc \cppinline|T propsize (T z, auto cosmo)| \itt{propsize} 18 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_flux.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|T lsun2uJy(T z, d, lam, lum)| \itt{lsun2uJy} 2 | 3 | \cppinline|T uJy2lsun(T z, d, lam, lum)| \itt{uJy2lsun} 4 | 5 | \funcitem \cppinline|T cgs2uJy(T lam, lum)| \itt{cgs2uJy} 6 | 7 | \cppinline|T uJy2cgs(T lam, lum)| \itt{uJy2cgs} 8 | 9 | \funcitem \cppinline|T lsun2mag(T lam, lum, double zp = 23.9)| \itt{lsun2mag} 10 | 11 | \cppinline|T mag2lsun(T lam, lum, double zp = 23.9)| \itt{mag2lsun} 12 | 13 | \funcitem \cppinline|T uJy2mag(T flx, double zp = 23.9)| \itt{uJy2mag} 14 | 15 | \cppinline|T mag2uJy(T mag, double zp = 23.9)| \itt{mag2uJy} 16 | 17 | \funcitem \cppinline|auto read_filter_db(string)| \itt{read_filter_db} 18 | 19 | \funcitem \cppinline|bool get_filter(auto db, string name, filter_t& f)| \itt{get_filter} 20 | 21 | \cppinline|bool get_filters(auto db, vec1s names, filter_bank_t& fb)| \itt{get_filters} 22 | 23 | \funcitem \cppinline|auto read_filter_map(string)| \itt{read_filter_map} 24 | 25 | \funcitem \cppinline|bool get_filter_id(auto map, string name, uint_t& i)| \itt{get_filter_id} 26 | 27 | \cppinline|bool get_filter_id(auto db, vec1s names, vec1u& i)| 28 | 29 | \funcitem \cppinline|double sed2flux(auto fil, vec<1,T> lam, sed)| \itt{sed2flux} 30 | 31 | \cppinline|vec1d sed2flux(auto fil, vec<2,T> lam, sed)| 32 | 33 | \funcitem \cppinline|double sed_convert(auto from, to, double z, d, vec<1,T> lam, sed)| \itt{sed_convert} 34 | 35 | \funcitem \cppinline|double lir_8_1000(vec<1,T> lam, sed)| \itt{lir_8_1000} 36 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_psffit.tex: -------------------------------------------------------------------------------- 1 | \funcitem \itt{make_psf}\begin{cppcode} 2 | bool make_psf(array {w, h}, double x0, y0, 3 | string model, vec2d& psf) 4 | \end{cppcode} 5 | 6 | \funcitem \cppinline|auto psffit(vec<2,T> m, e, psf, vec1i pos)| \itt{psffit} 7 | 8 | \cppinline|auto psffit(vec<2,T> m, e, psf)| 9 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_sedfit.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec2d template_observed(auto lib, double z, d, auto filters)| \itt{template_observed} 2 | 3 | \cppinline|vec2d template_observed(auto lib, vec1d z, d, auto filters)| 4 | 5 | \funcitem \vectorfunc \cppinline|double limweight(double)| \itt{limweight} 6 | 7 | \funcitem \itt{template_fit} \begin{cppcode} 8 | auto template_fit(auto lib, auto seed, T z, d, vec1d flux, err, 9 | auto filters, auto options = default) 10 | \end{cppcode} 11 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_sky.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|double field_area_hull(vec1u hull, vec ra, dec)| \itt{field_area_hull} 2 | 3 | \cppinline|double field_area_hull(vec ra, dec)| 4 | 5 | \funcitem \cppinline|double field_area_h2d(vec ra, dec)| \itt{field_area_h2d} 6 | 7 | \funcitem \cppinline|double field_area(vec ra, dec)| \itt{field_area} 8 | 9 | \funcitem \cppinline|vec1d angcorrel(vec ra, dec, vec rra, rdec, vec<2,V> b)| \itt{angcorrel} 10 | 11 | \funcitem \itt{randpos_uniform} \begin{cppcode} 12 | auto randpos_uniform(auto seed, vec1d rra, rdec, F in, 13 | vec& ra, dec, auto options = default) 14 | \end{cppcode} 15 | 16 | \funcitem \itt{randpos_power_circle} \begin{cppcode} 17 | auto randpos_power_circle(auto seed, double ra0, dec0, r0, 18 | vec& ra, dec, auto options = default) 19 | \end{cppcode} 20 | 21 | \funcitem \itt{randpos_power} \begin{cppcode} 22 | auto randpos_power(auto seed, vec1u h, vec hra, hdec, 23 | vec& ra, dec, auto options = default) 24 | \end{cppcode} 25 | 26 | \funcitem \vectorfunc \cppinline|bool sex2deg(string sra, sdec, T& ra, dec)| \itt{sex2deg} 27 | 28 | \vectorfunc \cppinline|void deg2sex(T ra, dec, string& sra, sdec)| \itt{deg2sex} 29 | 30 | \funcitem \itt{qxmatch} \begin{cppcode} 31 | auto qxmatch(vec<1,T> ra1, dec1, ra2, dec2, 32 | auto options = default) 33 | \end{cppcode} 34 | 35 | \funcitem \cppinline|vec2d qdist(vec<1,T> ra, dec, auto options = default)| \itt{qdist} 36 | 37 | \funcitem \vectorfunc \cppinline|double angdistr(double ra1, dec1, ra2, dec2)| \itt{angdistr} 38 | 39 | \vectorfunc \cppinline|double angdist(double ra1, dec1, ra2, dec2)| \itt{angdist} 40 | 41 | \funcitem \cppinline|vec angdist_less(vec ra1, dec1, double ra2, dec2)| \itt{angdist_less} 42 | 43 | \funcitem \cppinline|void move_ra_dec(double& ra, dec, double dra, ddec)| \itt{move_ra_dec} 44 | 45 | \cppinline|void move_ra_dec(vec& ra, dec, double dra, ddec)| 46 | 47 | \funcitem \cppinline|void normalize_coordinates(T& ra, dec)| \itt{normalize_coordinates} 48 | 49 | \funcitem \cppinline|double vernal_angle(double ra, dec)| \itt{vernal_angle} 50 | 51 | \funcitem \cppinline|void angrot_vernal(T ra, dec, double e, U& ora, odec)| \itt{angrot_vernal} 52 | 53 | -------------------------------------------------------------------------------- /doc/latex/functions_support_astro_stack.tex: -------------------------------------------------------------------------------- 1 | \funcitem \itt{pick_sources} \begin{cppcode} 2 | bool pick_sources(vec<2,T> m, vec1d x, y, uint_t hs, 3 | vec<3,T>& c, vec1u& ids) 4 | \end{cppcode} 5 | 6 | \funcitem \itt{qstack} \begin{cppcode} 7 | auto qstack(vec<1,T> ra, dec, string ff, uint_t hs, vec<3,T>& fc, 8 | vec1u& i, auto options = default) 9 | \end{cppcode} 10 | 11 | \begin{cppcode} 12 | auto qstack(vec<1,T> ra, dec, string ff, fw, uint_t hs, 13 | vec<3,T>& fc, wc, vec1u& i, auto options = default) 14 | \end{cppcode} 15 | 16 | \funcitem \cppinline|auto qstack_mean(vec<3,T> fc)| \itt{qstack_mean} 17 | 18 | \cppinline|auto qstack_mean(vec<3,T> fc, wc)| 19 | 20 | \funcitem \cppinline|auto qstack_median(vec<3,T> fc)| \itt{qstack_median} 21 | 22 | \funcitem \cppinline|void qstack_bootstrap(vec<3,T> fc, uint_t nb, ns, auto seed, F f)| \itt{qstack_bootstrap} 23 | 24 | \cppinline|void qstack_bootstrap(vec<3,T> fc, wc, uint_t nb, ns, auto seed, F f)| 25 | 26 | \cppinline|void qstack_bootstrap(uint_t nb, ns, auto seed, F f, ...)| 27 | 28 | \funcitem \cppinline|vec<3,T> qstack_mean_bootstrap(vec<3,T> fc, uint_t nb, ns, auto seed)| \itt{qstack_mean_bootstrap} 29 | 30 | \cppinline|vec<3,T> qstack_mean_bootstrap(vec<3,T> fc, wc, uint_t nb, ns, auto seed)| 31 | 32 | \funcitem \cppinline|vec<3,T> qstack_median_bootstrap(vec<3,T> fc, uint_t nb, ns, auto seed)| \itt{qstack_median_bootstrap} 33 | -------------------------------------------------------------------------------- /doc/latex/functions_support_fits_header.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|header fits::read_header(string f)| \itt{fits::read_header} 2 | 3 | \cppinline|header fits::read_header_hdu(string f, uint_t hdu)| 4 | 5 | \cppinline|header fits::read_header_sectfits(string f, uint_t s)| 6 | 7 | \funcitem \cppinline|bool fits::getkey(header hdr, string k, T& v)| \itt{fits::getkey} 8 | 9 | \funcitem \cppinline|bool fits::setkey(header hdr, string k, T& v, string c = "")| \itt{fits::setkey} 10 | -------------------------------------------------------------------------------- /doc/latex/functions_support_fits_image.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|uint_t fits::file_axes(string)| \itt{fits::file_axes} 2 | 3 | \funcitem \cppinline|vec1u fits::file_dimensions(string)| \itt{fits::file_dimensions} 4 | 5 | \funcitem \cppinline|bool fits::is_cube(string)| \itt{fits::is_cube} 6 | 7 | \funcitem \cppinline|bool fits::is_image(string)| \itt{fits::is_image} 8 | 9 | \funcitem \cppinline|void fits::read(string f, vec& v)| \itt{fits::read} 10 | 11 | \cppinline|void fits::read(string f, vec& v, header& hdr)| 12 | 13 | \cppinline|void fits::read_hdu(string f, vec& v, uint_t hdu)| \itt{fits::read_hdu} 14 | 15 | \cppinline|void fits::read_hdu(string f, vec& v, uint_t hdu, header& hdr)| 16 | 17 | \funcitem \cppinline|vec1s fits::read_sectfits(string f)| \itt{fits::read_sectfits} 18 | 19 | \funcitem \cppinline|void fits::write(string f, vec v)| \itt{fits::write} 20 | 21 | \cppinline|void fits::write(string f, vec v, header hdr)| 22 | 23 | \funcitem \cppinline|void fits::update_hdu(string f, vec v, uint_t hdu)| \itt{fits::update_hdu} 24 | 25 | \funcitem \cppinline|void fits::display(string f)| \itt{fits::display} 26 | 27 | \cppinline|void fits::display(string r, string g)| 28 | 29 | \cppinline|void fits::display(string r, string g, string b)| 30 | -------------------------------------------------------------------------------- /doc/latex/functions_support_fits_table.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec<1,auto> fits::read_table_columns(string)| \itt{fits::read_table_columns} 2 | 3 | \funcitem \cppinline|void fits::read_table(string f, ...)| \itt{fits::read_table} 4 | 5 | \cppinline|void fits::read_table_loose(string f, ...)| \itt{fits::read_table_loose} 6 | 7 | \funcitem \cppinline|void fits::write_table(string f, ...)| \itt{fits::write_table} 8 | 9 | \cppinline|void fits::update_table(string f, ...)| \itt{fits::update_table} 10 | -------------------------------------------------------------------------------- /doc/latex/functions_support_fits_wcs.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|bool fits::make_wcs_header(auto p, header& hdr)| \itt{fits::make_wcs_header} 2 | 3 | \cppinline|bool fits::make_wcs_header(vec1s p, header& hdr)| 4 | 5 | \funcitem \cppinline|header fits::filter_wcs(header)| \itt{fits::filter_wcs} 6 | 7 | \funcitem \cppinline|auto fits::extast(header)| \itt{fits::extast} 8 | 9 | \funcitem \cppinline|void fits::ad2xy(auto wcs, vec ra, dec, vec& x, y)| \itt{fits::ad2xy} 10 | 11 | \cppinline|void fits::xy2ad(auto wcs, vec ra, dec, vec& x, y)| \itt{fits::xy2ad} 12 | 13 | \funcitem \cppinline|bool fits::get_pixel_size(string file, double& a)| \itt{fits::get_pixel_size} 14 | -------------------------------------------------------------------------------- /doc/latex/functions_support_generic_error.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|void phypp_check(bool b, ...)| \itt{phypp_check} 2 | 3 | This function makes error checking easier. When called, it checks the value of \cppinline{b}. If \cppinline{b} is \cpptrue, then nothing happens. However if \cppinline{b} is \cppfalse, then the current file and line are printed to the standard output, followed by the other arguments of this function (they are supposed to compose an error message explaining what went wrong), and the program is immediately stopped. This function is used everywhere in the \phypp library to make sure that certain conditions are properly satisfied before doing a calculation, and it is essential to make the program crash in case something is unexpected (rather than letting it run hoping for the best, and often getting the worst). 4 | 5 | Since this function is actually implemented by a preprocessor macro, you should not worry about its performance impact. It will only affect the performances when something goes wrong and the program is about to crash. However the calculation of \cppinline{b} can itself be costly (for example, you may want to check that a vector is sorted), and there is no way around this. 6 | 7 | In addition, and if you have configured the \phypp library adequately, this function can print the ``backtrace'' of the program that lead to the error. This backtrace tells you which functions (or lines of code) the program was executing when the error occured. This information can be very useful to identify the source of the problem, but is only available if debugging informations are stored inside the compiled program. Note that this only affects the size of the executable on disk: debugging informations do not alter performances. If you need to solve complex problems, the backtrace may not be sufficient and you may need to use your favorite debugger. 8 | 9 | \begin{example} 10 | \begin{cppcode} 11 | vec1i v; 12 | // Suppose 'v' is read from the command line arguments. 13 | v = read_from_somewhere_unsafe(); 14 | 15 | // The rest of the code needs at least 3 elements in the 16 | // vector 'v', so we need to check that first. 17 | phypp_check(v.size() >= 3, "this algorithm needs at least " 18 | "3 values in the input vector, but only ", v.size(), 19 | " were found"); 20 | 21 | // If we get past this point, we can proceed safely to use 22 | // the first three elements 23 | print(v[0]+v[1]+v[3]); 24 | \end{cppcode} 25 | \end{example} 26 | -------------------------------------------------------------------------------- /doc/latex/functions_support_generic_index.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec1u mult_ids(vec v, uint_t i)| \itt{mult_ids} 2 | 3 | \cppinline|vec1u mult_ids(array dims, uint_t i)| 4 | 5 | This is only useful for multidimensional vectors. This function converts a ``flat'' index \cppinline{i} (\ref{SEC:core:vec:indexing}) into an array of multidimensional indices, following the dimensions of the provided vector \cppinline{v} (or, in the second version, following the dimensions \cppinline{dims}). The \cppinline{flat_id} function does the inverse job. 6 | 7 | \begin{example} 8 | \begin{cppcode} 9 | vec2i v(2,3); 10 | mult_ids(v,0); // {0,0} 11 | mult_ids(v,1); // {0,1} 12 | mult_ids(v,2); // {0,3} 13 | mult_ids(v,3); // {1,0} 14 | v[3] == v(1,0); // true 15 | \end{cppcode} 16 | \end{example} 17 | 18 | \funcitem \cppinline|uint_t flat_id(vec v, ...)| \itt{flat_id} 19 | 20 | This is only useful for multidimensional vectors. This function converts a group of multidimensional indices into a ``flat'' index (\ref{SEC:core:vec:indexing}), following the dimensions of the provided vector \cppinline{v}. The \cppinline{mult_ids} function does the inverse job. 21 | 22 | \begin{example} 23 | \begin{cppcode} 24 | vec2i v(2,3); 25 | flat_id(v,0,0); // 0 26 | flat_id(v,0,1); // 1 27 | flat_id(v,0,2); // 2 28 | flat_id(v,1,0); // 3 29 | v(1,0) == v[3]; // true 30 | \end{cppcode} 31 | \end{example} 32 | -------------------------------------------------------------------------------- /doc/latex/functions_support_generic_range.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|auto range(vec v)| \itt{range} 2 | 3 | \cppinline|auto range(uint_t n)| 4 | 5 | \cppinline|auto range(uint_t i0, uint_t n)| 6 | 7 | This function returns a C++ \emph{range}, i.e., an object that can be used inside the C++ range-based \cppinline{for} loop. This range will generate integer values starting from \cppinline{0} (first and second version) or \cppinline{i0} (third version) to \cppinline{v.size()} (first version) or \cppinline{n} (second and third versions), that last value being \emph{excluded} from the range. This nice way of writing an integer \cppinline{for} loop actually runs as fast as (if not faster than) the classical way, and is less error prone. 8 | 9 | \begin{example} 10 | \begin{cppcode} 11 | vec1i v = {4,5,6,8}; 12 | 13 | // First version 14 | for (uint_t i : range(v)) { 15 | // 'i' goes from 0 to 3 16 | v[i] = ...; 17 | } 18 | 19 | // Note that the loop above generates 20 | // *indices* inside the vector, while: 21 | for (int i : v) { /* ... */ } 22 | // ... generates *values* from the vector. 23 | 24 | // Second version 25 | for (uint_t i : range(3)) { 26 | // 'i' goes from 0 to 2 27 | v[i] = ...; 28 | } 29 | 30 | // Third version 31 | for (uint_t i : range(1,3)) { 32 | // 'i' goes from 1 to 3 33 | v[i] = ...; 34 | } 35 | \end{cppcode} 36 | \end{example} 37 | -------------------------------------------------------------------------------- /doc/latex/functions_support_generic_rearrange.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec1u sort(vec)| \itt{sort} 2 | 3 | \cppinline|vec1u sort(vec, F comp)| 4 | 5 | \cppinline|void inplace_sort(vec&)| \itt{inplace_sort} 6 | 7 | \cppinline|void inplace_sort(vec&, F comp)| 8 | 9 | These functions will change the order of the elements inside a given vector so that they are sorted from the smallest to the largest. The difference between \cppinline{sort} and \cppinline{inplace_sort} is that \cppinline{sort} does not actually modify the provided vector, but rather returns a vector containing indices inside the provided vector, and \cppinline{inplace_sort} directly modifies the provided vector. The later is the fastest of the two, but it is less powerful. 10 | 11 | \begin{example} 12 | \begin{cppcode} 13 | // First version 14 | vec1i v = {1,5,6,3,7}; 15 | vec1u id = sort(v); // {0,3,1,2,4} 16 | v[id]; // {1,3,5,6,7} is sorted 17 | // now, id can also be used to modify the order of 18 | // another vector of the same dimensions 19 | 20 | // Second version 21 | inplace_sort(v); 22 | v; // {1,3,5,6,7} is sorted 23 | \end{cppcode} 24 | \end{example} 25 | 26 | \begin{advanced} 27 | In addition, both functions can be called with a second parameter that specifies the comparison function. This can be any function object (including a lambda) that must take two arguments whose type is that of the elements in the provided vector, and that return \cppinline{true} if the first element can be considered as ``inferior to'' the second element. This can be used to produce complex sorting criteria, possibly involving multiple vectors. 28 | 29 | \begin{example} 30 | \begin{cppcode} 31 | vec2i x = replicate(indgen(5), 5); 32 | vec2i y = transpose(x); 33 | 34 | // Sort the values in 'x' and 'y' first by ascending values of 'x', 35 | // then (for identical 'x') by descending values of 'y'. 36 | vec1u sid = uindgen(x.size()); 37 | inplace_sort(sid, [&x, &y](uint_t i1, uint_t i2) { 38 | if (x[i1] == x[i2]) return y[i1] > y[i2]; 39 | else return x[i1] < x[i2]; 40 | }); 41 | 42 | // This is the equivalent to the simpler examples above 43 | vec1i v = {1,5,6,3,7}; 44 | vec1u id = sort(v, [](int_t i1, int_t i2) { 45 | return i1 < i2; // the default is always to use the "less than" 46 | // comparison operator 47 | }); 48 | 49 | v[id]; // {1,3,5,6,7} is sorted 50 | \end{cppcode} 51 | \end{example} 52 | \end{advanced} 53 | 54 | \funcitem \cppinline|bool is_sorted(vec)| \itt{is_sorted} 55 | 56 | This function just traverses the whole input vector and checks if its elements are sorted by increasing value. 57 | 58 | \begin{example} 59 | \begin{cppcode} 60 | // First version 61 | vec1i v = {1,5,6,3,7}; 62 | is_sorted(v); // false 63 | inplace_sort(v); 64 | v; // {1,3,5,6,7} 65 | is_sorted(v); // true 66 | \end{cppcode} 67 | \end{example} 68 | 69 | \funcitem \cppinline|vec<1,T> reverse(vec<1,T>)| \itt{reverse} 70 | 71 | This function will inverse the order of all the elements inside the provided vector. 72 | 73 | \begin{example} 74 | \begin{cppcode} 75 | vec1i v = {1,2,3,4,5,6}; 76 | vec1i w = reverse(v); // {6,5,4,3,2,1} 77 | \end{cppcode} 78 | \end{example} 79 | 80 | \funcitem \cppinline|vec<2,T> transpose(vec<2,T>)| \itt{transpose} 81 | 82 | This function will transpose the provided vector so that its dimensions are swapped, i.e., \cppinline{v(i,j)} becomes \cppinline{v(j,i)}. 83 | 84 | \begin{example} 85 | \begin{cppcode} 86 | vec2i v = {{1,2}, {3,4}, {5,6}}; 87 | vec2i w = transpose(v); // {{1,3,5}, {2,4,6}} 88 | // now w(i,j) == v(j,i) 89 | \end{cppcode} 90 | \end{example} 91 | 92 | \funcitem \cppinline|vec<1,T> shift(vec<1,T> v, int_t n, T d = 0)| \itt{shift} 93 | 94 | This function will shift the position of the elements inside the provided vector \cppinline{v} by a given amount of indices \cppinline{n}. Elements that would go outside of the bounds of the vector are destroyed. New elements are inserted and default constructed, or assigned the default value \cppinline{d} (optional argument). 95 | 96 | \begin{example} 97 | \begin{cppcode} 98 | vec1i v = {1,2,3,4,5}; 99 | vec1i sr = shift(v, 2); 100 | sr; // {0,0,1,2,3} 101 | vec1i sl = shift(v, -2, 99); 102 | sl; // {3,4,5,99,99}; 103 | \end{cppcode} 104 | \end{example} 105 | -------------------------------------------------------------------------------- /doc/latex/functions_support_generic_sequence.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec indgen(...)| \itt{indgen} 2 | 3 | \cppinline|vec uindgen(...)| \itt{uindgen} 4 | 5 | \cppinline|vec findgen(...)| \itt{findgen} 6 | 7 | \cppinline|vec dindgen(...)| \itt{dindgen} 8 | 9 | These functions will create a new vector, whose dimensions are specified in argument like in the dimension constructor \rsec{SEC:core:vec:constructor} or \cppinline{vec::resize()} \rsec{SEC:core:vec:member_fun}. After this vector is created, the function will fill it with values that start at \cppinline{0} and increment by steps of \cppinline{1} until the end of the vector. 10 | 11 | \begin{example} 12 | \begin{cppcode} 13 | vec1i v = indgen(5); // {0,1,2,3,4} 14 | vec2u w = uindgen(3,2); // {{0,1}, {2,3}, {4,5}} 15 | \end{cppcode} 16 | \end{example} 17 | -------------------------------------------------------------------------------- /doc/latex/functions_support_generic_vectorize.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|auto vectorize_lambda(T func)| \itt{vectorize_lambda} 2 | 3 | This function takes a single argument that must be a C++ lambda. In turn, this lambda can take an arbitrary number of arguments, with the only constraint that the \emph{first} argument must be a scalar, i.e., not a \phypp vector. 4 | 5 | The function then creates a new lambda that can be called both with a scalar or a vector as the first argument. This allows easy conversion from legacy functions (e.g., from the standard library) into vectorized functions, and automatically takes care of possible optimizations. 6 | 7 | \begin{example} 8 | \begin{cppcode} 9 | // Create a simple lambda 10 | auto lambda = [](double f1, double f2) { 11 | return f1*f2; 12 | }; 13 | 14 | // It can be called like this: 15 | double res = lambda(1.5, 2.0); 16 | res; // 3.0 17 | 18 | // But if we want to call this function on a vector 19 | // of doubles, we cannot: 20 | vec1d x = {1,2,3,4,5}; 21 | vec1d vres = lambda(x, 2.0); // error! 22 | 23 | // We have to explicitly adapt this function for 24 | // vectorization. Instead of doing this manually, 25 | // we use vectorize_lambda 26 | auto vlambda = vectorize_lambda([](double f1, double f2) { 27 | return f1*f2; 28 | }); 29 | 30 | vec1d vres = vlambda(x, 2.0); // ok! 31 | vres; // {2.0, 4.0, 6.0, 8.0, 10.0} 32 | 33 | // We can also use this new lambda with scalar arguments 34 | res = vlambda(1.5, 2.0); 35 | res; // 3.0 36 | \end{cppcode} 37 | \end{example} 38 | -------------------------------------------------------------------------------- /doc/latex/functions_support_image.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec<2,T> enlarge(vec<2,T> v, array {l1, l2, u1, u2}, T d = 0)| \itt{enlarge} 2 | 3 | \cppinline|vec<2,T> enlarge(vec<2,T> v, uint_t u, T d = 0)| 4 | 5 | \funcitem \cppinline|vec<2,T> shrink(vec<2,T> v, array {l1, l2, u1, u2})| \itt{shrink} 6 | 7 | \cppinline|vec<2,T> shrink(vec<2,T> v, uint_t u)| 8 | 9 | \funcitem \cppinline|void subregion(vec<2,T> v, vec1i r, vec1u& rr, rs)| \itt{subregion} 10 | 11 | \cppinline|void subregion(vec<2,T> v, vec1i r, T d = 0)| 12 | 13 | \funcitem \cppinline|vec<2,T> translate(vec<2,T> v, double x, y, T d = 0)| \itt{translate} 14 | 15 | \funcitem \cppinline|vec<2,T> flip_x(vec<2,T> v)| \itt{flip_x} 16 | 17 | \funcitem \cppinline|vec<2,T> flip_y(vec<2,T> v)| \itt{flip_y} 18 | 19 | \funcitem \cppinline|vec<2,T> scale(vec<2,T> v, double s)| \itt{scale} 20 | 21 | \funcitem \cppinline|vec<2,T> rotate(vec<2,T> v, double a)| \itt{rotate} 22 | 23 | \funcitem \cppinline|vec2d circular_mask(vec1u d, vec1d c, double r)| \itt{circular_mask} 24 | 25 | \funcitem \cppinline|vec<1,T> radial_profile(vec<2,T> m, uint_t n)| \itt{radial_profile} 26 | 27 | \funcitem \cppinline|vec<2,T> generate_img(array {w,h}, F f)| \itt{generate_img} 28 | 29 | \funcitem \cppinline|vec2d gaussian_profile(array {w,h}, double sigma)| \itt{gaussian_profile} 30 | 31 | \funcitem \cppinline|vec<2,T> convolve2d(vec<2,T> m, vec<2,U> k)| \itt{convolve2d} 32 | 33 | \funcitem \cppinline|vec<2,T> boxcar(vec<2,T> m, uint_t n, F f)| \itt{boxcar} 34 | 35 | \funcitem \cppinline|vec2b mask_inflate(vec2b m, uint_t d)| \itt{mask_inflate} 36 | -------------------------------------------------------------------------------- /doc/latex/functions_support_math_algebra.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec<2,T> matrix::product(vec<2,T> a, b)| \itt{matrix::product} 2 | 3 | \cppinline|vec<1,V> matrix::product(vec<2,T> a, vec<1,U> b)| 4 | 5 | \cppinline|vec<1,V> matrix::product(vec<1,T> b, vec<2,U> a)| 6 | 7 | \funcitem \cppinline|vec<2,T> matrix::transpose(vec<2,T> a)| \itt{matrix::transpose} 8 | 9 | This function is identical to the generic \cppinline{transpose()} function, and is also provided in the \cppinline{maxtrix} namespace for consistency. 10 | 11 | \funcitem \cppinline|vec<1,T*> matrix::diagonal(vec<2,T>)| \itt{matrix::diagonal} 12 | 13 | \funcitem \cppinline|vec2d matrix::make_identity(uint_t)| \itt{matrix::make_identity} 14 | 15 | \funcitem \cppinline|vec2d matrix::make_scale(double sx, sy)| \itt{matrix::make_scale} 16 | 17 | \cppinline|vec2d matrix::make_scale(double s)| 18 | 19 | \funcitem \cppinline|vec2d matrix::make_translation(double dx, dy)| \itt{matrix::make_translation} 20 | 21 | \funcitem \cppinline|vec2d matrix::make_rotation(double a)| \itt{matrix::make_rotation} 22 | 23 | \funcitem \cppinline|vec1d matrix::make_point(double x, y)| \itt{matrix::make_point} 24 | 25 | \funcitem \requirelib{lapack} \cppinline|bool matrix::invert(vec2d a, vec2d& i)| \itt{matrix::invert} 26 | 27 | \requirelib{lapack} \cppinline|bool matrix::inplace_invert(vec2d&)| \itt{matrix::inplace_invert} 28 | 29 | \requirelib{lapack} \cppinline|bool matrix::invert_symmetric(vec2d a, vec2d& i)| \itt{matrix::invert_symmetric} 30 | 31 | \requirelib{lapack} \cppinline|bool matrix::inplace_invert_symmetric(vec2d&)| \itt{matrix::inplace_invert_symmetric} 32 | 33 | \funcitem \requirelib{lapack} \cppinline|bool matrix::solve_symmetric(vec2d a, vec1d b, vec1d& r)| \itt{matrix::solve_symmetric} 34 | 35 | \requirelib{lapack} \cppinline|bool matrix::inplace_solve_symmetric(vec2d& a, vec1d& b)| \itt{matrix::inplace_solve_symmetric} 36 | 37 | \funcitem \requirelib{lapack} \cppinline|bool matrix::eigen_symmetric(vec2d a, vec1d& va, vec1d& ve)| \itt{matrix::eigen_symmetric} 38 | 39 | \requirelib{lapack} \cppinline|bool matrix::inplace_eigen_symmetric(vec2d& a, vec1d& va)| \itt{matrix::inplace_eigen_symmetric} 40 | 41 | \funcitem \requirelib{fftw} \cppinline|vec2cd fft(vec2d)| \itt{fft} 42 | 43 | \requirelib{fftw} \cppinline|vec2d ifft(vec2cd)| \itt{ifft} 44 | 45 | \funcitem \cppinline|vec<1,W> convolve(vec<1,T> x, vec<1,U> y, vec<1,V> k)| \itt{convolve} 46 | -------------------------------------------------------------------------------- /doc/latex/functions_support_math_fit.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|auto linfit(vec y, e, ...)| \itt{linfit} 2 | 3 | \cppinline|auto linfit_pack(vec y, e, x)| \itt{linfit_pack} 4 | 5 | \funcitem \cppinline|auto affinefit(vec y, e, x)| \itt{affinefit} 6 | 7 | \funcitem \cppinline|auto mpfit(F d, vec1d p, auto opt = default)| \itt{mpfit} 8 | 9 | \funcitem \cppinline|auto mpfitfun(vec y, e, x, F f, vec1d p, auto opt = default)| \itt{mpfitfun} 10 | -------------------------------------------------------------------------------- /doc/latex/functions_support_math_geometry.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|vec1u convex_hull(vec x, y)| \itt{convex_hull} 2 | 3 | \funcitem \cppinline|bool is_hull_closed(vec1u h, vec hx, hy)| \itt{is_hull_closed} 4 | 5 | \funcitem \vectorfunc \cppinline|bool in_convex_hull(T x, y, vec1u h, vec hx, hy)| \itt{in_convex_hull} 6 | 7 | \funcitem \vectorfunc \cppinline|double convex_hull_distance(T x, y, vec1u h, vec hx, hy)| \itt{convex_hull_distance} 8 | -------------------------------------------------------------------------------- /doc/latex/functions_support_math_lowlevel.tex: -------------------------------------------------------------------------------- 1 | \funcitem \vectorfunc \cppinline|T e10(T)| \itt{e10} 2 | 3 | \vectorfunc \cppinline|T sqr(T)| \itt{sqr} 4 | 5 | \vectorfunc \cppinline|T invsqr(T)| \itt{invsqr} 6 | 7 | These functions are just convenient shortcut for the \cppinline{pow()} function: 8 | \begin{itemize} 9 | \item \cppinline{e10(x)} computes the exponentiation in base $10$, i.e., $10^x$, and is equivalent to \cppinline{pow(10, x)}, 10 | \item \cppinline{sqr(x)} computes the square of its argument, i.e., $x^2$, and is equivalent to \cppinline{pow(x, 2)}, 11 | \item \cppinline{invsqr(x)} computes the inverse square of its argument, i.e., $1/x^2$, and is equivalent to \cppinline{pow(x, -2)}. 12 | \end{itemize} 13 | 14 | Because they are less generic, calling these functions instead of \cppinline{pow()} \emph{can} result in faster code, however any improvement should be marginal. 15 | 16 | \funcitem \vectorfunc \cppinline|T clamp(T t, mi, ma)| \itt{clamp} 17 | 18 | This function will compare its first argument against \cppinline{mi} and keep the largest value. Then, it will compare this latter value against \cppinline{ma} and return the smallest of both. In other words, the goal of this function is to make sure that a given value \cppinline{t} is bound to a specified interval \cppinline{[mi, ma]}. It is a more readable equivalent to \cppinline{min(max(t, mi), ma)}. 19 | 20 | \begin{example} 21 | \begin{cppcode} 22 | vec1d x = {0.0, -0.05, 1.0, 0.5, 0.2, 1.06, 0.95, dnan}; 23 | // Make sure that the input values are between 0 and 1 24 | clamp(x, 0.0, 1.0); // {0.0,0.0,1.0,0.5,0.2,1.0,0.95,nan} 25 | \end{cppcode} 26 | \end{example} 27 | 28 | \funcitem \vectorfunc \cppinline|bool is_finite(T)| \itt{is_finite} 29 | 30 | \vectorfunc \cppinline|bool is_nan(T)| \itt{is_nan} 31 | 32 | The \cppinline{is_finite()} function will check if the provided argument is a finite number. In particular, for floating point numbers, it will return \cppinline{false} if the provided argument is either positive or negative infinity, or not a number (NaN). It will always return \cppinline{true} for integer numbers. 33 | 34 | The \cppinline{is_nan()} function will only return \cppinline{true} if its argument is NaN, and is the safest way to isolate these values. Indeed, remember that NaN values have the special properties that \cppinline{x == fnan} will be \cppinline{false} even if the value of \cppinline{x} is NaN. 35 | 36 | \begin{example} 37 | \begin{cppcode} 38 | vec1f x = {0.0, 1.0, finf, -finf, fnan}; 39 | is_finite(x); // {true,true,false,false,false} 40 | is_nan(x); // {false,false,false,false,true} 41 | \end{cppcode} 42 | \end{example} 43 | 44 | \funcitem \vectorfunc \cppinline|int_t sign(T)| \itt{sign} 45 | 46 | This function will return the sign of its argument. The most convenient way to achieve this is by returning an integer whose value is \cppinline{+1} for positive (or null) numbers, and \cppinline{-1} for strictly negative numbers. This allows convenient usage of this function inside more complex mathematical expressions without having to write conditional statements. 47 | 48 | The result of calling this function on ``not a number'' values is undefined. 49 | 50 | \begin{example} 51 | \begin{cppcode} 52 | // A stupid example. 53 | vec1d x = {-1.0, 0.0, -1000.5, 20.0, 5.0}; 54 | // By computing the square of 'x', we loose its sign. 55 | vec1d x2 = x*x; 56 | // Say we want to get back to 'x' 57 | // If we write: x2 = sqrt(x2) 58 | // ... the value is right, but not the sign. 59 | // Instead we can write: 60 | x2 = sign(x)*sqrt(x2); 61 | x2; // {-1.0,0.0,-1000.5,20.0,5.0} 62 | \end{cppcode} 63 | \end{example} 64 | -------------------------------------------------------------------------------- /doc/latex/functions_support_os.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|std::string system_var(string v, string d)| \itt{system_var} 2 | 3 | \cppinline|T system_var(string v, T d)| \itt{system_var} 4 | 5 | This function looks inside the operating system environment for a variable named \cppinline{v} (using the C function \cppinline{getenv}). If this variable exists, its value is returned as a string (first version), or converted into a value of type \cppinline{T} (second version). If the conversion fails, or if the environment variable does not exist, the default value \cppinline{d} is returned. 6 | 7 | Environment variables are complementary to command line arguments: they are mostly used to store system specific configurations that usually only change from one machine (or user) to another. Because they seldom change, it would be tedious to have to specify these configurations as command line arguments and provide them for each call of a given program. Instead, environment variables are set once and for all at the beginning of the user's session (on Linux this is usually done in the \texttt{.bashrc} file, or equivalent), and are read on demand by each program that needs them. 8 | 9 | By convention and for portability issues, it is recommended to specify environment variable names in full upper case (i.e., \cppinline{"PATH"} and not \cppinline{"Path"} or \cppinline{"path"}). 10 | 11 | \begin{example} 12 | \begin{cppcode} 13 | // One typical use case is to get a path to some external component 14 | std::string sed_library_dir = system_var("SUPERFIT_LIB_PATH"); 15 | if (sed_library_dir.empty()) { 16 | // This component is missing, try to do without or print an error 17 | } else { 18 | // The directory has been provided, look what is inside... 19 | } 20 | 21 | // It can also be used to modify generic behaviors, for example 22 | // configure how many threads we want to use by default in all the 23 | // programs of a given tool suite. 24 | uint_t nthread = system_var("MYTOOLS_NTHREADS", 1); 25 | \end{cppcode} 26 | \end{example} 27 | -------------------------------------------------------------------------------- /doc/latex/functions_support_thread.tex: -------------------------------------------------------------------------------- 1 | \funcitem \cppinline|void fork(string)| \itt{fork} 2 | 3 | \cppinline|void spawn(string)| \itt{spawn} 4 | 5 | \funcitem \cppinline|auto thread::pool(uint_t)| \itt{thread::pool} 6 | 7 | \funcitem \cppinline|void thread::sleep_for(double)| \itt{thread::sleep_for} 8 | -------------------------------------------------------------------------------- /doc/latex/phypp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/doc/latex/phypp.pdf -------------------------------------------------------------------------------- /doc/sphinx/astro.rst: -------------------------------------------------------------------------------- 1 | Astronomy library 2 | ================= 3 | -------------------------------------------------------------------------------- /doc/sphinx/filesystem.rst: -------------------------------------------------------------------------------- 1 | File system 2 | =========== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Categories 7 | 8 | filesystem-paths 9 | filesystem-system 10 | -------------------------------------------------------------------------------- /doc/sphinx/generic-error.rst: -------------------------------------------------------------------------------- 1 | Error checking 2 | ============== 3 | 4 | Defined in header ````. 5 | 6 | vif_check 7 | --------- 8 | 9 | .. code-block:: c++ 10 | 11 | template 12 | void vif_check(bool b, Args&& ... args); 13 | 14 | This function (in fact a C++ macro) makes error checking easier. When called, it checks the value of ``b``. If ``b`` is ``true``, then nothing happens and the values of ``args`` are not evaluated. However if ``b`` is ``false``, then the current file and line are printed to the standard output, followed by the other arguments of this function, which are supposed to compose an error message explaining what went wrong, and the program is immediately stopped. This function is used everywhere in the vif library to ensure that certain pre-conditions are met before doing a calculation, and it is *essential* to make the program stop in case something is unexpected rather than letting it run hoping for the best (and often getting the worst). 15 | 16 | Since this function is actually implemented by a preprocessor macro, one should not worry about its performance impact beside the cost of evaluating ``b``. Performances will only be affected when something goes wrong and the program is about to stop anyway. 17 | 18 | In addition, if the vif library was configured accordingly, this function can print the "backtrace" of the program that lead to the error. This backtrace lists which functions or lines of code the program was executing when the error occured, tracing back the offending line all the way up from the ``main()`` function. This can be very useful to identify the source of the problem, but is only available if debugging informations are stored inside the compiled program. Note that this only affects the size of the executable on disk: debugging informations do not alter performances. Lastly, the backtrace may not be sufficient to understand what went wrong, and one may need to use the debugger. 19 | 20 | .. code-block:: c++ 21 | 22 | // Suppose 'v' is read from the command line arguments. 23 | vec1i v = /* read from somewhere unsafe */; 24 | 25 | // The rest of the code needs at least 3 elements in the 26 | // vector 'v', so we need to check that first. 27 | vif_check(v.size() >= 3, "this algorithm needs at least 3 values in the input vector, " 28 | "but only ", v.size(), " were found"); 29 | 30 | // If we get past this point, we can proceed safely to use 31 | // the first three elements 32 | print(v[0]+v[1]+v[3]); 33 | 34 | // ... and we can safely disable index checking using the 35 | // 'safe' interface of the vector 36 | print(v.safe[0]+v.safe[1]+v.safe[3]); 37 | -------------------------------------------------------------------------------- /doc/sphinx/generic-indices.rst: -------------------------------------------------------------------------------- 1 | Index manipulation 2 | ================== 3 | 4 | Defined in header ````. 5 | 6 | 7 | mult_ids 8 | -------- 9 | 10 | .. code-block:: c++ 11 | 12 | template 13 | vec1u mult_ids(const std::array& dims, uint_t i); // [1] 14 | 15 | template 16 | vec2u mult_ids(const std::array& dims, vec1u i); // [2] 17 | 18 | template 19 | vec1u mult_ids(const vec& v, uint_t i); // [3] 20 | 21 | template 22 | vec2u mult_ids(const vec& v, vec1u i); // [4] 23 | 24 | This function converts a "flat" index ``i`` into an array of multidimensional indices, following the provided dimensions ``dims`` ([1] and [2]) or the provided vector ``v`` ([3] and [4]). The ``flat_id`` function does the inverse job. 25 | 26 | [2] and [4] are the vectorized version of [1] and [3], respectively. The return value is a 2D vector of indices: the first dimension contains as many elements as ``dims`` ([2]) or the dimensions of ``v`` ([4]), and the second dimension contains as many elements as the provided index vector ``i``. 27 | 28 | **Example:** 29 | 30 | .. code-block:: c++ 31 | 32 | vec2i v(2,3); 33 | mult_ids(v,0); // {0,0} 34 | mult_ids(v,1); // {0,1} 35 | mult_ids(v,2); // {0,3} 36 | mult_ids(v,3); // {1,0} 37 | v[3] == v(1,0); // true 38 | 39 | 40 | flat_id 41 | ------- 42 | 43 | .. code-block:: c++ 44 | 45 | template 46 | uint_t flat_id(const std::array& dims, Args&& ... args); // [1] 47 | 48 | template 49 | uint_t flat_id(const std::array& dims, const vec<1,TI>& ids); // [2] 50 | 51 | template 52 | uint_t flat_id(const vec& v, Args&& ... args); // [3] 53 | 54 | template 55 | uint_t flat_id(const vec& v, const vec<1,TI>& ids); // [4] 56 | 57 | This function converts a set of multidimensional indices into a "flat" index, following the provided dimensions ``dims`` ([1] and [2]) or the provided vector ``v`` ([3] and [4]). The ``mult_ids`` function does the inverse job. 58 | 59 | In [1] and [3], the multidimensional indices are provided as separate arguments to the function. In [2] and [4] they are grouped inside an index vector. 60 | 61 | **Example:** 62 | 63 | .. code-block:: c++ 64 | 65 | vec2i v(2,3); 66 | flat_id(v,0,0); // 0 67 | flat_id(v,0,1); // 1 68 | flat_id(v,0,2); // 2 69 | flat_id(v,1,0); // 3 70 | v(1,0) == v[3]; // true 71 | 72 | 73 | increment_index_list 74 | -------------------- 75 | 76 | .. code-block:: c++ 77 | 78 | void increment_index_list(vec1u& ids, const uint_t& n); // [1] 79 | 80 | void increment_index_list(vec1u& ids, const vec1u& n); // [2] 81 | 82 | These functions perform *one* increment on the set of multidimensional indices ``ids``, following the order in memory (i.e., last dimension is incremented first). In [1], each dimension has the same size ``n``, while in [2] the dimensions may be different and are provided as a vector ``n``. These functions allow the full traversal of the multidimensional space in a single loop, and are typically used to iterate on a multidimensional data set when the number of dimensions is either too large or unknown at compile time. 83 | 84 | If called on the last allowed index, the function will set ``ids`` to zero, hence come back to the first index. 85 | 86 | 87 | **Example:** 88 | 89 | .. code-block:: c++ 90 | 91 | // Say we got some multidimensional data from a file 92 | vec1d data; 93 | vec1u dims = /* read from a file */; 94 | 95 | uint_t nelem = 1; 96 | for (uint_t d : dims) nelem *= d; 97 | 98 | data.resize(nelem); 99 | 100 | // Initialize the index vector to zero (first index) 101 | vec1u ids(dims.size()); 102 | 103 | // Iterate in one single loop 104 | for (uint_t i : range(nelem)) { 105 | // data[i] is the element at index (ids[0],ids[1],...) 106 | 107 | // Increment using [2] 108 | increment_index_list(ids, dims); 109 | } 110 | -------------------------------------------------------------------------------- /doc/sphinx/generic-range.rst: -------------------------------------------------------------------------------- 1 | Range-based iteration 2 | ===================== 3 | 4 | Defined in header ````. 5 | 6 | range 7 | ----- 8 | 9 | .. code-block:: c++ 10 | 11 | template 12 | /*...*/ range(const vec& v); // [1] 13 | 14 | /*...*/ range(uint_t n); // [2] 15 | 16 | /*...*/ range(uint_t i0, uint_t n); // [3] 17 | 18 | This function returns a C++ *range*, that is, an object that can be used inside the C++ range-based ``for`` loop. This range will generate integer values starting from ``0`` (in [1], [2]) or ``i0`` (in [3]) to ``v.size()`` (in [1]) or ``n`` (in [2], [3]), that last value being *excluded* from the range. This nice way of writing an integer ``for`` loop actually runs as fast as (if not faster than) the classical way, and is less error prone. 19 | 20 | The return value is a proxy class that holds the starting and ending point of the range, and offers ``begin()`` and ``end()`` function for iteration. Its type is of little importance. 21 | 22 | **Example:** 23 | 24 | .. code-block:: c++ 25 | 26 | vec1i v = {4,5,6,8}; 27 | 28 | // First version 29 | for (uint_t i : range(v)) { // [1] 30 | // 'i' goes from 0 to 3 31 | v[i] = ...; 32 | } 33 | 34 | // Note that the loop above generates 35 | // *indices* inside the vector, while: 36 | for (int i : v) { /* ... */ } 37 | // ... generates *values* from the vector. 38 | 39 | // Second version 40 | for (uint_t i : range(3)) { // [2] 41 | // 'i' goes from 0 to 2 42 | v[i] = ...; 43 | } 44 | 45 | // Third version 46 | for (uint_t i : range(1,3)) { // [3] 47 | // 'i' goes from 1 to 3 48 | v[i] = ...; 49 | } 50 | -------------------------------------------------------------------------------- /doc/sphinx/generic-sequence.rst: -------------------------------------------------------------------------------- 1 | Integer sequences 2 | ================= 3 | 4 | Defined in header ````. 5 | 6 | indgen 7 | ------ 8 | 9 | .. code-block:: c++ 10 | 11 | template 12 | vec indgen(Dims&& ... ds); 13 | 14 | This functions will create a new vector with values starting at ``0`` and increment linearly by steps of ``1`` until the end of the vector. Internally, the values are generated with the standard function ``std::iota```. The number of dimensions of the resulting vector depends on the types ``Args`` of the arguments: 15 | 16 | * Each argument of type ``uint_t`` increases the number of dimensions by one. 17 | * Each argument of type ``std::array`` increases the number of dimensions by ``D``. 18 | 19 | The type of the values in the resulting vector is determined by the template parameter ``T``, which defaults to ``uint_t`` if none is provided. 20 | 21 | **Example:** 22 | 23 | .. code-block:: c++ 24 | 25 | vec1u v = indgen(5); // {0,1,2,3,4} 26 | vec2u w = indgen(3,2); // {{0,1}, {2,3}, {4,5}} 27 | -------------------------------------------------------------------------------- /doc/sphinx/generic.rst: -------------------------------------------------------------------------------- 1 | Generic functions 2 | ================= 3 | 4 | The vector and view classes are useful on their own. However, there are a number of tasks that one may needs to do quite often, like generating a sequence of indices, or sorting a vector, which would be tedious to rewrite each time they are needed. For this reason, the vif support library comes with a large set of utility functions to traverse, sort, rearrange, and select data inside vectors. In this section we list these various functions and describe the corresponding algorithms. 5 | 6 | The support library introduces a global constant called ``npos``. This is an unsigned integer whose value is the largest possible integer that the ``uint_t`` type can hold. It is meant to be used as an error value, or the value to return if no valid integer value would make sense. It is very similar in concept to the ``std::string::npos`` provided by the C++ standard library. In particular, it is worth noting that converting ``npos`` to a *signed* integer produces the value ``-1``. 7 | 8 | We now describe the functions provided by this module, sorted by categories. 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | :caption: Categories 13 | 14 | generic-range 15 | generic-indices 16 | generic-sequence 17 | generic-rearrange 18 | generic-find 19 | generic-error 20 | -------------------------------------------------------------------------------- /doc/sphinx/image.rst: -------------------------------------------------------------------------------- 1 | Image manipulation 2 | ================== 3 | -------------------------------------------------------------------------------- /doc/sphinx/index.rst: -------------------------------------------------------------------------------- 1 | .. image:: icon_black_text.svg 2 | :alt: vif 3 | :width: 400 4 | 5 | 6 | Documentation 7 | ============= 8 | 9 | vif is a set of library and tools built to provide user-friendly vector data manipulation, as offered in interpreted languages like IDL_, its open source clone GDL_, or Python and numpy_, but with the added benefit of C++: increased robustness, and optimal speed. 10 | 11 | The library can be split into two components: 12 | 13 | * The "core" library 14 | * The "support" library 15 | 16 | The core library introduces the ``vec`` type (a "data vector"), which is the most important data type in vif, while the support library provides functions and other tools to manipulate these vectors and perform common tasks. You can think of vif as a separate language inside C++, where the core library defines this language, and the support library is the the "standard" library where all the useful functions are stored. 17 | 18 | Below is a code sample written in vif that illustrates the most basic functionalities. 19 | 20 | .. code-block:: c++ 21 | 22 | using namespace vif; // import everything in current namespace 23 | vec2f img = fits::read("img.fits"); // read a FITS image 24 | img -= median(img); // subtract the median of the whole image 25 | float imax = max(img); // find the maximum of the image 26 | vec1u ids = where(img > 0.5*imax); // find pixels at least half as bright 27 | float sum = total(img[ids]); // compute the sum of these pixels 28 | img[ids] = log(img[ids]/sum); // modify these pixels with a logarithm 29 | fits::write("new.fits", img); // save the modified image to a FITS file 30 | 31 | .. _IDL: http://www.exelisvis.com/ProductsServices/IDL.aspx 32 | .. _GDL: http://gnudatalanguage.sourceforge.net/ 33 | .. _numpy: http://www.numpy.org/ 34 | 35 | .. _core-library: 36 | 37 | .. toctree:: 38 | :maxdepth: 2 39 | :caption: The core library 40 | 41 | overview 42 | vector 43 | indexing 44 | view 45 | known-issues 46 | generic-function-guidelines 47 | idl 48 | 49 | .. _support-library: 50 | 51 | .. toctree:: 52 | :maxdepth: 2 53 | :caption: The support library 54 | 55 | support-intro 56 | generic 57 | argv 58 | string 59 | print 60 | os 61 | filesystem 62 | io-ascii 63 | io-fits 64 | time 65 | math 66 | thread 67 | image 68 | astro 69 | -------------------------------------------------------------------------------- /doc/sphinx/io-fits-image.rst: -------------------------------------------------------------------------------- 1 | .. _FITS images: 2 | 3 | FITS images 4 | =========== 5 | 6 | Defined in header ````. 7 | -------------------------------------------------------------------------------- /doc/sphinx/io-fits-keywords.rst: -------------------------------------------------------------------------------- 1 | .. _FITS files: 2 | 3 | Header & keywords 4 | ================= 5 | 6 | Defined in header ````. 7 | 8 | 9 | has_keyword 10 | ----------- 11 | 12 | .. code-block:: c++ 13 | 14 | bool fits::file_base::has_keyword(std::string name) const; 15 | 16 | This function checks if a given keyword exists in the header of the current HDU. This check is not case-sensitive, and the function automatically supports long keyword names specified with the ``HIERARCH`` convention; it is not necessary to specify the ``HIERARCH`` explicitly. Will throw an exception if no file is currently open. 17 | 18 | **Example:** 19 | 20 | .. code-block:: c++ 21 | 22 | // Open a FITS image 23 | fits::input_image img("my_image.fits"); 24 | img.has_keyword("BUNIT"); // does this image have a unit? 25 | 26 | 27 | read_keyword 28 | ------------ 29 | 30 | .. code-block:: c++ 31 | 32 | template 33 | bool fits::file_base::read_keyword(std::string name, T& value) const; 34 | 35 | This function checks if a given keyword exists in the header of the current HDU, and if the keyword exits, attempts to read its value and store it into the variable ``value``. This check is not case-sensitive, and the function automatically supports long keyword names specified with the ``HIERARCH`` convention; it is not necessary to specify the ``HIERARCH`` explicitly. If any of these steps fail, the content of ``value`` is unchanged and the function returns ``false``. Will throw an exception if no file is currently open. 36 | 37 | **Example:** 38 | 39 | .. code-block:: c++ 40 | 41 | // Open a FITS image 42 | fits::input_image img("my_image.fits"); 43 | std::string unit; 44 | if (img.read_keyword("BUNIT", unit)) { 45 | // We know the unit of the image 46 | } 47 | double frequency; 48 | if (img.read_keyword("FREQ", frequency)) { 49 | // We know the frequency at which the image was obtained 50 | } 51 | 52 | 53 | write_keyword, add_keyword 54 | -------------------------- 55 | 56 | .. code-block:: c++ 57 | 58 | template 59 | void fits::output_file_base::write_keyword(std::string name, const T& value); // [1] 60 | template 61 | void fits::output_file_base::add_keyword(std::string name, const T& value); // [2] 62 | 63 | These functions write the given keyword into the header of the current HDU, setting its value to the provided ``value``. If a keyword with this name already exist, function [1] will update its value, while function [2] will simply ignore it and add a new keyword with the same name at the end of the header (it is indeed possible to have multiple keywords with the same name). If the keyword name is longer than 8 characters, CFITSIO will automatically write the keyword with the ``HIERARCH`` convention; it is not necessary to specify the ``HIERARCH`` explicitly. Will throw an exception if no file is currently open. 64 | 65 | **Example:** 66 | 67 | .. code-block:: c++ 68 | 69 | // Open a FITS image 70 | fits::output_image img("my_image.fits"); 71 | vec2d data(10,10); 72 | img.write(data); 73 | img.write_keyword("BUNIT", "W/m2/sr"); // write a string 74 | img.write_keyword("FREQ", 1.4e9); // write a number 75 | 76 | 77 | remove_keyword 78 | -------------- 79 | 80 | .. code-block:: c++ 81 | 82 | void fits::output_file_base::remove_keyword(std::string name); 83 | 84 | This function will remove the first keyword in the header whose name matches the provided string. No error is generated if no such keyword exists. If the keyword name is longer than 8 characters, CFITSIO will automatically write the keyword with the ``HIERARCH`` convention; it is not necessary to specify the ``HIERARCH`` explicitly. Will throw an exception if no file is currently open. 85 | 86 | **Example:** 87 | 88 | .. code-block:: c++ 89 | 90 | // Open a FITS image 91 | fits::output_image img("my_image.fits"); 92 | vec2d data(10,10); 93 | img.write(data); 94 | img.write_keyword("BUNIT", "W/m2/sr"); // write a string 95 | img.remove_keyword("BUNIT"); // we changed our mind, remove it 96 | -------------------------------------------------------------------------------- /doc/sphinx/io-fits-raw.rst: -------------------------------------------------------------------------------- 1 | .. _FITS files: 2 | 3 | C interface 4 | =========== 5 | 6 | Defined in header ````. 7 | 8 | cfitstio_status 9 | --------------- 10 | 11 | .. code-block:: c++ 12 | 13 | int fits::file_base::cfitstio_status() const noexcept; 14 | 15 | This function returns the current CFITSIO error code. Only useful for debugging purposes. If no file is currently open, it will return zero. 16 | 17 | **Example:** 18 | 19 | .. code-block:: c++ 20 | 21 | fits::input_image img("my_image.fits"); 22 | img.cfitsio_status(); // most likely 0 23 | 24 | 25 | cfitsio_ptr 26 | ----------- 27 | 28 | .. code-block:: c++ 29 | 30 | fitsfile* fits::file_base::cfitsio_ptr() noexcept; 31 | const fitsfile* fits::file_base::cfitsio_ptr() const noexcept; 32 | 33 | These functions returns the underlying CFITSIO file pointer. This is useful if you need to perform an operation that is not available as part of the C++ interface. It is safe to perform any operation with this pointer and then fall back to the C++ interface, however if you do so you must call the ``update_state()`` function before using any function of the C++ interface. 34 | 35 | If no file is currently open, it will return a null pointer. 36 | 37 | **Example:** 38 | 39 | .. code-block:: c++ 40 | 41 | // Open a FITS image 42 | fits::input_image img("my_image.fits"); 43 | // Get the underlying CFITSIO pointer 44 | fitsptr* fptr = img.cfitsio_ptr(); 45 | // Use the pointer with the raw C interface 46 | // ... 47 | // Update the internal state 48 | img.update_internal_state(); 49 | // Continue using the C++ interface 50 | 51 | 52 | update_internal_state 53 | --------------------- 54 | 55 | .. code-block:: c++ 56 | 57 | void fits::file_base::update_internal_state(); 58 | 59 | This function is called internally by ``open()`` and ``reach_hdu()``, and is used to update the internal state of the C++ wrapper based on the current content of the file. You only need to use this function if you perform operations on the file using the raw CFITSIO interface. See ``cfitsio_ptr()`` for more information. Will throw an exception if no file is currently open. 60 | -------------------------------------------------------------------------------- /doc/sphinx/io-fits-table.rst: -------------------------------------------------------------------------------- 1 | .. _FITS tables: 2 | 3 | FITS tables 4 | =========== 5 | 6 | Defined in header ````. 7 | -------------------------------------------------------------------------------- /doc/sphinx/io-fits.rst: -------------------------------------------------------------------------------- 1 | FITS files 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Categories 7 | 8 | io-fits-overview 9 | io-fits-open 10 | io-fits-hdu 11 | io-fits-keywords 12 | io-fits-image 13 | io-fits-table 14 | io-fits-raw 15 | -------------------------------------------------------------------------------- /doc/sphinx/math.rst: -------------------------------------------------------------------------------- 1 | Mathematics 2 | =========== 3 | -------------------------------------------------------------------------------- /doc/sphinx/os-process.rst: -------------------------------------------------------------------------------- 1 | Processes 2 | ========= 3 | 4 | Defined in header ````. 5 | 6 | spawn 7 | ----- 8 | 9 | .. code-block:: c++ 10 | 11 | bool spawn(const std::string& cmd); 12 | 13 | This function executes the shell command passed in argument (on UNIX systems, using ``/bin/sh``). It puts execution of the current program on hold until the shell command terminates. This can be used to launch another application, for example an image viewer that the user can use to inspect some temporary calculations. 14 | 15 | If you wish to run this command in parallel with the current program, see ``fork()``. 16 | 17 | **Example:** 18 | 19 | .. code-block:: c++ 20 | 21 | // Calculate some things to make an image 22 | vec2d img = /* ... */; 23 | 24 | // Write this image to the disk in FITS format 25 | fits::write("tmp.fits", img); 26 | 27 | // Call the FITS viewer DS9 on this data and let user inspect it. 28 | // The program will be paused until the user closes DS9. 29 | spawn("ds9 tmp.fits"); 30 | 31 | // Now execution comes back to us. 32 | // We can, for example, ask the user if the data was satisfactory. 33 | 34 | 35 | fork 36 | ----- 37 | 38 | .. code-block:: c++ 39 | 40 | bool fork(const std::string& cmd); 41 | 42 | This function creates a new ``child`` process to execute the shell command passed in argument (on UNIX systems, using ``/bin/sh``). The child process runs in the background, while execution continues in the main process. Note that any child process will be automatically killed when the main process terminates: child processes cannot survive longer than the main process. 43 | 44 | If you wish simply to run a command and wait for it to finish, see ``spawn()``. 45 | 46 | **Example:** 47 | 48 | .. code-block:: c++ 49 | 50 | // Calculate some things to make an image 51 | vec2d img = /* ... */; 52 | 53 | // Write this image to the disk in FITS format 54 | fits::write("tmp.fits", img); 55 | 56 | // Call the FITS viewer DS9 on this data to let user inspect it. 57 | // The DS9 window will open in the background. 58 | fork("ds9 tmp.fits"); 59 | 60 | // Execution comes back to us immediately, so the user can keep 61 | // inspecting the image while we do some more calculations. 62 | // Just be careful not to open too many windows in this way! 63 | -------------------------------------------------------------------------------- /doc/sphinx/os-sysvar.rst: -------------------------------------------------------------------------------- 1 | Environment variables 2 | ===================== 3 | 4 | Defined in header ````. 5 | 6 | system_var 7 | ---------- 8 | 9 | .. code-block:: c++ 10 | 11 | std::string system_var(const std::string& v, const std::string& d); // [1] 12 | 13 | template 14 | T system_var(string v, T d); // [2] 15 | 16 | These functions looks inside the operating system environment for a variable named ``v`` (using the C function ``getenv()``). If this variable exists, its value is returned as a string ([1]), or converted into a value of type ``T`` ([2]). If the conversion fails, or if the environment variable does not exist, the default value ``d`` is returned instead. 17 | 18 | Environment variables are complementary to :ref:`Command line arguments`. They are mostly used to store constant, system-specific configurations that will typically change only between one machine or one user to another. Because they seldom change, it would be tedious to have to specify these configurations as command line arguments and provide them for *each* call of a given program. Instead, environment variables are set "once and for all" at the beginning of the user's session (on Linux this is usually done in the ``~/.bashrc`` file, or equivalent), and are read on demand by each program that needs them. 19 | 20 | By convention and for portability issues, it is recommended to specify environment variable names in full upper case (i.e., ``"PATH"`` and not ``"Path"`` or ``"path"``). 21 | 22 | **Example:** 23 | 24 | .. code-block:: c++ 25 | 26 | // One typical use case is to get the path of some external component 27 | std::string sed_library_dir = system_var("SUPERFIT_LIB_PATH"); 28 | if (!sed_library_dir.empty()) { 29 | // The directory has been provided, look what is inside... 30 | } else { 31 | // This component is missing, try to do without or print an error 32 | } 33 | 34 | // It can also be used to modify generic behaviors, for example 35 | // configure how many threads we want to use by default in all the 36 | // programs of a given tool suite. 37 | uint_t nthread = system_var("MYTOOLS_NTHREADS", 1); 38 | -------------------------------------------------------------------------------- /doc/sphinx/os.rst: -------------------------------------------------------------------------------- 1 | Interacting with the operating system 2 | ===================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Categories 7 | 8 | os-sysvar 9 | os-process 10 | -------------------------------------------------------------------------------- /doc/sphinx/overview.rst: -------------------------------------------------------------------------------- 1 | Overview of the core library 2 | ============================ 3 | 4 | At the core of the vif library is the *vector* class, ``vec``. This is basically an enhanced ``std::vector``, and it therefore shares most of its features and strengths. On top of the ``std::vector`` interface, the vif vectors have extra functionalities to simplify data analysis and calculations, including overloaded mathematical operators, multi-dimensional indexing, and the ability to create "views" to access and edit subsets of a given vector. 5 | 6 | Here we will first describe the properties of the vector class, and then describe the vector views. Lastly, a guide for writing "generic" functions that work with any vector type is provided. 7 | -------------------------------------------------------------------------------- /doc/sphinx/string-base.rst: -------------------------------------------------------------------------------- 1 | Basic string operations 2 | ======================= 3 | 4 | Defined in header ````. 5 | 6 | empty 7 | ----- 8 | 9 | .. code-block:: c++ 10 | 11 | bool empty(const std::string& s); // [1] 12 | 13 | template 14 | vec empty(const vec& s); // [2] 15 | 16 | The function [1] will return ``true`` if the provided string does not contain *any* character (including spaces), and ``false`` otherwise. This is a synonym for ``s.empty()``. The function [2] is the vectorized version of [1]. 17 | 18 | **Example:** 19 | 20 | .. code-block:: c++ 21 | 22 | vec1s str = {"", "abc", " "}; 23 | vec1b b = empty(str); 24 | b; // {true, false, false} 25 | // Not to be confused with the vec::empty() function 26 | str.empty(); // false 27 | str = {""}; 28 | str.empty(); // false 29 | str = {}; 30 | str.empty(); // true 31 | 32 | 33 | length 34 | ------ 35 | 36 | .. code-block:: c++ 37 | 38 | uint_t length(const std::string& s); // [1] 39 | 40 | template 41 | vec length(const vec& s); // [2] 42 | 43 | The function [1] will return the length of the provided string, i.e., the number of character it contains (including spaces). If the string is empty, the function will return zero. The function [2] is the vectorized version of [1]. 44 | 45 | **Example:** 46 | 47 | .. code-block:: c++ 48 | 49 | vec1s str = {"", "abc", " a b"}; 50 | vec1u n = length(str); 51 | n; // {0, 3, 4} 52 | 53 | 54 | keep_first, keep_last 55 | --------------------- 56 | 57 | .. code-block:: c++ 58 | 59 | std::string keep_first(std::string s, uint_t n = 1); // [1] 60 | 61 | std::string keep_last(std::string s, uint_t n = 1); // [2] 62 | 63 | template 64 | vec keep_first(vec s, uint_t n = 1); // [3] 65 | 66 | template 67 | vec keep_last(vec s, uint_t n = 1); // [4] 68 | 69 | These functions will return the first ([1]) or last ([2]) ``n`` characters of the string ``s`` and discard the rest. If ``n`` is larger than the size of ``s``, the whole string is returned untouched. Functions [3] and [4] are the vectorized versions of [1] and [2], respectively. 70 | 71 | **Example:** 72 | 73 | .. code-block:: c++ 74 | 75 | vec1s v = {"p1_m2.txt", "p3_c4.fits", "p1_t8.fits"}; 76 | vec1s s = keep_first(v, 2); 77 | s; // {"p1", "p3", "p1"} 78 | s = keep_last(v, 4); 79 | s; // {".txt", "fits", "fits"} 80 | 81 | 82 | distance 83 | -------- 84 | 85 | .. code-block:: c++ 86 | 87 | uint_t distance(const std::string& s1, const std::string& s2); // [1] 88 | 89 | template 90 | vec distance(const vec& s1, const std::string& s2); // [2] 91 | 92 | 93 | The function [1] computes the *lexicographic distance* between two strings. The definition of this distance is the following. If the two strings are exactly identical, the distance is zero. Else, each character of the shortest string are compared to the corresponding character at the same position in the other string: if they are different, the distance is increase by one. Finally, the distance is increased by the difference of size between the two strings. 94 | 95 | The goal of this function is to identify *near* matches in case a string could not be found in a pre-defined list. This is useful to suggest corrections to the user, who may have misspelled it. 96 | 97 | **Example:** 98 | 99 | .. code-block:: c++ 100 | 101 | vec1s s = {"wircam_K", "hawki_Ks", "subaru_B"}; 102 | vec1u d = distance(s, "wirkam_Ks"); 103 | d; // {2, 8, 8} 104 | 105 | // Nearest match 106 | std::string m = s[min_id(d)]; 107 | m; // "wircam_K" 108 | 109 | -------------------------------------------------------------------------------- /doc/sphinx/string-format.rst: -------------------------------------------------------------------------------- 1 | .. _Formatting: 2 | 3 | Formatting 4 | ========== 5 | 6 | Defined in header ````. 7 | 8 | 9 | trim 10 | ---- 11 | 12 | .. code-block:: c++ 13 | 14 | std::string trim(std::string s, const std::string& c = " \t"); // [1] 15 | 16 | template 17 | vec trim(vec s, const std::string& c = " \t"); // [2] 18 | 19 | The function [1] will look at the *beginning* and *end* of the string ``s`` for any of the characters that is present in ``c`` (order is irrelevant), and remove them. This procedure is repeated until no such character is found. The net effect of this function is that the provided string ``s`` is *trimmed* from any of the characters listed in ``c``. This is useful for example to remove leading and trailing spaces of a string (which is what the default value of ``c`` does), or to removes quotes, leading zeroes, etc. The function [2] is the vectorized version of [1]. 20 | 21 | **Example:** 22 | 23 | .. code-block:: c++ 24 | 25 | vec1s str = {"", "abc", " a b", " a b c "}; 26 | vec1s t = trim(str, " "); // trim spaces 27 | t; // {"", "abc", "a b", "a b c"} 28 | 29 | str = {"", "(a,b)", "((a,b),c)"}; 30 | t = trim(str, "()"); // trim parentheses 31 | t; // {"", "a,b", "a,b),c"} 32 | 33 | 34 | to_upper, to_lower 35 | ------------------ 36 | 37 | .. code-block:: c++ 38 | 39 | std::string to_upper(std::string s); // [1] 40 | 41 | std::string to_lower(std::string s); // [2] 42 | 43 | template 44 | vec to_upper(vec s); // [3] 45 | 46 | template 47 | vec to_lower(vec s); // [4] 48 | 49 | These functions will transform all characters of the string to be upper case ([1]) or lower case ([2]). It has no effect on non-alphabetic characters such as numbers, punctuation, of special characters. Functions [3] and [4] are the vectorized versions of [1] and [2], respectively. 50 | 51 | **Example:** 52 | 53 | .. code-block:: c++ 54 | 55 | vec1s str = {"", "abc", "AbCdE", "No, thanks!"}; 56 | vec1s t = to_upper(str); 57 | t; // {"", "ABC", "ABCDE", "NO, THANKS!"} 58 | t = to_lower(str); 59 | t; // {"", "abc", "abcde", "no, thanks!"} 60 | 61 | 62 | align_left, align_right, align_center 63 | ------------------------------------- 64 | 65 | .. code-block:: c++ 66 | 67 | std::string align_left(std::string s, uint_t w, char f = ' '); // [1] 68 | 69 | std::string align_right(std::string s, uint_t w, char f = ' '); // [2] 70 | 71 | std::string align_center(std::string s, uint_t w, char f = ' '); // [3] 72 | 73 | These functions will pad the provided string with the character ``f`` (default to a space) so that the total width the returned string is equal to ``w``. If the provided string is larger than ``w``, it is returned untouched. Padding characters will be appended at the end of the string ([1]), at the beginning of the string ([2]), or equally to both ([3]), so the string will be aligned left, right, and centered, respectively. 74 | 75 | **Example:** 76 | 77 | .. code-block:: c++ 78 | 79 | std::string s = "5.0"; 80 | std::string n = align_left(s, 6); 81 | n; // "5.0 " 82 | n = align_right(s, 6); 83 | n; // " 5.0" 84 | n = align_center(s, 6); 85 | n; // " 5.0 " 86 | 87 | // Another padding character can be used 88 | n = align_left(s, 6, '0'); 89 | n; // "5.0000" 90 | -------------------------------------------------------------------------------- /doc/sphinx/string-hash.rst: -------------------------------------------------------------------------------- 1 | Hash 2 | ==== 3 | 4 | Defined in header ````. 5 | 6 | 7 | hash 8 | ---- 9 | 10 | .. code-block:: c++ 11 | 12 | template 13 | std::string hash(const Args& ... args); // [1] 14 | 15 | This function scans all the arguments that are provided, and returns the hexadecimal representation of the SHA-1 "hash" of this argument list. The hash is a string such that: 1) all further calls of ``hash(...)`` with arguments that have the exact same value (perhaps when the program is executed a second time later) will always return the same string, and 2) the probability is very small that the function returns the same string for another set of arguments, or arguments with different values. Although this algorithm was created in 1995, the first "collision" (two different data sets producing the same hash) was found in 2017. 16 | 17 | This is useful for example to cache the result of some heavy computation: once the computation is done, the *input* parameters of the computation can be fed to ``hash()`` to give a "sort-of-unique" identifier to the "input+result" pair. The result of the computation can then be saved somewhere with the hash as an identifier. Later on, if the computation is requested with a new set of parameters, these parameters are fed to ``hash()`` and the resulting string is compared to all the identifiers of the cached results: if a match is found, then the associated pre-computed result can be re-used, else the computation must be executed anew. 18 | 19 | **Example:** 20 | 21 | .. code-block:: c++ 22 | 23 | std::string s; 24 | 25 | // With a single argument 26 | s = hash("hello world!"); 27 | s; // "da52a1357f3c973e1ffc1b694d5308d0abcd9845" 28 | s = hash("hello world?") 29 | s; // "793e673d04e555f8f0b38033d5223c525a040719" 30 | // Notice how changing a single character gives a completely 31 | // different hash string 32 | 33 | // With multiple arguments 34 | s = hash(1, 2, 3); 35 | s; // "570331ab965721aae8a8b3c628cae57a21a37560" 36 | s = hash("123"); 37 | s; // "0e898437b29ec20c39ca48243e676bcb177d4632" 38 | s = hash(1.0, 2.0, 3.0); 39 | s; // "9c45014f7c7943cb7860f3db4b885fb44b510ec8" 40 | // Notice how the hash is different even though we would 41 | // consider these different sets of values to be equivalent. 42 | -------------------------------------------------------------------------------- /doc/sphinx/string.rst: -------------------------------------------------------------------------------- 1 | String manipulation 2 | =================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Categories 7 | 8 | string-conversion 9 | string-base 10 | string-split 11 | string-format 12 | string-find-replace 13 | string-regex 14 | string-hash 15 | -------------------------------------------------------------------------------- /doc/sphinx/thread.rst: -------------------------------------------------------------------------------- 1 | Multi threading 2 | =============== 3 | -------------------------------------------------------------------------------- /doc/sphinx/time.rst: -------------------------------------------------------------------------------- 1 | Measuring time 2 | ============== 3 | -------------------------------------------------------------------------------- /include/vif.hpp: -------------------------------------------------------------------------------- 1 | // Core headers, containing essential features from the library 2 | #include "vif/core/vec.hpp" 3 | #include "vif/core/range.hpp" 4 | #include "vif/core/print.hpp" 5 | #include "vif/core/error.hpp" 6 | 7 | // New entry point of the program, necessary to get stack trace in case of errors 8 | #include "vif/core/main.hpp" 9 | 10 | // Generic utility functions 11 | #include "vif/utility/string.hpp" 12 | #include "vif/utility/argv.hpp" 13 | #include "vif/utility/os.hpp" 14 | #include "vif/utility/time.hpp" 15 | #include "vif/utility/thread.hpp" 16 | #include "vif/utility/generic.hpp" 17 | 18 | // Reflection tools 19 | #include "vif/reflex/reflex.hpp" 20 | #include "vif/reflex/reflex_helpers.hpp" 21 | 22 | // Input/output (IO) functions for reading and writing files 23 | #include "vif/io/filesystem.hpp" 24 | #include "vif/io/ascii.hpp" 25 | #include "vif/io/fits.hpp" 26 | 27 | // Mathematics functions 28 | #include "vif/math/base.hpp" 29 | #include "vif/math/interpolate.hpp" 30 | #include "vif/math/reduce.hpp" 31 | #include "vif/math/histogram.hpp" 32 | #include "vif/math/random.hpp" 33 | #include "vif/math/matrix.hpp" 34 | #include "vif/math/linfit.hpp" 35 | #include "vif/math/convex_hull.hpp" 36 | #include "vif/math/complex.hpp" 37 | #include "vif/math/fourier.hpp" 38 | #include "vif/math/transform.hpp" 39 | 40 | // Astronomy functions 41 | #include "vif/astro/image.hpp" 42 | #include "vif/astro/astro.hpp" 43 | #include "vif/astro/wcs.hpp" 44 | 45 | -------------------------------------------------------------------------------- /include/vif/core/bits/initializer_list.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_CORE_VEC_BITS 2 | #error this file is not meant to be included separately, include "vif/core/vec.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | namespace impl { 7 | namespace vec_ilist { 8 | template 9 | struct helper { 10 | using dtype = meta::dtype_t; 11 | 12 | static void set_dim_(vec& v, meta::nested_initializer_list<1,dtype> il, meta::cte_t) { 13 | if (il.size() == 0) { 14 | for (uint_t i = 0; i < Dim; ++i) { 15 | v.dims[i] = 0; 16 | } 17 | } else { 18 | v.dims[Dim-1] = il.size(); 19 | } 20 | } 21 | 22 | template::type> 23 | static void set_dim_(vec& v, meta::nested_initializer_list il, meta::cte_t) { 24 | if (il.size() == 0) { 25 | for (uint_t i = 0; i < Dim; ++i) { 26 | v.dims[i] = 0; 27 | } 28 | } else { 29 | v.dims[N] = il.size(); 30 | set_dim_(v, *il.begin(), meta::cte_t()); 31 | } 32 | } 33 | 34 | static void fill_(vec& v, meta::nested_initializer_list<1,dtype> il, uint_t& idx, meta::cte_t) { 35 | vif_check(il.size() == v.dims[Dim-1], "heterogeneous intializer lists are not allowed"); 36 | for (auto& t : il) { 37 | v.data[idx] = t; 38 | ++idx; 39 | } 40 | } 41 | 42 | template::type> 43 | static void fill_(vec& v, meta::nested_initializer_list il, uint_t& idx, meta::cte_t) { 44 | vif_check(il.size() == v.dims[N], "heterogeneous intializer lists are not allowed"); 45 | for (auto& t : il) { 46 | fill_(v, t, idx, meta::cte_t()); 47 | } 48 | } 49 | 50 | static void fill(vec& v, meta::nested_initializer_list il) { 51 | set_dim_(v, il, meta::cte_t<0>()); 52 | v.resize(); 53 | if (!v.empty()) { 54 | uint_t idx = 0; 55 | fill_(v, il, idx, meta::cte_t<0>()); 56 | } 57 | } 58 | }; 59 | 60 | template 61 | struct helper { 62 | using dtype = meta::dtype_t; 63 | 64 | static void fill_(vec& v, meta::nested_initializer_list<1,dtype> il, uint_t& idx, meta::cte_t) { 65 | vif_check(il.size() == v.dims[Dim-1], "heterogeneous intializer lists are not allowed"); 66 | for (auto& t : il) { 67 | *v.data[idx] = t; 68 | ++idx; 69 | } 70 | } 71 | 72 | template::type> 73 | static void fill_(vec& v, meta::nested_initializer_list il, uint_t& idx, meta::cte_t) { 74 | vif_check(il.size() == v.dims[N], "heterogeneous intializer lists are not allowed"); 75 | for (auto& t : il) { 76 | fill_(v, t, idx, meta::cte_t()); 77 | } 78 | } 79 | 80 | static void fill(vec& v, meta::nested_initializer_list il) { 81 | uint_t idx = 0; 82 | fill_(v, il, idx, meta::cte_t<0>()); 83 | } 84 | }; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /include/vif/core/main.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_CORE_MAIN_HPP 2 | #define VIF_CORE_MAIN_HPP 3 | 4 | #include "vif/core/error.hpp" 5 | 6 | #ifndef NO_LIBUNWIND 7 | namespace vif { 8 | const char* executable_path; 9 | } 10 | #endif 11 | 12 | // New entry point 13 | int vif_main(int argc, char* argv[]); 14 | 15 | // Define the standard main function 16 | int main(int argc, char* argv[]) { 17 | #ifndef NO_LIBUNWIND 18 | vif::executable_path = argv[0]; 19 | #endif 20 | 21 | return vif_main(argc, argv); 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/vif/core/print.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_CORE_PRINT_HPP 2 | #define VIF_CORE_PRINT_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace vif { 10 | template 11 | void print(const T& t) { 12 | std::cout << t << std::endl; 13 | } 14 | 15 | template 16 | void print(const T& t, Args&&... args) { 17 | std::cout << t; 18 | print(std::forward(args)...); 19 | } 20 | 21 | template 22 | void error(Args&& ... args) { 23 | print("error: ", std::forward(args)...); 24 | } 25 | 26 | template 27 | void warning(Args&& ... args) { 28 | print("warning: ", std::forward(args)...); 29 | } 30 | 31 | template 32 | void note(Args&& ... args) { 33 | print("note: ", std::forward(args)...); 34 | } 35 | 36 | template 37 | bool prompt(const std::string& msg, T& value, const std::string& err_msg = "") { 38 | bool ok = false; 39 | 40 | do { 41 | std::cout << msg; 42 | std::string answer; 43 | std::getline(std::cin, answer); 44 | 45 | std::istringstream ss(std::move(answer)); 46 | ss >> value; 47 | 48 | if (!ss.fail()) { 49 | if (ss.eof()) { 50 | ok = true; 51 | } else { 52 | std::string rem; 53 | ss >> rem; 54 | ok = rem.find_first_not_of(" \t") == rem.npos; 55 | } 56 | } else { 57 | ok = false; 58 | } 59 | 60 | if (!ok) { 61 | if (!err_msg.empty()) { 62 | error(err_msg); 63 | } 64 | } 65 | } while (!ok); 66 | 67 | return ok; 68 | } 69 | } 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /include/vif/core/typedefs.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_CORE_TYPEDEF_HPP 2 | #define VIF_CORE_TYPEDEF_HPP 3 | 4 | #include 5 | 6 | namespace vif { 7 | // Type shortcuts 8 | using int_t = std::ptrdiff_t; 9 | using uint_t = std::size_t; 10 | 11 | // npos is the largest positive integer, used for signalling the end of a sequence, 12 | // or referencing an invalid position in a sequence (e.g., for a non-existing element) 13 | static const uint_t npos = uint_t(-1); 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /include/vif/io/fits/file.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_IO_FITS_FILE_HPP 2 | #define VIF_IO_FITS_FILE_HPP 3 | 4 | #include "vif/io/fits/image.hpp" 5 | #include "vif/io/fits/table.hpp" 6 | 7 | #ifndef NO_CFITSIO 8 | 9 | namespace vif { 10 | namespace fits { 11 | class input_file : public fits::input_image, public fits::input_table { 12 | public : 13 | explicit input_file(const std::string& filename) : 14 | impl::fits_impl::file_base(impl::fits_impl::generic_file, filename, impl::fits_impl::read_only), 15 | input_image(filename), input_table(filename) {} 16 | 17 | input_file(input_file&&) noexcept = default; 18 | }; 19 | 20 | class output_file : public fits::output_image, public fits::output_table { 21 | public : 22 | explicit output_file(const std::string& filename) : 23 | impl::fits_impl::file_base(impl::fits_impl::generic_file, filename, impl::fits_impl::write_only), 24 | output_image(filename), output_table(filename) {} 25 | 26 | output_file(output_file&&) noexcept = default; 27 | }; 28 | 29 | class file : public fits::image, public fits::table { 30 | public : 31 | explicit file(const std::string& filename) : 32 | impl::fits_impl::file_base(impl::fits_impl::generic_file, filename, impl::fits_impl::read_write), 33 | image(filename), table(filename) {} 34 | 35 | file(file&&) noexcept = default; 36 | }; 37 | } 38 | } 39 | 40 | #endif 41 | #endif 42 | -------------------------------------------------------------------------------- /include/vif/math/lapack.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_MATH_LAPACK_HPP 2 | #define VIF_MATH_LAPACK_HPP 3 | 4 | // LAPACK functions imported from fortran library 5 | // ---------------------------------------------- 6 | 7 | namespace lapack { 8 | extern "C" void dgetrf_(int* n, int* m, double* a, int* lda, int* ipiv, int* info); 9 | extern "C" void dgetri_(int* n, double* a, int* lda, int* ipiv, double* work, int* lwork, 10 | int* info); 11 | extern "C" void dgesv_(int* n, int* nrhs, double* a, int* lda, int* ipiv, double* b, 12 | int* ldb, int* info); 13 | extern "C" void dgesdd_(char* jobz, int* m, int* n, double* a, int* lda, double* s, double* u, 14 | int* ldu, double* vt, int* ldvt, double* work, int* lwork, int* iwork, int* info); 15 | 16 | extern "C" void dsytrf_(char* uplo, int* n, double* a, int* lda, int* ipiv, double* work, 17 | int* lwork, int* info); 18 | extern "C" void dsytri_(char* uplo, int* n, double* a, int* lda, int* ipiv, double* work, 19 | int* info); 20 | extern "C" void dsysv_(char* uplo, int* n, int* nrhs, double* a, int* lda, int* ipiv, double* b, 21 | int* ldb, double* work, int* lwork, int* info); 22 | extern "C" void dsyev_(char* jobz, char* uplo, int* n, double* a, int* lda, double* w, 23 | double* work, int* lwork, int* info); 24 | 25 | extern "C" void dpotrf_(char* uplo, int* n, double* a, int* lda, int* info); 26 | extern "C" void dpotri_(char* uplo, int* n, double* a, int* lda, int* info); 27 | extern "C" void dpotrs_(char* uplo, int* n, int* nrhs, const double* a, int* lda, double* b, 28 | int* ldb, int* info); 29 | 30 | extern "C" void dtrtri_(char* uplo, char* diag, int* n, double* a, int* lda, int* info); 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/vif/math/matrix.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_MATH_MATRIX_HPP 2 | #define VIF_MATH_MATRIX_HPP 3 | 4 | #ifndef NO_LAPACK 5 | #include "vif/math/lapack.hpp" 6 | #endif 7 | #include "vif/core/vec.hpp" 8 | #include "vif/core/error.hpp" 9 | #include "vif/core/range.hpp" 10 | #include "vif/math/base.hpp" 11 | 12 | #define VIF_INCLUDING_MATH_MATRIX_BITS 13 | #include "vif/math/bits/matrix-types.hpp" 14 | #include "vif/math/bits/matrix-functions.hpp" 15 | #undef VIF_INCLUDING_MATH_MATRIX_BITS 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/vif/math/transform.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_MATH_TRANSFORM_HPP 2 | #define VIF_MATH_TRANSFORM_HPP 3 | 4 | #include "vif/core/vec.hpp" 5 | #include "vif/core/error.hpp" 6 | #include "vif/core/range.hpp" 7 | #include "vif/math/interpolate.hpp" 8 | 9 | namespace vif { 10 | // Perform the convolution of two 1D arrays, assuming that they are based on the same 'x' coordinate 11 | template 12 | auto convolve(const vec<1,TypeX>& x, const vec<1,TypeY1>& y1, const vec<1,TypeY2>& y2) -> 13 | vec<1,decltype(x[0]*y1[0]*y2[0])> { 14 | 15 | vif_check(x.dims == y1.dims, "incompatible dimensions for X and Y1 " 16 | "(", x.dims, " vs. ", y1.dims, ")"); 17 | vif_check(x.dims == y2.dims, "incompatible dimensions for X and Y2 " 18 | "(", x.dims, " vs. ", y2.dims, ")"); 19 | vif_check(x.size() > 3, "convolve needs arrays of at least 3 elements to work " 20 | "(got ", x.size(), ")"); 21 | 22 | vec<1,decltype(x[0]*y1[0]*y2[0])> r(x.size()); 23 | for (uint_t i : range(x)) { 24 | auto dx = x.safe[i]; 25 | if (i == 0) dx = x.safe[i+1] - dx; 26 | else dx -= x.safe[i-1]; 27 | 28 | auto tmp = interpolate(y2, x + x.safe[i], x); 29 | r += y1.safe[i]*tmp*dx; 30 | } 31 | 32 | return r; 33 | } 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /include/vif/test/unit_test.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_TEST_UNIT_TEST_HPP 2 | #define VIF_TEST_UNIT_TEST_HPP 3 | 4 | #include "vif/core/vec.hpp" 5 | #include "vif/core/print.hpp" 6 | #include "vif/core/string_conversion.hpp" 7 | #include "vif/math/base.hpp" 8 | 9 | namespace vif { 10 | uint_t tested = 0u; 11 | uint_t failed = 0u; 12 | 13 | bool reduce_and(bool b) { 14 | return b; 15 | } 16 | 17 | template 18 | bool reduce_and(const vec& b) { 19 | bool res = true; 20 | for (bool v : b) { 21 | res = res && v; 22 | } 23 | return res; 24 | } 25 | 26 | namespace impl { 27 | template 28 | struct is_float_ : std::false_type { 29 | }; 30 | template<> 31 | struct is_float_ : std::true_type { 32 | }; 33 | template<> 34 | struct is_float_ : std::true_type { 35 | }; 36 | template 37 | struct is_float_> : is_float_::type> { 38 | }; 39 | } 40 | 41 | template 42 | struct is_float : std::integral_constant::value || impl::is_float_::value> { 43 | }; 44 | 45 | namespace impl { 46 | template 47 | auto is_same_(const T1& v1, const T2& v2, std::false_type) -> decltype(v1 == v2) { 48 | return v1 == v2; 49 | } 50 | 51 | template 52 | auto is_same_(const T1& v1, const T2& v2, std::true_type) -> decltype(v1 == v2) { 53 | return abs(v1 - v2) <= std::numeric_limits::epsilon() || 54 | (is_nan(v1) && is_nan(v2)) || is_nan(v1 - v2); 55 | } 56 | } 57 | 58 | template 59 | auto is_same(const T1& v1, const T2& v2) -> decltype(v1 == v2) { 60 | return impl::is_same_(v1, v2, is_float{}); 61 | } 62 | 63 | static bool check_show_line = false; 64 | 65 | #define check_base_(cond, msg, file, line) do { \ 66 | if (check_show_line) print(std::string(file)+":"+to_string(line)); \ 67 | if (!cond) { \ 68 | print(msg); \ 69 | ++failed; \ 70 | } \ 71 | ++tested; \ 72 | } while (false) 73 | 74 | #define check_base(cond, msg) check_base_(reduce_and(cond), msg, __FILE__, __LINE__) 75 | 76 | #define check(t, s) \ 77 | check_base(is_same(t, s), " failed: "+std::string(#t)+" = "+to_string(t)+" != "+to_string(s)) 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/vif/utility/bits/generic-dims.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_GENERIC_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/generic.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | template::value>::type> 7 | T flatten(T&& t) { 8 | return t; 9 | } 10 | 11 | template 12 | vec<1,Type> flatten(const vec& v) { 13 | vec<1,Type> r; 14 | r.dims[0] = v.data.size(); 15 | r.data = v.data; 16 | return r; 17 | } 18 | 19 | template 20 | vec<1,Type> flatten(vec&& v) { 21 | vec<1,Type> r; 22 | r.dims[0] = v.data.size(); 23 | r.data = std::move(v.data); 24 | return r; 25 | } 26 | 27 | template 28 | vec<1,Type*> flatten(const vec& v) { 29 | vec<1,Type*> r(impl::vec_ref_tag, v.parent); 30 | r.dims[0] = v.data.size(); 31 | r.data = v.data; 32 | return r; 33 | } 34 | 35 | template 36 | vec<1,Type*> flatten(vec&& v) { 37 | vec<1,Type*> r(impl::vec_ref_tag, v.parent); 38 | r.dims[0] = v.data.size(); 39 | r.data = std::move(v.data); 40 | return r; 41 | } 42 | 43 | template 44 | vec::value, Type> reform(const vec& v, Args&& ... args) { 45 | vec::value, Type> r; 46 | impl::set_array(r.dims, std::forward(args)...); 47 | uint_t nsize = 1; 48 | for (uint_t i : range(meta::dim_total::value)) { 49 | nsize *= r.dims[i]; 50 | } 51 | 52 | vif_check(v.size() == nsize, 53 | "incompatible dimensions (", v.dims, " vs ", r.dims, ")"); 54 | 55 | r.data = v.data; 56 | 57 | return r; 58 | } 59 | 60 | template 61 | vec::value, Type> reform(vec&& v, Args&& ... args) { 62 | vec::value, Type> r; 63 | impl::set_array(r.dims, std::forward(args)...); 64 | uint_t nsize = 1; 65 | for (uint_t i : range(meta::dim_total::value)) { 66 | nsize *= r.dims[i]; 67 | } 68 | 69 | vif_check(v.size() == nsize, 70 | "incompatible dimensions (", v.dims, " vs ", r.dims, ")"); 71 | 72 | r.data = std::move(v.data); 73 | 74 | return r; 75 | } 76 | 77 | template 78 | vec::value, Type*> reform(const vec& v, Args&& ... args) { 79 | vec::value, Type*> r(impl::vec_ref_tag, v.parent); 80 | impl::set_array(r.dims, std::forward(args)...); 81 | uint_t nsize = 1; 82 | for (uint_t i : range(meta::dim_total::value)) { 83 | nsize *= r.dims[i]; 84 | } 85 | 86 | vif_check(v.size() == nsize, 87 | "incompatible dimensions (", v.dims, " vs ", r.dims, ")"); 88 | 89 | r.data = v.data; 90 | 91 | return r; 92 | } 93 | 94 | template 95 | vec::value, Type*> reform(vec&& v, Args&& ... args) { 96 | vec::value, Type*> r(impl::vec_ref_tag, v.parent); 97 | impl::set_array(r.dims, std::forward(args)...); 98 | uint_t nsize = 1; 99 | for (uint_t i : range(meta::dim_total::value)) { 100 | nsize *= r.dims[i]; 101 | } 102 | 103 | vif_check(v.size() == nsize, 104 | "incompatible dimensions (", v.dims, " vs ", r.dims, ")"); 105 | 106 | r.data = std::move(v.data); 107 | 108 | return r; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /include/vif/utility/bits/generic-indices.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_GENERIC_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/generic.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | // Get multi-dim IDs from a flat ID 7 | template 8 | vec1u mult_ids(const std::array& dims, uint_t i) { 9 | vec1u r(D); 10 | 11 | for (uint_t j : range(D)) { 12 | r.safe[D-1-j] = i % dims[D-1-j]; 13 | i /= dims[D-1-j]; 14 | } 15 | 16 | return r; 17 | } 18 | 19 | template 20 | vec2u mult_ids(const std::array& dims, vec1u i) { 21 | vec2u r(D,i.size()); 22 | 23 | for (uint_t j : range(D)) { 24 | r.safe(D-1-j,_) = i % dims[D-1-j]; 25 | i /= dims[D-1-j]; 26 | } 27 | 28 | return r; 29 | } 30 | 31 | template 32 | vec1u mult_ids(const vec& v, uint_t i) { 33 | return mult_ids(v.dims, i); 34 | } 35 | 36 | template 37 | vec2u mult_ids(const vec& v, vec1u i) { 38 | return mult_ids(v.dims, i); 39 | } 40 | 41 | // Get flat ID from multi-dim IDs 42 | namespace impl { 43 | template 44 | uint_t flat_id_(const std::array&, uint_t ret, meta::cte_t) { 45 | return ret; 46 | } 47 | 48 | template 49 | uint_t flat_id_(const std::array& dims, uint_t ret, 50 | meta::cte_t, U i, Args&& ... args) { 51 | 52 | uint_t di = impl::vec_access::pitch(dims, I)* 53 | impl::vec_access::template to_idx(dims, i); 54 | return flat_id_(dims, ret + di, meta::cte_t{}, 55 | std::forward(args)...); 56 | } 57 | 58 | template 59 | uint_t flat_id_(const std::array& dims, uint_t ret, 60 | meta::cte_t, const vec<1,TI>& ids) { 61 | 62 | uint_t di = impl::vec_access::pitch(dims, I)* 63 | impl::vec_access::template to_idx(dims, ids[I]); 64 | return flat_id_(dims, ret + di, meta::cte_t{}, ids); 65 | } 66 | } 67 | 68 | template 69 | uint_t flat_id(const std::array& dims, Args&& ... args) { 70 | static_assert(sizeof...(Args) == D, "wrong number of IDs provided"); 71 | return impl::flat_id_(dims, 0, meta::cte_t<0>{}, std::forward(args)...); 72 | } 73 | 74 | template 75 | uint_t flat_id(const vec& v, Args&& ... args) { 76 | return flat_id(v.dims, std::forward(args)...); 77 | } 78 | 79 | template 80 | uint_t flat_id(const std::array& dims, const vec<1,TI>& ids) { 81 | vif_check(ids.size() == D, "wrong number of IDs provided"); 82 | return impl::flat_id_(dims, meta::cte_t<0>{}, ids); 83 | } 84 | 85 | template 86 | uint_t flat_id(const vec& v, const vec<1,TI>& ids) { 87 | return flat_id(v.dims, ids); 88 | } 89 | 90 | // Increment a list of indices, step by step 91 | // This is an alternative to a recursive loop. 92 | inline void increment_index_list(vec1u& ids, const vec1u& n) { 93 | uint_t i = ids.size(); 94 | do { 95 | --i; 96 | ++(ids.safe[i]); 97 | if (ids.safe[i] == n.safe[i]) { 98 | ids.safe[i] = 0; 99 | } else { 100 | break; 101 | } 102 | } while (i != 0); 103 | } 104 | 105 | inline void increment_index_list(vec1u& ids, const uint_t& n) { 106 | uint_t i = ids.size(); 107 | do { 108 | --i; 109 | ++(ids.safe[i]); 110 | if (ids.safe[i] == n) { 111 | ids.safe[i] = 0; 112 | } else { 113 | break; 114 | } 115 | } while (i != 0); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /include/vif/utility/bits/generic-sequences.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_GENERIC_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/generic.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | // Generate linearly increasing values. 7 | template 8 | vec::value,T> indgen(Dims&& ... ds) { 9 | vec::value,T> v(std::forward(ds)...); 10 | std::iota(v.begin(), v.end(), static_cast(0)); 11 | return v; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /include/vif/utility/bits/string-base.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_STRING_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/string.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | inline uint_t length(const std::string& s) { 7 | return s.size(); 8 | } 9 | 10 | inline bool empty(const std::string& s) { 11 | return s.empty(); 12 | } 13 | 14 | inline std::string keep_first(std::string s, uint_t n = 1) { 15 | if (s.size() > n) { 16 | s.erase(n); 17 | } 18 | 19 | return s; 20 | } 21 | 22 | inline std::string keep_last(std::string s, uint_t n = 1) { 23 | if (s.size() > n) { 24 | s.erase(0, s.size()-n); 25 | } 26 | 27 | return s; 28 | } 29 | 30 | inline uint_t distance(const std::string& t, const std::string& u) { 31 | uint_t n, d; 32 | if (t.size() < u.size()) { 33 | n = t.size(); 34 | d = u.size() - t.size(); 35 | } else { 36 | n = u.size(); 37 | d = t.size() - u.size(); 38 | } 39 | 40 | for (uint_t i : range(n)) { 41 | if (t[i] != u[i]) ++d; 42 | } 43 | 44 | return d; 45 | } 46 | 47 | VIF_VECTORIZE(length) 48 | VIF_VECTORIZE(empty) 49 | VIF_VECTORIZE(distance) 50 | VIF_VECTORIZE(keep_first) 51 | VIF_VECTORIZE(keep_last) 52 | } 53 | -------------------------------------------------------------------------------- /include/vif/utility/bits/string-format.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_STRING_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/string.hpp" instead 3 | #endif 4 | 5 | #include 6 | 7 | namespace vif { 8 | inline char to_upper(char c) { 9 | return std::toupper(static_cast(c)); 10 | } 11 | 12 | inline char to_lower(char c) { 13 | return std::tolower(static_cast(c)); 14 | } 15 | 16 | inline unsigned char to_upper(unsigned char c) { 17 | return std::toupper(c); 18 | } 19 | 20 | inline unsigned char to_lower(unsigned char c) { 21 | return std::tolower(c); 22 | } 23 | 24 | inline std::string to_upper(std::string s) { 25 | for (auto& c : s) { 26 | c = to_upper(c); 27 | } 28 | return s; 29 | } 30 | 31 | inline std::string to_lower(std::string s) { 32 | for (auto& c : s) { 33 | c = to_lower(c); 34 | } 35 | return s; 36 | } 37 | 38 | inline std::string align_left(std::string s, uint_t width, char fill = ' ') { 39 | if (s.size() < width) { 40 | s += std::string(width-s.size(), fill); 41 | } 42 | 43 | return s; 44 | } 45 | 46 | inline std::string align_right(std::string s, uint_t width, char fill = ' ') { 47 | if (s.size() < width) { 48 | s.insert(0, std::string(width-s.size(), fill)); 49 | } 50 | 51 | return s; 52 | } 53 | 54 | inline std::string align_center(std::string s, uint_t width, char fill = ' ') { 55 | if (s.size() < width) { 56 | uint_t n1 = (width-s.size())/2, n2 = width-s.size() - n1; 57 | s.insert(0, std::string(n1, fill)); 58 | s += std::string(n2, fill); 59 | } 60 | 61 | return s; 62 | } 63 | 64 | VIF_VECTORIZE(to_upper) 65 | VIF_VECTORIZE(to_lower) 66 | VIF_VECTORIZE(align_left) 67 | VIF_VECTORIZE(align_right) 68 | VIF_VECTORIZE(align_center) 69 | 70 | namespace terminal_format { 71 | inline void header(const std::string& msg) { 72 | vec1s w = wrap(" "+msg, 80, " "); 73 | for (auto& s : w) { 74 | print(s); 75 | } 76 | } 77 | 78 | inline void paragraph(const std::string& msg) { 79 | vec1s w = wrap(" "+msg, 80, " "); 80 | for (auto& s : w) { 81 | print(s); 82 | } 83 | print(""); 84 | } 85 | 86 | inline void bullet(const std::string& name, const std::string& desc) { 87 | std::string header = " "+name+": "; 88 | vec1s w = wrap(header+desc, 80, std::string(header.size(), ' ')); 89 | for (auto& s : w) { 90 | print(s); 91 | } 92 | } 93 | 94 | inline void item(const std::string& msg) { 95 | std::string header = " - "; 96 | vec1s w = wrap(header+msg, 80, std::string(header.size(), ' ')); 97 | for (auto& s : w) { 98 | print(s); 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /include/vif/utility/bits/string-split.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_STRING_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/string.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | template 7 | vec1s split(const std::string& ts, const T& pattern) { 8 | vec1s ret; 9 | std::size_t p = 0, op = 0; 10 | while ((p = ts.find(pattern, op)) != ts.npos) { 11 | ret.data.push_back(ts.substr(op, p - op)); 12 | op = p + length(pattern); 13 | } 14 | 15 | ret.data.push_back(ts.substr(op)); 16 | ret.dims[0] = ret.size(); 17 | 18 | return ret; 19 | } 20 | 21 | template 22 | vec1s split_any_of(const std::string& ts, const T& chars) { 23 | vec1s ret; 24 | std::size_t op = ts.find_first_not_of(chars); 25 | std::size_t p = op; 26 | while ((p = ts.find_first_of(chars, op)) != ts.npos) { 27 | ret.data.push_back(ts.substr(op, p - op)); 28 | op = ts.find_first_not_of(chars, p); 29 | } 30 | 31 | if (op != ts.npos) { 32 | ret.data.push_back(ts.substr(op)); 33 | } 34 | 35 | ret.dims[0] = ret.size(); 36 | 37 | return ret; 38 | } 39 | 40 | inline vec1s cut(const std::string& ts, uint_t size) { 41 | uint_t ncut = floor(ts.size()/float(size)); 42 | vec1s res(ncut); 43 | for (uint_t i = 0; i < ncut; ++i) { 44 | res.safe[i] = ts.substr(i*size, std::min(size, ts.size() - i*size)); 45 | } 46 | 47 | return res; 48 | } 49 | 50 | inline vec1s wrap(const std::string& ts, uint_t width, const std::string& indent = "", bool ellipse = false) { 51 | vec1s ret; 52 | std::string s = ts; 53 | uint_t twidth = width; 54 | std::string header = ""; 55 | while (s.size() > twidth) { 56 | uint_t i = twidth; 57 | while (i != npos && s[i] != ' ') --i; 58 | if (i == npos) { 59 | if (ellipse) { 60 | ret.push_back(header+s.substr(0, twidth-3)+"..."); 61 | i = twidth+1; 62 | while (i < s.size() && s[i] != ' ') ++i; 63 | s.erase(0, i); 64 | s = trim(s); 65 | } else { 66 | i = twidth+1; 67 | while (i < s.size() && s[i] != ' ') ++i; 68 | ret.push_back(header+s.substr(0, i)); 69 | s.erase(0, i); 70 | s = trim(s); 71 | } 72 | } else { 73 | ret.push_back(header+s.substr(0, i)); 74 | s.erase(0, i); 75 | s = trim(s); 76 | } 77 | 78 | twidth = width - indent.size(); 79 | header = indent; 80 | } 81 | 82 | if (!s.empty()) { 83 | ret.push_back(header+s); 84 | } 85 | 86 | return ret; 87 | } 88 | 89 | template::type, std::string>::value>::type> 91 | std::string collapse(const vec& v) { 92 | std::string r; 93 | for (auto& s : v) { 94 | r += s; 95 | } 96 | 97 | return r; 98 | } 99 | 100 | template::type, std::string>::value>::type> 102 | std::string collapse(const vec& v, const std::string& sep) { 103 | std::string r; 104 | bool first = true; 105 | for (auto& s : v) { 106 | if (!first) r += sep; 107 | r += s; 108 | first = false; 109 | } 110 | 111 | return r; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /include/vif/utility/bits/thread-thread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_THREAD_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/thread.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | namespace thread { 7 | struct thread_t { 8 | std::unique_ptr impl; 9 | 10 | template 11 | void start(F&& f, Args&& ... args) { 12 | impl = std::unique_ptr(new std::thread( 13 | std::forward(f), std::forward(args)... 14 | )); 15 | } 16 | 17 | void join() { 18 | impl->join(); 19 | } 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /include/vif/utility/bits/thread-utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_THREAD_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/thread.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | namespace thread { 7 | using pool_t = std::vector; 8 | 9 | inline pool_t pool(uint_t n) { 10 | return pool_t(n); 11 | } 12 | 13 | inline void sleep_for(double duration) { 14 | std::this_thread::sleep_for(std::chrono::microseconds(uint_t(duration*1e6))); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /include/vif/utility/bits/thread-worker.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_INCLUDING_THREAD_BITS 2 | #error this file is not meant to be included separately, include "vif/utilty/thread.hpp" instead 3 | #endif 4 | 5 | namespace vif { 6 | namespace thread { 7 | class worker { 8 | std::atomic stop_on_empty_; 9 | lock_free_queue> jobs_; 10 | std::unique_ptr thread_; 11 | 12 | void consume_loop_() { 13 | while (!stop_on_empty_ || !jobs_.empty()) { 14 | std::function job; 15 | while (jobs_.pop(job)) { 16 | job(); 17 | } 18 | 19 | sleep_for(0.05); 20 | } 21 | } 22 | 23 | public : 24 | 25 | worker() : stop_on_empty_(false) {} 26 | 27 | ~worker() { 28 | wait(); 29 | } 30 | 31 | void push(std::function job) { 32 | if (!thread_) { 33 | thread_ = std::unique_ptr(new std::thread( 34 | &worker::consume_loop_, this 35 | )); 36 | } 37 | 38 | jobs_.push(std::move(job)); 39 | } 40 | 41 | void wait() { 42 | if (thread_ && thread_->joinable()) { 43 | stop_on_empty_ = true; 44 | thread_->join(); 45 | thread_ = nullptr; 46 | stop_on_empty_ = false; 47 | } 48 | } 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /include/vif/utility/generic.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_UTILITY_GENERIC_HPP 2 | #define VIF_UTILITY_GENERIC_HPP 3 | 4 | #include 5 | 6 | #include "vif/core/vec.hpp" 7 | #include "vif/core/meta.hpp" 8 | #include "vif/core/range.hpp" 9 | #include "vif/core/error.hpp" 10 | #include "vif/core/string_conversion.hpp" 11 | 12 | #define VIF_INCLUDING_GENERIC_BITS 13 | #include "vif/utility/bits/generic-sequences.hpp" 14 | #include "vif/utility/bits/generic-indices.hpp" 15 | #include "vif/utility/bits/generic-dims.hpp" 16 | #include "vif/utility/bits/generic-find.hpp" 17 | #include "vif/utility/bits/generic-rearrange.hpp" 18 | #undef VIF_INCLUDING_GENERIC_BITS 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/vif/utility/os.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_UTILITY_OS_HPP 2 | #define VIF_UTILITY_OS_HPP 3 | 4 | #include 5 | #include 6 | #include "vif/core/string_conversion.hpp" 7 | 8 | namespace vif { 9 | template 10 | T system_var(const std::string& name, U def) { 11 | char* v = getenv(name.c_str()); 12 | if (!v) return def; 13 | 14 | T ret; 15 | if (!from_string(v, ret)) return def; 16 | return ret; 17 | } 18 | 19 | inline std::string system_var(const std::string& name, std::string def) { 20 | char* v = getenv(name.c_str()); 21 | if (!v) return def; 22 | return v; 23 | } 24 | 25 | inline std::string system_var(const std::string& name, const char* def) { 26 | return system_var(name, std::string(def)); 27 | } 28 | 29 | inline bool fork(const std::string& cmd) { 30 | return system((cmd+" &").c_str()) == 0; 31 | } 32 | 33 | inline bool spawn(const std::string& cmd) { 34 | return system(cmd.c_str()) == 0; 35 | } 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/vif/utility/string.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_UTILITY_STRING_HPP 2 | #define VIF_UTILITY_STRING_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "vif/core/vec.hpp" 10 | #include "vif/core/error.hpp" 11 | #include "vif/core/range.hpp" 12 | #include "vif/core/string_conversion.hpp" 13 | #include "vif/utility/generic.hpp" 14 | 15 | #define VIF_INCLUDING_STRING_BITS 16 | #include "vif/utility/bits/string-base.hpp" 17 | #include "vif/utility/bits/string-find-replace.hpp" 18 | #include "vif/utility/bits/string-split.hpp" 19 | #include "vif/utility/bits/string-format.hpp" 20 | #include "vif/utility/bits/string-regex.hpp" 21 | #include "vif/utility/bits/string-hash.hpp" 22 | #undef VIF_INCLUDING_STRING_BITS 23 | 24 | #endif 25 | 26 | -------------------------------------------------------------------------------- /include/vif/utility/thread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VIF_UTILITY_THREAD_HPP 2 | #define VIF_UTILITY_THREAD_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "vif/core/vec.hpp" 9 | 10 | #define VIF_INCLUDING_THREAD_BITS 11 | #include "vif/utility/bits/thread-thread.hpp" 12 | #include "vif/utility/bits/thread-utils.hpp" 13 | #include "vif/utility/bits/thread-queue.hpp" 14 | #include "vif/utility/bits/thread-worker.hpp" 15 | #include "vif/utility/bits/thread-worker-pool.hpp" 16 | #include "vif/utility/bits/thread-parallel-for.hpp" 17 | #undef VIF_INCLUDING_THREAD_BITS 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /python/pycolfits.py: -------------------------------------------------------------------------------- 1 | from astropy.io import fits 2 | import numpy as np 3 | import re 4 | 5 | def readfrom(filename, lower_case=False, upper_case=False, **kwargs): 6 | # Open the file and get HDU list 7 | hdulist = fits.open(filename, **kwargs) 8 | 9 | # Column-oriented FITS tables have empty primary HDU 10 | # The actual data is located inside the first HDU 11 | if len(hdulist) == 1: 12 | raise RuntimeError('this is not a column-oriented FITS table') 13 | 14 | hdr = hdulist[1].header 15 | data = hdulist[1].data[0] 16 | 17 | # Create columns one by one 18 | tbl = dict() 19 | for c in hdulist[1].columns: 20 | # Store that into the dictionary 21 | if lower_case: 22 | cname = c.name.lower() 23 | elif upper_case: 24 | cname = c.name.upper() 25 | else: 26 | cname = c.name 27 | 28 | # Check the length of columns to avoid any empty ones, 29 | # as astropy is not able to read empty columns. 30 | if c.dim is not None and re.search(r'[(,]0[),]', c.dim) is None: 31 | tbl[cname] = data[c.name] 32 | else: 33 | tbl[cname] = np.array(()) 34 | 35 | return tbl 36 | 37 | def _get_format_code(v): 38 | # Convert numpy type code into FITS 39 | if isinstance(v, str): 40 | dims = () 41 | tdtype = 'S'+str(len(v)) 42 | else : 43 | if isinstance(v, np.ndarray): 44 | dims = v.shape 45 | else: 46 | dims = () 47 | 48 | tdtype = v.dtype.str.replace('>','').replace('<','').replace('|','') 49 | 50 | if isinstance(v, np.chararray): 51 | tdtype = tdtype.replace('U', 'S') 52 | 53 | if tdtype[0] == 'S': 54 | # Strings are handled in a peculiar way in FITS 55 | # They are stored as multi-dimensional array of bytes 56 | # and the last dimension is the maximum length of all 57 | # strings in the array 58 | strlen = int(tdtype[1:]) 59 | tdtype = 'a' 60 | dims = dims + (strlen,) 61 | 62 | if len(dims) == 0: 63 | repeat = '' 64 | dims = (1,) 65 | else: 66 | repeat = str(np.prod(dims)) 67 | 68 | tform = repeat+fits.column.NUMPY2FITS[tdtype] 69 | tdim = '('+','.join(str(d) for d in reversed(dims))+')' 70 | 71 | return tform, tdim 72 | 73 | def writeto(filename, data, lower_case=False, upper_case=False, **kwargs): 74 | # Build the ColDef array 75 | cols = fits.ColDefs([]) 76 | for colname, value in data.items(): 77 | # Figure out which FITS format to use to store this column 78 | tform, tdim = _get_format_code(value) 79 | 80 | if lower_case: 81 | cname = colname.lower() 82 | elif upper_case: 83 | cname = colname.upper() 84 | else: 85 | cname = colname 86 | 87 | # Add new column to the list 88 | cols.add_col(fits.Column( 89 | name=cname, 90 | format=tform, 91 | dim=tdim)) 92 | 93 | # Create the FITS table in memory 94 | hdu = fits.BinTableHDU.from_columns(cols, nrows=1, fill=True) 95 | for colname, value in data.items(): 96 | if lower_case: 97 | cname = colname.lower() 98 | elif upper_case: 99 | cname = colname.upper() 100 | else: 101 | cname = colname 102 | 103 | hdu.data[cname] = value 104 | 105 | # Write it on the disk 106 | hdu.writeto(filename, **kwargs) 107 | 108 | 109 | -------------------------------------------------------------------------------- /sublime/vif/DataFile.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | fileTypes 6 | 7 | dat 8 | cat 9 | tbl 10 | 11 | name 12 | Data file 13 | patterns 14 | 15 | 16 | scopeName 17 | source.data 18 | 19 | 20 | -------------------------------------------------------------------------------- /sublime/vif/vif.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | vif include & main 3 | 4 | 5 | int vif_main(int argc, char* argv[]) { 6 | ${0} 7 | 8 | return 0; 9 | } 10 | ]]> 11 | vif 12 | source.c++, source.objc++ 13 | 14 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | ._reflex* 3 | unit_test 4 | plot_test 5 | -------------------------------------------------------------------------------- /test/data/image.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/test/data/image.fits -------------------------------------------------------------------------------- /test/data/psf.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/test/data/psf.fits -------------------------------------------------------------------------------- /test/data/sources.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/test/data/sources.fits -------------------------------------------------------------------------------- /test/data/stack1.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/test/data/stack1.fits -------------------------------------------------------------------------------- /test/data/stack2.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/test/data/stack2.fits -------------------------------------------------------------------------------- /test/data/table.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cschreib/vif/705b13681f7f8563debf9801c9f03ac1eff1e07f/test/data/table.fits -------------------------------------------------------------------------------- /test/data/table.txt: -------------------------------------------------------------------------------- 1 | # header 2 | # id1 id2 3 | 0 0 4 | 1 1 5 | 2 3 6 | 3 5 7 | 8 | 4 9 9 | -------------------------------------------------------------------------------- /test/fits/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | 5 | #define check(t, s) { \ 6 | std::string st = to_string(t); \ 7 | if (st == s) print(" checked: "+st); \ 8 | else print(" failed: "+std::string(#t)+" = "+st+" != "+s); \ 9 | assert(st == s); \ 10 | } 11 | 12 | int vif_main(int argc, char* argv[]) { 13 | vec1u id = uindgen(100); 14 | vec1s sid = to_string_vector(reverse(id)); 15 | 16 | { 17 | fits::write_table("col_1d.fits", ftable(id, sid)); 18 | } 19 | 20 | { 21 | vec1u tid; 22 | vec1s tsid; 23 | fits::read_table("col_1d.fits", "id", tid, "sid", tsid); 24 | 25 | check(count(tid != id), "0"); 26 | check(count(tsid != sid), "0"); 27 | } 28 | 29 | { 30 | fits::output_table otbl("row_1d.fits"); 31 | otbl.set_format(fits::output_format::row_oriented); 32 | otbl.write_columns(ftable(id, sid)); 33 | } 34 | 35 | { 36 | vec1u tid; 37 | vec1s tsid; 38 | fits::read_table("row_1d.fits", "id", tid, "sid", tsid); 39 | 40 | check(count(tid != id), "0"); 41 | check(count(tsid != sid), "0"); 42 | } 43 | 44 | vec3u id2d = uindgen(3,5,100); 45 | vec3s sid2d = to_string_vector(id2d); 46 | 47 | { 48 | fits::write_table("col_2d.fits", ftable(id2d, sid2d)); 49 | } 50 | 51 | { 52 | vec3u tid2d; 53 | vec3s tsid2d; 54 | fits::read_table("col_2d.fits", "id2d", tid2d, "sid2d", tsid2d); 55 | 56 | check(count(tid2d != id2d), "0"); 57 | check(count(tsid2d != sid2d), "0"); 58 | } 59 | 60 | { 61 | fits::output_table otbl("row_2d.fits"); 62 | otbl.set_format(fits::output_format::row_oriented); 63 | otbl.write_columns(ftable(id2d, sid2d)); 64 | } 65 | 66 | { 67 | vec3u tid2d; 68 | vec3s tsid2d; 69 | fits::read_table("row_2d.fits", "id2d", tid2d, "sid2d", tsid2d); 70 | 71 | check(count(tid2d != id2d), "0"); 72 | check(count(tsid2d != sid2d), "0"); 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /test/unit/.gitignore: -------------------------------------------------------------------------------- 1 | vec 2 | -------------------------------------------------------------------------------- /test/unit/math/.gitignore: -------------------------------------------------------------------------------- 1 | fft 2 | bounds 3 | -------------------------------------------------------------------------------- /test/unit/math/bounds.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace vif; 5 | 6 | int vif_main(int argc, char* argv[]) { 7 | vec1i v; 8 | 9 | auto get_and_check = [&]() { 10 | auto res = bounds(v, 4, 7); 11 | check(res[0], lower_bound(v, 4)); 12 | check(res[1], upper_bound(v, 7)); 13 | return res; 14 | }; 15 | 16 | auto res = get_and_check(); 17 | check(res[0], npos); 18 | check(res[1], npos); 19 | 20 | v = {0,1}; 21 | 22 | res = get_and_check(); 23 | check(res[0], 1); 24 | check(res[1], npos); 25 | 26 | v = {0,10}; 27 | 28 | res = get_and_check(); 29 | check(res[0], 0); 30 | check(res[1], 1); 31 | 32 | v = {10,20}; 33 | 34 | res = get_and_check(); 35 | check(res[0], npos); 36 | check(res[1], 0); 37 | 38 | v = {2,3,4,5,6,7,8,9}; 39 | 40 | res = get_and_check(); 41 | check(res[0], 2); 42 | check(res[1], 6); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /test/unit/math/fft.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace vif; 5 | 6 | int vif_main(int argc, char* argv[]) { 7 | vec2d v = gaussian_profile({{41,41}}, 4.0) + 0.1*gaussian_profile({{41,41}}, 10.0); 8 | vec2cd cv = fft(v); 9 | vec2d iv = ifft(cv)/v.size(); 10 | 11 | for (uint_t i : range(v)) { 12 | check(v[i], iv[i]); 13 | } 14 | 15 | auto seed = make_seed(42); 16 | vec2d img = randomn(seed, 1000, 1000); 17 | vec2d psf = v; 18 | 19 | double st = now(); 20 | vec2d cimg1 = convolve2d(img, psf); 21 | double fast = now() - st; 22 | st = now(); 23 | vec2d cimg2 = convolve2d_naive(img, psf); 24 | double slow = now() - st; 25 | 26 | // TODO: investigate expected numerical precision of the FFT convolution algorithm 27 | for (uint_t i : range(v)) { 28 | check(cimg1[i], cimg2[i]); 29 | } 30 | 31 | print("fast version: ", fast); 32 | print("slow version: ", slow); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(vif-tools) 3 | 4 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/../cmake") 5 | find_package(vif) 6 | 7 | add_subdirectory(catinfo) 8 | add_subdirectory(findsrc) 9 | add_subdirectory(fitstool) 10 | add_subdirectory(getgal) 11 | add_subdirectory(imgtool) 12 | add_subdirectory(photinfo) 13 | add_subdirectory(psffit) 14 | add_subdirectory(qconvol) 15 | add_subdirectory(qaper) 16 | add_subdirectory(qmask) 17 | add_subdirectory(qregrid) 18 | add_subdirectory(qstack2) 19 | add_subdirectory(qxmatch2) 20 | add_subdirectory(subsrc) 21 | add_subdirectory(fluxcube) 22 | add_subdirectory(randsrc) 23 | add_subdirectory(radec2pix) 24 | add_subdirectory(sex2deg) 25 | add_subdirectory(deg2sex) 26 | add_subdirectory(angcorrel) 27 | add_subdirectory(fits2ascii) 28 | add_subdirectory(pixfit) 29 | -------------------------------------------------------------------------------- /tools/angcorrel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(angcorrel) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(angcorrel angcorrel.cpp) 6 | target_link_libraries(angcorrel ${VIF_LIBRARIES}) 7 | install(TARGETS angcorrel DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/angcorrel/angcorrel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | void print_help(); 7 | 8 | int vif_main(int argc, char* argv[]) { 9 | if (argc <= 2) { 10 | print_help(); 11 | return 0; 12 | } 13 | 14 | struct cat_t { 15 | vec1d ra, dec; 16 | }; 17 | 18 | cat_t cat; 19 | fits::read_table(argv[1], ftable(cat.ra, cat.dec)); 20 | 21 | cat_t fcat; 22 | fits::read_table(argv[2], ftable(fcat.ra, fcat.dec)); 23 | 24 | vec1d range = {1.0, 40.0}; 25 | uint_t nbin = 10; 26 | std::string out_file = "angcorrel.fits"; 27 | uint_t tseed = 42; 28 | 29 | read_args(argc-2, argv+2, arg_list(range, nbin, name(out_file, "out"), name(tseed, "seed"))); 30 | 31 | vec2d bins = e10(make_bins(log10(range[0]), log10(range[1]), nbin)); 32 | vec1d ang = 0.5*(bins(0,_) + bins(1,_)); 33 | 34 | auto hull = build_convex_hull(fcat.ra, fcat.dec); 35 | auto in_hull = [&](double ra, double dec) { 36 | return in_convex_hull(ra, dec, hull); 37 | }; 38 | 39 | vec1d rra, rdec; 40 | uint_t nsrc = cat.ra.size(); 41 | if (nsrc < 1000) nsrc = 1000; 42 | auto seed = make_seed(tseed); 43 | 44 | auto status = randpos_uniform_box(seed, nsrc, 45 | {min(hull.x), max(hull.x)}, 46 | {min(hull.y), max(hull.y)}, 47 | rra, rdec, in_hull 48 | ); 49 | 50 | if (!status.success) { 51 | error("could not generate random positions"); 52 | note(status.failure); 53 | return 1; 54 | } 55 | 56 | vec1d w = angcorrel(cat.ra, cat.dec, rra, rdec, bins); 57 | 58 | fits::write_table(out_file, ftable(bins, w, ang)); 59 | 60 | return 0; 61 | } 62 | 63 | void print_help() { 64 | using namespace terminal_format; 65 | 66 | print("angcorrel v1.0"); 67 | paragraph("usage: angcorrel cat.fits refcat.fits [range,nbin,out,seed]"); 68 | paragraph("Compute the angular two point correlation function of a given catalog " 69 | "'cat.fits'. The correlation is calculated using the Landy-Szalay estimator, by " 70 | "comparing against a random uniform distribution of points generated within the " 71 | "boundaries of the catalog 'refcat.fits'. The correlation function is written in " 72 | "a FITS file as column 'W', in units of counts per arcsec."); 73 | 74 | header("List of available command line options:"); 75 | bullet("range", "[float,float] angular range within which to compute the correlation " 76 | "function [arcsec] (default: [1,40])"); 77 | bullet("nbin", "[unsigned integer] number of angular bins (default: 10)"); 78 | bullet("out", "[string] output file name (default: angcorrel.fits)"); 79 | bullet("seed", "[unsigned integer] random seed for the generation of the random " 80 | "uniform positions (default: 42)"); 81 | } 82 | -------------------------------------------------------------------------------- /tools/catinfo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(catinfo) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(catinfo catinfo.cpp) 6 | target_link_libraries(catinfo ${VIF_LIBRARIES}) 7 | install(TARGETS catinfo DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/catinfo/catinfo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | int vif_main(int argc, char* argv[]) { 7 | if (argc < 2) return 0; 8 | 9 | bool version = false; 10 | std::string fcat = argv[1]; 11 | read_args(argc-1, argv+1, arg_list(version)); 12 | 13 | struct { 14 | std::string catalogs; 15 | std::string comments; 16 | std::string version; 17 | std::string changelog; 18 | } cat; 19 | 20 | fits::read_table_loose(fcat, ftable( 21 | cat.catalogs, cat.comments, cat.version, cat.changelog 22 | )); 23 | 24 | print(fcat+"\n"); 25 | 26 | if (version) { 27 | if (!cat.version.empty()) { 28 | print("version: "+cat.version); 29 | } 30 | if (!cat.changelog.empty()) { 31 | print(cat.changelog); 32 | } 33 | } else { 34 | if (!cat.comments.empty()) { 35 | print(cat.comments); 36 | } 37 | if (!cat.catalogs.empty()) { 38 | print(cat.catalogs); 39 | } 40 | } 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tools/deg2sex/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(deg2sex) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(deg2sex deg2sex.cpp) 6 | target_link_libraries(deg2sex ${VIF_LIBRARIES}) 7 | install(TARGETS deg2sex DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/deg2sex/deg2sex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | void print_help(); 7 | 8 | int vif_main(int argc, char* argv[]) { 9 | if (argc < 3) { 10 | print_help(); 11 | return 0; 12 | } 13 | 14 | double ra, dec; 15 | if (!from_string(argv[1], ra)) { 16 | error("could not read RA"); 17 | return 1; 18 | } 19 | if (!from_string(argv[2], dec)) { 20 | error("could not read Dec"); 21 | return 1; 22 | } 23 | 24 | std::string sra, sdec; 25 | deg2sex(ra, dec, sra, sdec); 26 | print(sra, " ", sdec); 27 | 28 | return 0; 29 | } 30 | 31 | void print_help() { 32 | print("deg2sex v1.0"); 33 | print("usage: deg2sex RA Dec"); 34 | } 35 | -------------------------------------------------------------------------------- /tools/findsrc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(findsrc) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(findsrc findsrc.cpp) 6 | target_link_libraries(findsrc ${VIF_LIBRARIES}) 7 | install(TARGETS findsrc DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/findsrc/findsrc.ans: -------------------------------------------------------------------------------- 1 | hmenu phy++ 2 | 3 | # Get regions around the selected point 4 | param findreg 5 | catalog menu Catalog gn|gs|uds|cosmos|cosmos2d 6 | regtxt entry Text 7 | nsrc entry Number 10 8 | end 9 | 10 | Find neighbors 11 | *.fits 12 | menu 13 | $param(findreg); findsrc /home/cschreib/programming/phypp/data/fits/$catalog/$catalog_cmp.fits $regions(source,xy,wcs,fk5,degrees) region=/tmp/ds9.reg show=[$regtxt] region_text=[$regtxt] nsrc=$nsrc | $text 14 | -------------------------------------------------------------------------------- /tools/fits2ascii/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(fits2ascii) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(fits2ascii fits2ascii.cpp) 6 | target_link_libraries(fits2ascii ${VIF_LIBRARIES}) 7 | install(TARGETS fits2ascii DESTINATION bin) 8 | 9 | -------------------------------------------------------------------------------- /tools/fitstool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(fitstool) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(fitstool fitstool.cpp) 6 | target_link_libraries(fitstool ${VIF_LIBRARIES}) 7 | install(TARGETS fitstool DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/fluxcube/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(fluxcube) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(fluxcube fluxcube.cpp) 6 | target_link_libraries(fluxcube ${VIF_LIBRARIES}) 7 | install(TARGETS fluxcube DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/getgal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(getgal) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(getgal getgal.cpp) 6 | target_link_libraries(getgal ${VIF_LIBRARIES}) 7 | install(TARGETS getgal DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/imgtool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(imgtool) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(imgtool imgtool.cpp) 6 | target_link_libraries(imgtool ${VIF_LIBRARIES}) 7 | install(TARGETS imgtool DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/photinfo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(photinfo) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(photinfo photinfo.cpp) 6 | target_link_libraries(photinfo ${VIF_LIBRARIES}) 7 | install(TARGETS photinfo DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/pixfit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(pixfit) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | 6 | 7 | add_executable(pixfit-extract pixfit-extract.cpp) 8 | target_link_libraries(pixfit-extract ${VIF_LIBRARIES}) 9 | install(TARGETS pixfit-extract DESTINATION bin) 10 | 11 | add_executable(pixfit-cutout pixfit-cutout.cpp) 12 | target_link_libraries(pixfit-cutout ${VIF_LIBRARIES}) 13 | install(TARGETS pixfit-cutout DESTINATION bin) 14 | 15 | add_executable(pixfit-findprior pixfit-findprior.cpp) 16 | target_link_libraries(pixfit-findprior ${VIF_LIBRARIES}) 17 | install(TARGETS pixfit-findprior DESTINATION bin) 18 | 19 | add_executable(pixfit-addflx pixfit-addflx.cpp) 20 | target_link_libraries(pixfit-addflx ${VIF_LIBRARIES}) 21 | install(TARGETS pixfit-addflx DESTINATION bin) 22 | 23 | add_executable(pixfit-addtdcst pixfit-addtdcst.cpp) 24 | target_link_libraries(pixfit-addtdcst ${VIF_LIBRARIES}) 25 | install(TARGETS pixfit-addtdcst DESTINATION bin) 26 | 27 | add_executable(pixfit-combine pixfit-combine.cpp) 28 | target_link_libraries(pixfit-combine ${VIF_LIBRARIES}) 29 | install(TARGETS pixfit-combine DESTINATION bin) 30 | 31 | add_executable(pixfit-gfit pixfit-gfit.cpp) 32 | target_link_libraries(pixfit-gfit ${VIF_LIBRARIES}) 33 | install(TARGETS pixfit-gfit DESTINATION bin) 34 | 35 | add_executable(pixfit-prep pixfit-prep.cpp) 36 | target_link_libraries(pixfit-prep ${VIF_LIBRARIES}) 37 | install(TARGETS pixfit-prep DESTINATION bin) 38 | 39 | add_executable(pixfit-reg2fits pixfit-reg2fits.cpp) 40 | target_link_libraries(pixfit-reg2fits ${VIF_LIBRARIES}) 41 | install(TARGETS pixfit-reg2fits DESTINATION bin) 42 | 43 | add_executable(pixfit-residual pixfit-residual.cpp) 44 | target_link_libraries(pixfit-residual ${VIF_LIBRARIES}) 45 | install(TARGETS pixfit-residual DESTINATION bin) 46 | 47 | add_executable(pixfit-show pixfit-show.cpp) 48 | target_link_libraries(pixfit-show ${VIF_LIBRARIES}) 49 | install(TARGETS pixfit-show DESTINATION bin) 50 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-addflx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | int vif_main(int argc, char* argv[]) { 7 | fits::table tbl(argv[1]); 8 | 9 | vec1u ids; 10 | tbl.read_column("id", ids); 11 | uint_t ngal = ids.size(); 12 | 13 | vec1s bands; 14 | vec2f flux, flux_err; 15 | tbl.read_columns(fits::missing, 16 | "bands", bands, "flux", flux, "flux_err", flux_err 17 | ); 18 | 19 | uint_t b = npos; 20 | uint_t id = npos; 21 | float flx = fnan, err = fnan; 22 | uint_t state = 0; 23 | for (int i : range(2, argc)) { 24 | vec1s spl = split(argv[i], "="); 25 | if (spl.size() == 2) { 26 | if (spl[0] == "band") { 27 | b = where_first(bands == spl[1]); 28 | if (b == npos) { 29 | b = bands.size(); 30 | bands.push_back(spl[1]); 31 | append<1>(flux, replicate(fnan, ngal, 1)); 32 | append<1>(flux_err, replicate(fnan, ngal, 1)); 33 | } 34 | 35 | state = 0; 36 | } else { 37 | error("unknown parameter '", spl[0], "'"); 38 | return 1; 39 | } 40 | } else if (spl.size() == 1) { 41 | if (state == 0) { 42 | ++state; 43 | if (!from_string(argv[i], id)) { 44 | error("could not read ID in '", argv[i], "'"); 45 | return 1; 46 | } 47 | } else if (state == 1) { 48 | ++state; 49 | if (!from_string(argv[i], flx)) { 50 | error("could not read flux in '", argv[i], "'"); 51 | return 1; 52 | } 53 | } else if (state == 2) { 54 | state = 0; 55 | if (!from_string(argv[i], err)) { 56 | error("could not read flux error in '", argv[i], "'"); 57 | return 1; 58 | } 59 | 60 | uint_t p = where_first(ids == id); 61 | if (p == npos) { 62 | error("could not find source with ID=", id); 63 | return 1; 64 | } 65 | 66 | flux(p,b) = flx; 67 | flux_err(p,b) = err; 68 | } 69 | } else { 70 | error("ill formed parameter '", argv[i], "'"); 71 | return 1; 72 | } 73 | } 74 | 75 | tbl.update_column("bands", bands); 76 | tbl.update_column("flux", flux); 77 | tbl.update_column("flux_err", flux_err); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-addtdcst.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | int vif_main(int argc, char* argv[]) { 7 | fits::table tbl(argv[1]); 8 | 9 | vec1u ids; 10 | tbl.read_column("id", ids); 11 | uint_t ngal = ids.size(); 12 | 13 | vec1f tdust_min, tdust_max; 14 | tbl.read_columns(fits::missing, "tdust_min", tdust_min, "tdust_max", tdust_max); 15 | 16 | if (tdust_min.empty()) { 17 | tdust_min = replicate(fnan, ids.size()); 18 | } 19 | if (tdust_max.empty()) { 20 | tdust_max = replicate(fnan, ids.size()); 21 | } 22 | 23 | uint_t id = npos; 24 | float mi = fnan, ma = fnan; 25 | 26 | auto add_cst = [&]() { 27 | if (is_finite(mi) || is_finite(ma)) { 28 | if (id == npos) { 29 | error("please specify the galaxy ID before min=... and max=..."); 30 | return false; 31 | } 32 | 33 | uint_t p = where_first(ids == id); 34 | if (p == npos) { 35 | error("could not find source with ID=", id); 36 | return false; 37 | } 38 | 39 | tdust_min[p] = mi; 40 | tdust_max[p] = ma; 41 | 42 | mi = fnan; ma = fnan; 43 | } 44 | 45 | return true; 46 | }; 47 | 48 | for (int i : range(2, argc)) { 49 | vec1s spl = split(argv[i], "="); 50 | if (spl.size() == 2) { 51 | if (spl[0] == "min") { 52 | if (!from_string(spl[1], mi)) { 53 | error("could not read minimum temperature in '", argv[i], "'"); 54 | return 1; 55 | } 56 | } else if (spl[0] == "max") { 57 | if (!from_string(spl[1], ma)) { 58 | error("could not read maximum temperature in '", argv[i], "'"); 59 | return 1; 60 | } 61 | } else { 62 | error("unknown parameter '", spl[0], "'"); 63 | return 1; 64 | } 65 | } else if (spl.size() == 1) { 66 | if (!add_cst()) { 67 | return 1; 68 | } 69 | 70 | if (!from_string(argv[i], id)) { 71 | error("could not read ID in '", argv[i], "'"); 72 | return 1; 73 | } 74 | } else { 75 | error("ill formed parameter '", argv[i], "'"); 76 | return 1; 77 | } 78 | } 79 | 80 | if (!add_cst()) { 81 | return 1; 82 | } 83 | 84 | tbl.update_columns("tdust_min", tdust_min, "tdust_max", tdust_max); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-combine.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | 3 | int vif_main(int argc, char* argv[]) { 4 | std::string map_file; 5 | std::string incat; 6 | std::string outcat; 7 | 8 | read_args(argc, argv, arg_list(name(map_file, "maps"), incat, outcat)); 9 | 10 | bool bad = false; 11 | if (map_file.empty()) { 12 | error("please provide the map list file in maps=..."); 13 | bad = true; 14 | } 15 | if (incat.empty()) { 16 | error("please provide the input flux catalog in incat=..."); 17 | bad = true; 18 | } 19 | if (outcat.empty()) { 20 | error("please provide the output flux catalog in outcat=..."); 21 | bad = true; 22 | } 23 | 24 | if (bad) return 1; 25 | 26 | std::vector maps; 27 | if (!read_maps(map_file, maps)) return 1; 28 | 29 | file::copy(incat, outcat); 30 | 31 | fits::table tbl(outcat); 32 | 33 | uint_t ngal; { 34 | vec1u id; 35 | tbl.read_column("id", id); 36 | ngal = id.size(); 37 | } 38 | 39 | vec2f flux, flux_err; 40 | vec2u flux_group; 41 | vec2f flux_group_cov; 42 | vec1f group_flux, group_flux_err; 43 | vec1s bands; 44 | tbl.read_columns(fits::missing, "bands", bands, "flux", flux, "flux_err", flux_err); 45 | 46 | flux_group = replicate(npos, flux.dims); 47 | flux_group_cov.resize(flux.dims); 48 | 49 | for (auto& map : maps) { 50 | std::string band = map.band; 51 | std::string cat = map.band+"-fit.fits"; 52 | 53 | bands.push_back(band); 54 | 55 | fits::input_table itbl(cat); 56 | 57 | // Merge individual flux measurements 58 | vec1f tflx, terr; 59 | itbl.read_columns("flux", tflx, "flux_err", terr); 60 | 61 | append<1>(flux, reform(tflx, ngal, 1)); 62 | append<1>(flux_err, reform(terr, ngal, 1)); 63 | 64 | // Merge group membership 65 | vec1u group_aper_id; 66 | vec1f group_cov; 67 | 68 | itbl.read_columns(fits::missing, "group_cov", group_cov, "group_aper_id", group_aper_id); 69 | 70 | if (group_cov.empty()) { 71 | group_cov = replicate(0.0, ngal); 72 | group_aper_id = replicate(0, ngal); 73 | } 74 | 75 | vec1u idg = where(group_cov > 0); 76 | if (!idg.empty()) { 77 | // Adjust IDs to refer to the merged groups 78 | vec1u idb = complement(group_cov, idg); 79 | uint_t i0 = min(group_aper_id[idg]); 80 | group_aper_id[idg] += group_flux.size() - i0; 81 | group_aper_id[idb] = npos; 82 | } 83 | 84 | append<1>(flux_group, reform(group_aper_id, ngal, 1)); 85 | append<1>(flux_group_cov, reform(group_cov, ngal, 1)); 86 | 87 | // Merge flux groups 88 | vec1b gfit; 89 | vec1f tgflx, tgerr; 90 | 91 | itbl.read_columns(fits::missing, "group_fit", gfit, 92 | "group_flux", tgflx, "group_flux_err", tgerr); 93 | 94 | vec1u ida = where(!gfit); 95 | 96 | if (!ida.empty()) { 97 | append(group_flux, tgflx[ida]); 98 | append(group_flux_err, tgerr[ida]); 99 | } 100 | } 101 | 102 | tbl.update_column("bands", bands); 103 | tbl.update_column("flux", flux); 104 | tbl.update_column("flux_err", flux_err); 105 | tbl.update_column("flux_group", flux_group); 106 | tbl.update_column("flux_group_cov", flux_group_cov); 107 | tbl.update_column("group_flux", group_flux); 108 | tbl.update_column("group_flux_err", group_flux_err); 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-cutout.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | #include 3 | 4 | int vif_main(int argc, char* argv[]) { 5 | std::vector maps; 6 | if (!read_maps(argv[1], maps)) return 1; 7 | 8 | double radius = 30.0; 9 | double ra = dnan, dec = dnan; 10 | read_args(argc-1, argv+1, arg_list(radius, ra, dec)); 11 | 12 | if (!is_finite(ra) || !is_finite(dec)) { 13 | error("please provide the center coordinate with ra=... dec=..."); 14 | return 1; 15 | } 16 | 17 | for (auto map : maps) 18 | for (std::string type : {"sci", "err"}) { 19 | std::string file = (type == "sci" ? map.img : map.err); 20 | 21 | int_t hsize; 22 | double aspix; 23 | if (astro::get_pixel_size(file, aspix)) { 24 | hsize = ceil(radius/aspix); 25 | } else { 26 | return 1; 27 | } 28 | 29 | qstack_params p; 30 | p.keep_nan = true; 31 | p.save_offsets = true; 32 | vec3d cube; 33 | vec1u ids; 34 | 35 | qstack_output qout = qstack(vec1d{ra}, vec1d{dec}, file, hsize, cube, ids, p); 36 | 37 | if (ids.empty()) { 38 | // Create empty cutouts for non covered sources 39 | cube.resize(1, 2*hsize + 1, 2*hsize + 1); 40 | cube[_] = dnan; 41 | qout.dx = {0.0}; 42 | qout.dy = {0.0}; 43 | } 44 | 45 | // Build new header 46 | fits::header nhdr = astro::filter_wcs(fits::read_header(file)); 47 | if (!fits::setkey(nhdr, "CRPIX1", hsize+1+qout.dx[0]) || 48 | !fits::setkey(nhdr, "CRPIX2", hsize+1+qout.dy[0]) || 49 | !fits::setkey(nhdr, "CRVAL1", ra) || 50 | !fits::setkey(nhdr, "CRVAL2", dec)) { 51 | error("could not set WCS information (CRPIX1, CRPIX2, CRVAL1, CRVAL2)"); 52 | note("WCS for the cutout will be wrong"); 53 | note("parsing band '"+map.band+"'"); 54 | return 1; 55 | } 56 | 57 | fits::write(map.band+"-"+type+".fits", cube(0,_,_), nhdr); 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-findprior.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | #include 3 | 4 | int vif_main(int argc, char* argv[]) { 5 | // Read search circles 6 | vec2d regs; 7 | vec1s text; 8 | 9 | bool physical = false; 10 | if (!read_ds9_region_circles(argv[1], regs, text, physical)) { 11 | return 1; 12 | } 13 | 14 | if (physical) { 15 | error("the region file must be in WCS coordinates, not physical"); 16 | return 1; 17 | } 18 | 19 | // Read catalog 20 | fits::input_table tbl(argv[2]); 21 | 22 | std::string cra = "pos.ra"; 23 | std::string cdec = "pos.dec"; 24 | std::string cid = "id.cls"; 25 | std::string cz = "z.mp.phot"; 26 | std::string cm = "m.mp.del"; 27 | uint_t nsrc = 100; 28 | double mref = 9, zref = 1.0, mmin = 10.0; 29 | read_args(argc-3, argv+3, arg_list( 30 | name(cra, "ra"), name(cdec, "dec"), name(cid, "id"), name(cz, "z"), name(cm, "m"), 31 | nsrc, mmin, mref, zref 32 | )); 33 | 34 | vec1u id; 35 | vec1d ra, dec; 36 | vec1f z, m; 37 | tbl.read_columns(fits::narrow, cra, ra, cdec, dec, cid, id, cz, z, cm, m); 38 | 39 | // Filter catalog 40 | auto cosmo = get_cosmo("std"); 41 | vec1d d = lumdist(z, cosmo); 42 | double dref = lumdist(zref, cosmo); 43 | 44 | vec1u sid = where(m > mref + 2*log10(d/dref) || m > mmin); 45 | ra = ra[sid]; 46 | dec = dec[sid]; 47 | id = id[sid]; 48 | z = z[sid]; 49 | m = m[sid]; 50 | 51 | // Cross match 52 | vec1d sra = regs(_,0); 53 | vec1d sdec = regs(_,1); 54 | 55 | qxmatch_params p; p.nth = nsrc; p.brute_force = true; 56 | auto res = qxmatch(sra, sdec, ra, dec, p); 57 | 58 | // Build region file 59 | std::ofstream out(argv[3]); 60 | out << "# Region file format: DS9 version 4.1\n"; 61 | out << "global color=green dashlist=8 3 width=2 font=\"helvetica 10 normal roman\"" 62 | "select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 source=1\n"; 63 | out << "fk5\n"; 64 | 65 | for (uint_t i : range(sra)) 66 | for (uint_t j : range(nsrc)) { 67 | if (res.d(j,i) > regs(i,2)) break; 68 | 69 | uint_t k = res.id(j,i); 70 | std::string rra, rdec; 71 | deg2sex(ra[k], dec[k], rra, rdec); 72 | out << "circle(" << rra << "," << rdec << ",0.5\") # width=3 text={" 73 | << id[k] << ", " << z[k] << ", " << m[k] << "}\n"; 74 | } 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-prep.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | 3 | int vif_main(int argc, char* argv[]) { 4 | std::vector maps; 5 | if (!read_maps(argv[2], maps)) return 1; 6 | 7 | std::string cat_file = argv[3]; 8 | std::string cmb_file = argv[4]; 9 | 10 | std::string catalogs = "\""+cmb_file+"\" \""+cat_file+"\""; 11 | std::ofstream oscript(argv[1]); 12 | oscript << "#!/bin/bash\n\n"; 13 | for (uint_t i : range(maps)) { 14 | oscript << "pixfit-extract cat=\""+cat_file+"\" img=\""+maps[i].band+"-sci.fits\" " 15 | << "err=\""+maps[i].band+"-err.fits\" psf=\""+maps[i].psf+"\" " 16 | << "fconv="+to_string(maps[i].fconv)+" " 17 | << "beam_flux="+to_string(maps[i].beam_flux)+" " 18 | << "out=fit-"+maps[i].band+".fits " 19 | << "out_res="+maps[i].band+"-res.fits " 20 | << "out_model="+maps[i].band+"-mod.fits make_groups " 21 | << "out_gmap="+maps[i].band+"-grp.fits " 22 | << "group_fit_threshold="+to_string(maps[i].group_fit_threshold)+" " 23 | << "group_aper_threshold="+to_string(maps[i].group_aper_threshold)+" "; 24 | 25 | if (is_finite(maps[i].beam_smear)) { 26 | oscript << " beam_smeared beam_size=" << to_string(maps[i].beam_smear); 27 | } 28 | 29 | oscript << "\n"; 30 | 31 | catalogs += " "+maps[i].band+":fit-"+maps[i].band+".fits"; 32 | } 33 | 34 | oscript << "\n"; 35 | oscript << "pixfit-combine "+catalogs+"\n"; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-reg2fits.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | 3 | int vif_main(int argc, char* argv[]) { 4 | vec2d regs; 5 | vec1s text; 6 | 7 | bool physical = false; 8 | if (!read_ds9_region_circles(argv[1], regs, text, physical)) { 9 | return 1; 10 | } 11 | 12 | if (physical) { 13 | error("must be WCS coordinates"); 14 | return 1; 15 | } 16 | 17 | vec1u id; 18 | vec1f z, m; 19 | for (std::string txt : text) { 20 | vec1s spl = split(txt,","); 21 | if (spl.size() != 3) { 22 | error("need three elements: ID, z and M*"); 23 | return 1; 24 | } 25 | 26 | uint_t tid; 27 | float tz, tm; 28 | if (!from_string(spl[0], tid) || !from_string(spl[1], tz) || !from_string(spl[2], tm)) { 29 | error("could not convert ID, z and M* into numbers"); 30 | return 1; 31 | } 32 | 33 | id.push_back(tid); 34 | z.push_back(tz); 35 | m.push_back(tm); 36 | } 37 | 38 | fits::write_table(file::remove_extension(argv[1])+".fits", 39 | "id", id, "ra", vec1d{regs(_,0)}, "dec", vec1d{regs(_,1)}, "z", z, "m", m 40 | ); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-residual.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | 3 | int vif_main(int argc, char* argv[]) { 4 | std::string map_file; 5 | std::string cat_file; 6 | double snr_min = dnan; 7 | 8 | read_args(argc, argv, arg_list(name(map_file, "maps"), name(cat_file, "cat"), snr_min)); 9 | 10 | bool bad = false; 11 | if (map_file.empty()) { 12 | error("please provide the map list file in maps=..."); 13 | bad = true; 14 | } 15 | if (cat_file.empty()) { 16 | error("please provide the flux catalog in cat=..."); 17 | bad = true; 18 | } 19 | 20 | if (bad) return 1; 21 | 22 | std::vector maps; 23 | if (!read_maps(map_file, maps)) return 1; 24 | 25 | vec1d ra, dec; 26 | vec2f flux; 27 | vec1s bands; 28 | fits::read_table(cat_file, ftable(ra, dec, flux, bands)); 29 | 30 | vec1b sel = replicate(true, ra.size()); 31 | if (is_finite(snr_min)) { 32 | vec1d lir, lir_err; 33 | fits::read_table(cat_file, ftable(lir, lir_err)); 34 | sel = lir/lir_err > snr_min; 35 | } 36 | 37 | for (auto& map : maps) { 38 | // Find band in catalog 39 | uint_t b = where_first(bands == map.band); 40 | if (b == npos) { 41 | warning("no band named '", map.band, "' in the provided catalog"); 42 | continue; 43 | } 44 | 45 | // Read map 46 | vec2d img; 47 | fits::header hdr; 48 | fits::read(map.band+"-sci.fits", img, hdr); 49 | 50 | // Read PSF 51 | int_t hsize; 52 | vec2d psf = read_psf(map, hsize); 53 | 54 | // Get pixel coordinates 55 | vec1d x, y; 56 | astro::ad2xy(astro::wcs(hdr), ra, dec, x, y); 57 | x -= 1; y -= 1; 58 | 59 | // Select sources which fall on the map and have a flux measurement 60 | vec1u ids = where(is_finite(flux(_,b)) && sel && 61 | x >= -hsize && x < img.dims[1]+hsize && 62 | y >= -hsize && y < img.dims[0]+hsize); 63 | 64 | x = x[ids]; y = y[ids]; 65 | vec1f flx = flux(ids,b); 66 | vec1i ix = round(x), iy = round(y); 67 | vec1d dx = x - ix, dy = y - iy; 68 | 69 | // Remove the sources from the map 70 | for (uint_t i : range(x)) { 71 | vec1f tpsf = flatten(translate(psf, dy[i], dx[i])); 72 | vec1u idi, idp; 73 | subregion(img, {iy[i]-hsize, ix[i]-hsize, iy[i]+hsize, ix[i]+hsize}, idi, idp); 74 | 75 | img[idi] -= (flx[i]/map.fconv)*tpsf[idp]; 76 | } 77 | 78 | // Save the residual 79 | fits::write(map.band+"-fullres.fits", img, hdr); 80 | } 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /tools/pixfit/pixfit-show.cpp: -------------------------------------------------------------------------------- 1 | #include "pixfit-common.hpp" 2 | 3 | int vif_main(int argc, char* argv[]) { 4 | std::vector maps; 5 | if (!read_maps(argv[3], maps)) return 1; 6 | 7 | std::string cat_file = argv[4]; 8 | 9 | 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /tools/psffit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(psffit) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(psffit psffit.cpp) 6 | target_link_libraries(psffit ${VIF_LIBRARIES}) 7 | install(TARGETS psffit DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/psffit/psffit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | void print_help(); 7 | 8 | int vif_main(int argc, char* argv[]) { 9 | if (argc < 3) { 10 | print_help(); 11 | return 0; 12 | } 13 | 14 | std::string psf_model; 15 | std::string serr; 16 | float radius = 0.0; 17 | float psf_frac = 1.0; 18 | float fconv = 1.0; 19 | bool silent = false; 20 | bool nobg = false; 21 | bool save = false; 22 | std::string resi; 23 | 24 | read_args(argc-3, argv+3, arg_list( 25 | name(psf_model, "psf"), radius, psf_frac, name(serr, "error"), fconv, silent, 26 | name(resi, "residual"), nobg, save 27 | )); 28 | 29 | vec2d img, err; 30 | fits::read(argv[1], img); 31 | if (!serr.empty()) { 32 | fits::read(serr, err); 33 | } else { 34 | if (!silent) warning("no error map provided, reported errors will be wrong"); 35 | err = img*0 + 1; 36 | } 37 | 38 | float fx0, fy0; 39 | from_string(argv[2], fx0); 40 | from_string(argv[3], fy0); 41 | int_t x0 = round(fx0), y0 = round(fy0); 42 | 43 | vec2d psf; 44 | if (!make_psf({{img.dims[0], img.dims[1]}}, x0, y0, psf_model, psf)) { 45 | return 1; 46 | } 47 | 48 | vec1u idf; 49 | if (psf_frac != 1.0) { 50 | idf = where(is_finite(img) && is_finite(err) && is_finite(psf) && 51 | psf > (1.0 - psf_frac)*max(psf[where(is_finite(psf))])); 52 | } else if (radius != 0.0) { 53 | vec2d rad = generate_img({{img.dims[0], img.dims[1]}}, [=](uint_t x, uint_t y) { 54 | return sqr(double(x) - x0) + sqr(double(y) - y0); 55 | }); 56 | 57 | idf = where(is_finite(img) && is_finite(err) && is_finite(psf) && rad < sqr(radius)); 58 | } else { 59 | idf = where(is_finite(img) && is_finite(err) && is_finite(psf)); 60 | } 61 | 62 | if (nobg) { 63 | auto res = linfit(img[idf], err[idf], psf[idf]); 64 | 65 | if (!silent) print("flux: ", fconv*res.params[0], " +/- ", fconv*res.errors[0], " (flux unit)"); 66 | 67 | if (!resi.empty()) { 68 | vec2d ires = img - res.params[0]*psf; 69 | fits::write(resi, ires); 70 | } 71 | 72 | if (save) { 73 | std::string outname = argv[1]; 74 | outname = outname.substr(0, outname.size() - length(".fits")) + "_flx.fits"; 75 | fits::write_table(outname, "flux", fconv*res.params[0], "flux_err", fconv*res.errors[0]); 76 | } 77 | } else { 78 | auto res = linfit(img[idf], err[idf], 1.0, psf[idf]); 79 | 80 | if (!silent) { 81 | print("flux: ", fconv*res.params[1], " +/- ", fconv*res.errors[1], " (flux unit)"); 82 | print("background: ", res.params[0], " +/- ", res.errors[0], " (map unit)"); 83 | } 84 | 85 | if (!resi.empty()) { 86 | if (resi == "1") { 87 | std::string outname = argv[1]; 88 | resi = outname.substr(0, outname.size() - length(".fits")) + "_res.fits"; 89 | } 90 | 91 | vec2d ires = img - res.params[1]*psf; 92 | fits::write(resi, ires); 93 | } 94 | 95 | if (save) { 96 | std::string outname = argv[1]; 97 | outname = outname.substr(0, outname.size() - length(".fits")) + "_flx.fits"; 98 | fits::write_table(outname, 99 | "flux", fconv*res.params[1], "flux_err", fconv*res.errors[1], 100 | "bg", fconv*res.params[0], "bg_err", fconv*res.errors[0] 101 | ); 102 | } 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | void print_help() { 109 | using namespace terminal_format; 110 | print("psffit v1.0"); 111 | paragraph("usage: psffit img.fits x y psf=..."); 112 | } 113 | -------------------------------------------------------------------------------- /tools/qaper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(qaper) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(qaper qaper.cpp) 6 | target_link_libraries(qaper ${VIF_LIBRARIES}) 7 | install(TARGETS qaper DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/qconvol/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(qconvol) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(qconvol qconvol.cpp) 6 | target_link_libraries(qconvol ${VIF_LIBRARIES}) 7 | install(TARGETS qconvol DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/qconvol/qconvol.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | 5 | void print_help() { 6 | using namespace terminal_format; 7 | 8 | print("qconvol v1.0"); 9 | paragraph("usage: qconvol img.fits radius=1 kernel=\"\" out=output.fits"); 10 | 11 | paragraph( 12 | "The program will convolve the provided image with a Gaussian beam of FWHM equal " 13 | "to 2 x radius [pixels] (or [arcsec] if the 'arcsec' keyword is provided), and " 14 | "save the result in a new FITS file.\n\n" 15 | "Alternatively, one may provide a 'kernel' image in FITS format which will be " 16 | "used directly to perform the convolution." 17 | ); 18 | } 19 | 20 | int vif_main(int argc, char* argv[]) { 21 | if (argc < 2) { 22 | print_help(); 23 | return 0; 24 | } 25 | 26 | std::string fimg = argv[1]; 27 | std::string fout = ""; 28 | std::string kernel_file = ""; 29 | double radius = 1.0; 30 | bool arcsec = false; 31 | 32 | read_args(argc-1, argv+1, arg_list( 33 | name(fout, "out"), radius, arcsec, name(kernel_file, "kernel") 34 | )); 35 | 36 | if (fout.empty()) { 37 | error("please provide the name of the output file in out=..."); 38 | return 1; 39 | } 40 | 41 | 42 | vec2d beam; 43 | if (!kernel_file.empty()) { 44 | fits::read(kernel_file, beam); 45 | 46 | // Trim the PSF, make sure that the peak is at the center, and that the dimensions 47 | // are odds 48 | vec1i idm = mult_ids(beam, max_id(beam)); 49 | int_t hsize = 0; 50 | int_t imax = std::min( 51 | std::min(idm[0], int_t(beam.dims[0])-1-idm[0]), 52 | std::min(idm[1], int_t(beam.dims[1])-1-idm[1]) 53 | ); 54 | 55 | for (int_t i = 1; i <= imax; ++i) { 56 | if (beam(idm[0]-i,idm[1]) == 0.0 && 57 | beam(idm[0]+i,idm[1]) == 0.0 && 58 | beam(idm[0],idm[1]-i) == 0.0 && 59 | beam(idm[0],idm[1]+i) == 0.0) { 60 | hsize = i; 61 | break; 62 | } 63 | } 64 | 65 | if (hsize == 0) hsize = imax; 66 | beam = astro::subregion(beam, {idm[0]-hsize, idm[1]-hsize, idm[0]+hsize, idm[1]+hsize}); 67 | } else { 68 | if (arcsec) { 69 | double aspix; 70 | if (!astro::get_pixel_size(fimg, aspix)) { 71 | error("could not read the pixel size of this image, please provide the beam " 72 | "size in pixels and remove the 'arcsec' keyword"); 73 | return 1; 74 | } 75 | 76 | radius /= aspix; 77 | } 78 | 79 | radius /= 1.117; 80 | uint_t nk = ceil(30*radius); 81 | if (nk % 2 == 0) ++nk; 82 | 83 | beam = astro::gaussian_profile({{nk,nk}}, radius); 84 | beam /= total(beam); 85 | } 86 | 87 | vec2d img; 88 | fits::header hdr; 89 | fits::read(fimg, img, hdr); 90 | 91 | vec2d out = astro::convolve2d(img, beam); 92 | fits::write(fout, out, hdr); 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /tools/qmask/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(qmask) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(qmask qmask.cpp) 6 | target_link_libraries(qmask ${VIF_LIBRARIES}) 7 | install(TARGETS qmask DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/qregrid/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(qregrid) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(qregrid qregrid.cpp) 6 | target_link_libraries(qregrid ${VIF_LIBRARIES}) 7 | install(TARGETS qregrid DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/qstack2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(qstack2) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(qstack2 qstack2.cpp) 6 | target_link_libraries(qstack2 ${VIF_LIBRARIES}) 7 | install(TARGETS qstack2 DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/qxmatch2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(qxmatch2) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(qxmatch2 qxmatch2.cpp) 6 | target_link_libraries(qxmatch2 ${VIF_LIBRARIES}) 7 | install(TARGETS qxmatch2 DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/radec2pix/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(radec2pix) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(radec2pix radec2pix.cpp) 6 | target_link_libraries(radec2pix ${VIF_LIBRARIES}) 7 | install(TARGETS radec2pix DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/radec2pix/radec2pix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | void print_help(); 7 | 8 | int vif_main(int argc, char* argv[]) { 9 | if (argc < 4) { 10 | print_help(); 11 | return 0; 12 | } 13 | 14 | fits::header hdr = fits::read_header(argv[1]); 15 | astro::wcs astro(hdr); 16 | 17 | uint_t nc = argc - 2; 18 | if (nc % 2 != 0) { 19 | error("expected an even number of coordinates, RA and Dec"); 20 | return 1; 21 | } 22 | 23 | nc /= 2; 24 | 25 | vec1d ra(nc), dec(nc); 26 | for (uint_t c : range(nc)) { 27 | std::string sra = argv[2*c+2]; 28 | std::string sdec = argv[2*c+3]; 29 | 30 | if (find(sra, ":") == npos) { 31 | if (!from_string(sra, ra[c])) { 32 | error("could not convert '"+sra+"' to a coordinate"); 33 | return 1; 34 | } 35 | if (!from_string(sdec, dec[c])) { 36 | error("could not convert '"+sdec+"' to a coordinate"); 37 | return 1; 38 | } 39 | } else { 40 | sex2deg(sra, sdec, ra[c], dec[c]); 41 | } 42 | } 43 | 44 | vec1d px, py; 45 | astro::ad2xy(astro, ra, dec, px, py); 46 | 47 | for (uint_t c : range(nc)) { 48 | print(px[c], " ", py[c]); 49 | } 50 | 51 | return 0; 52 | } 53 | 54 | void print_help() { 55 | print("radec2pix v1.0"); 56 | print("usage: radec2pix img.fits RA1 Dec1 RA2 Dec2 ..."); 57 | } 58 | -------------------------------------------------------------------------------- /tools/randsrc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(randsrc) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(randsrc randsrc.cpp) 6 | target_link_libraries(randsrc ${VIF_LIBRARIES}) 7 | install(TARGETS randsrc DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/randsrc/randsrc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | void print_help(); 7 | 8 | template 9 | bool read_param(T& p, D def, std::string name, I& iter, const I& end) { 10 | if (iter == end) { 11 | p = def; 12 | } else if (!from_string(*iter, p)) { 13 | error("could not read ", name, " from '", *iter, "'"); 14 | return false; 15 | } else { 16 | ++iter; 17 | } 18 | 19 | return true; 20 | } 21 | 22 | int vif_main(int argc, char* argv[]) { 23 | if (argc < 2) { 24 | print_help(); 25 | return 0; 26 | } 27 | 28 | // Program arguments 29 | std::string pos = ""; 30 | std::string out; 31 | uint_t tseed = 42; 32 | uint_t max_iter = 1000; 33 | uint_t nsrc = 0; 34 | std::string model = "uniform"; 35 | bool verbose = false; 36 | 37 | read_args(argc-1, argv+1, arg_list(pos, out, nsrc, max_iter, model, 38 | name(tseed, "seed"), verbose)); 39 | 40 | auto seed = make_seed(tseed); 41 | 42 | // Read input position list 43 | vec1d hra, hdec; 44 | if (!pos.empty() && !ends_with(pos, ".")) pos = pos+"."; 45 | fits::read_table(argv[1], pos+"ra", hra, pos+"dec", hdec); 46 | 47 | if (nsrc == 0) nsrc = hra.size(); 48 | 49 | if (hra.size() < 3) { 50 | error("too few points to build convex hull"); 51 | note("need at least 3"); 52 | return 1; 53 | } 54 | 55 | // Compute convex hull of input positions 56 | auto hull = build_convex_hull(hra, hdec); 57 | auto in_hull = [&](double tra, double tdec) { 58 | return in_convex_hull(tra, tdec, hull); 59 | }; 60 | 61 | // Compute bounding box of input positions 62 | vec1d rra = {min(hra), max(hra)}; 63 | vec1d rdec = {min(hdec), max(hdec)}; 64 | 65 | vec1s vmodel = split(model, ":"); 66 | 67 | vec1d ra, dec; 68 | 69 | if (vmodel[0] == "uniform") { 70 | // Place points uniformly within the convex hull formed by the provided coordinates 71 | randpos_uniform_options opt; 72 | opt.max_iter = max_iter; 73 | 74 | auto status = randpos_uniform_box(seed, nsrc, rra, rdec, ra, dec, in_hull, opt); 75 | if (!status.success) { 76 | error("generation failed: ", status.failure); 77 | return 1; 78 | } 79 | } else { 80 | error("unknown model '", vmodel[0], "'"); 81 | return 1; 82 | } 83 | 84 | if (out.empty()) { 85 | out = argv[1]; 86 | if (ends_with(out, ".fits")) { 87 | out = erase_end(out, ".fits"); 88 | } 89 | 90 | out += "-rnd.fits"; 91 | } 92 | 93 | file::mkdir(file::get_directory(out)); 94 | fits::write_table(out, ftable(ra, dec)); 95 | 96 | return 0; 97 | } 98 | 99 | void print_help() { 100 | print("randsrc v1.0"); 101 | print("usage: randsrc cat.fits [seed,out,nsrc,pos,max_iter,model,verbose]"); 102 | } 103 | -------------------------------------------------------------------------------- /tools/refgen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(refgen) 3 | 4 | include_directories(${CLANG_INCLUDE}) 5 | 6 | add_definitions(-D__STDC_CONSTANT_MACROS) 7 | add_definitions(-D__STDC_FORMAT_MACROS) 8 | add_definitions(-D__STDC_LIMIT_MACROS) 9 | 10 | add_executable(vif-refgen refgen.cpp) 11 | 12 | target_link_libraries(vif-refgen ${CLANG_LIBS}) 13 | if (TCMALLOC_LIBRARY) 14 | target_link_libraries(vif-refgen ${TCMALLOC_LIBRARIES}) 15 | endif() 16 | 17 | install(TARGETS vif-refgen RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) 18 | -------------------------------------------------------------------------------- /tools/sex2deg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(sex2deg) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(sex2deg sex2deg.cpp) 6 | target_link_libraries(sex2deg ${VIF_LIBRARIES}) 7 | install(TARGETS sex2deg DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/sex2deg/sex2deg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace vif; 4 | using namespace vif::astro; 5 | 6 | void print_help(); 7 | 8 | int vif_main(int argc, char* argv[]) { 9 | if (argc < 3) { 10 | print_help(); 11 | return 0; 12 | } 13 | 14 | std::string sra = argv[1]; 15 | std::string sdec = argv[2]; 16 | double ra, dec; 17 | if (sex2deg(sra, sdec, ra, dec)) { 18 | print(format::precision(ra, 12), " ", format::precision(dec, 12)); 19 | } else { 20 | error("could not read sexagesimal coordinates"); 21 | return 1; 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | void print_help() { 28 | print("sex2deg v1.0"); 29 | print("usage: sex2deg RA Dec"); 30 | } 31 | -------------------------------------------------------------------------------- /tools/subsrc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(subsrc) 3 | 4 | include_directories(${VIF_INCLUDE_DIRS}) 5 | add_executable(subsrc subsrc.cpp) 6 | target_link_libraries(subsrc ${VIF_LIBRARIES}) 7 | install(TARGETS subsrc DESTINATION bin) 8 | --------------------------------------------------------------------------------