From 7e9b74b3fe9c1c7a40f8ecf1d18e6c7a138324ac Mon Sep 17 00:00:00 2001 From: Federico Berlfein Date: Fri, 8 Nov 2024 13:40:02 -0500 Subject: [PATCH] Updated structure --- CHANGELOG.rst | 3 + config/README.md | 41 - config/README.rst | 49 ++ docs/_build/doctrees/environment.pickle | Bin 102442 -> 310600 bytes docs/_build/doctrees/euclidlike.doctree | Bin 117843 -> 101238 bytes docs/_build/doctrees/euclidlike_imsim.doctree | Bin 6746 -> 221830 bytes docs/_build/doctrees/examples.doctree | Bin 0 -> 8315 bytes docs/_build/doctrees/history.doctree | Bin 0 -> 4039 bytes docs/_build/doctrees/index.doctree | Bin 17879 -> 5453 bytes docs/_build/doctrees/install.doctree | Bin 0 -> 7822 bytes docs/_build/doctrees/modules.doctree | Bin 2877 -> 2598 bytes docs/_build/doctrees/overview.doctree | Bin 0 -> 18152 bytes docs/_build/doctrees/scripts.doctree | Bin 3593 -> 40604 bytes docs/_build/html/.buildinfo | 2 +- .../html/_modules/euclidlike/backgrounds.html | 15 +- .../html/_modules/euclidlike/bandpass.html | 10 +- .../_modules/euclidlike/euclidlike_psf.html | 12 +- .../_modules/euclidlike/euclidlike_wcs.html | 27 +- .../_modules/euclidlike_imsim/bandpass.html | 144 ++++ .../html/_modules/euclidlike_imsim/ccd.html | 331 ++++++++ .../html/_modules/euclidlike_imsim/noise.html | 384 +++++++++ .../html/_modules/euclidlike_imsim/obseq.html | 227 +++++ .../_modules/euclidlike_imsim/photonOps.html | 194 +++++ .../html/_modules/euclidlike_imsim/psf.html | 304 +++++++ .../_modules/euclidlike_imsim/skycat.html | 631 ++++++++++++++ .../html/_modules/euclidlike_imsim/stamp.html | 454 ++++++++++ .../html/_modules/euclidlike_imsim/utils.html | 250 ++++++ .../html/_modules/euclidlike_imsim/wcs.html | 169 ++++ docs/_build/html/_modules/index.html | 20 + .../html/_modules/scripts/download_psf.html | 619 ++++++++++++++ .../scripts/make_euclidlike_pupil_plane.html | 295 +++++++ docs/_build/html/_sources/euclidlike.rst.txt | 180 +++- .../html/_sources/euclidlike_imsim.rst.txt | 69 +- docs/_build/html/_sources/examples.rst.txt | 29 + docs/_build/html/_sources/history.rst.txt | 11 + docs/_build/html/_sources/index.rst.txt | 71 +- docs/_build/html/_sources/install.rst.txt | 4 + docs/_build/html/_sources/modules.rst.txt | 5 +- docs/_build/html/_sources/overview.rst.txt | 4 + docs/_build/html/_sources/scripts.rst.txt | 13 +- docs/_build/html/euclidlike.html | 486 +++++------ docs/_build/html/euclidlike_imsim.html | 787 +++++++++++++++++- docs/_build/html/examples.html | 135 +++ docs/_build/html/genindex.html | 361 +++++++- docs/_build/html/history.html | 123 +++ docs/_build/html/index.html | 107 +-- docs/_build/html/install.html | 150 ++++ docs/_build/html/modules.html | 169 +++- docs/_build/html/objects.inv | Bin 477 -> 1262 bytes docs/_build/html/overview.html | 173 ++++ docs/_build/html/py-modindex.html | 67 +- docs/_build/html/scripts.html | 122 ++- docs/_build/html/search.html | 8 + docs/_build/html/searchindex.js | 2 +- docs/conf.py | 5 +- docs/euclidlike.rst | 180 +++- docs/euclidlike_imsim.rst | 69 +- docs/examples.rst | 29 + docs/history.rst | 11 + docs/index.rst | 71 +- docs/install.rst | 4 + docs/modules.rst | 5 +- docs/overview.rst | 4 + docs/scripts.rst | 13 +- euclidlike/instrument_params.py | 2 +- 65 files changed, 6813 insertions(+), 837 deletions(-) create mode 100644 CHANGELOG.rst delete mode 100644 config/README.md create mode 100644 config/README.rst create mode 100644 docs/_build/doctrees/examples.doctree create mode 100644 docs/_build/doctrees/history.doctree create mode 100644 docs/_build/doctrees/install.doctree create mode 100644 docs/_build/doctrees/overview.doctree create mode 100644 docs/_build/html/_modules/euclidlike_imsim/bandpass.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/ccd.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/noise.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/obseq.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/photonOps.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/psf.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/skycat.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/stamp.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/utils.html create mode 100644 docs/_build/html/_modules/euclidlike_imsim/wcs.html create mode 100644 docs/_build/html/_modules/scripts/download_psf.html create mode 100644 docs/_build/html/_modules/scripts/make_euclidlike_pupil_plane.html create mode 100644 docs/_build/html/_sources/examples.rst.txt create mode 100644 docs/_build/html/_sources/history.rst.txt create mode 100644 docs/_build/html/_sources/install.rst.txt create mode 100644 docs/_build/html/_sources/overview.rst.txt create mode 100644 docs/_build/html/examples.html create mode 100644 docs/_build/html/history.html create mode 100644 docs/_build/html/install.html create mode 100644 docs/_build/html/overview.html create mode 100644 docs/examples.rst create mode 100644 docs/history.rst create mode 100644 docs/install.rst create mode 100644 docs/overview.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..0bf7cfc --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,3 @@ +Changes from v0.0.0 to v0.0.1 +========================= +Made repo public. \ No newline at end of file diff --git a/config/README.md b/config/README.md deleted file mode 100644 index bc79c08..0000000 --- a/config/README.md +++ /dev/null @@ -1,41 +0,0 @@ -## Config imsim - -`was.yaml`: _euclidlike_imsim exemple_ config file. -You will want to update the following entries: - -- `input.obseq_data.file_name`: path to the observing sequence. Link to `euclidlike/data/euclid_obseq.fits` -- `input.sky_catalog.file_name`: path to the skyCatalog to use -- `output.dir`: path to the output directory for the simulated images -- `output.truth.dir`: path to the ouput directory for the true catalogs - -To run the code: -```bash -galsim was.yaml -``` - -You might want to specify some config entries in the command line, likes: -```bash -galsim was.yaml input.obseq_data.visit=33690 image.CCD=1 -``` - -## Config SLURM - -`slurm_runner.sh` contain the SLURM configuration to run "large scale" simulations. -You will want to update the following line: -- `#!/bin/zsh`: depending on the shell you are using you might want to change it to: `#!/bin/bash` -- `#SBATCH --output=/path/to/slurm-%A-%a.out`: slurm stdout file -- `#SBATCH --error=/path/to/slurm-%A-%a.err`: slurm stderr file -- `source activate [env_name]`: conda environment to use -- `file_list='/path/to/run_list.txt'`: file containing the pointings to simulate (see note below) - -the `run_list.txt` is a 2 columns file with the pointing and the CCD_ID to simulate. It should lookq like: -``` -33688 0 -33688 1 -33688 2 -[...] -33688 35 -33689 0 -33689 1 -[...] -``` diff --git a/config/README.rst b/config/README.rst new file mode 100644 index 0000000..fb823c3 --- /dev/null +++ b/config/README.rst @@ -0,0 +1,49 @@ +Config imsim +============ + +``was.yaml``: *euclidlike_imsim example* config file. +You will want to update the following entries: + +- ``input.obseq_data.file_name``: path to the observing sequence. Link to ``euclidlike/data/euclid_obseq.fits`` +- ``input.sky_catalog.file_name``: path to the skyCatalog to use +- ``output.dir``: path to the output directory for the simulated images +- ``output.truth.dir``: path to the output directory for the true catalogs + +To run the code: + +.. code-block:: bash + + galsim was.yaml + +You might want to specify some config entries on the command line, like: + +.. code-block:: bash + + galsim was.yaml input.obseq_data.visit=33690 image.CCD=1 + + +Config SLURM +============ + +``slurm_runner.sh`` contains the SLURM configuration to run "large scale" simulations. +You will want to update the following lines: + +- ``#!/bin/zsh``: depending on the shell you are using, you might want to change it to: ``#!/bin/bash`` +- ``#SBATCH --output=/path/to/slurm-%A-%a.out``: SLURM stdout file +- ``#SBATCH --error=/path/to/slurm-%A-%a.err``: SLURM stderr file +- ``source activate [env_name]``: conda environment to use +- ``file_list='/path/to/run_list.txt'``: file containing the pointings to simulate (see note below) + +The ``run_list.txt`` is a 2-column file with the pointing and the ``CCD_ID`` to simulate. It should look like: + +.. code-block:: text + + 33688 0 + 33688 1 + 33688 2 + [...] + 33688 35 + 33689 0 + 33689 1 + [...] + diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index 2d9ec1c4b8fa7bbe21fdb691383182b5d2e0391b..d38556fc8ea8691d0754cc57fc8144f62a21ef72 100644 GIT binary patch literal 310600 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

U{aF`+`69%X0mRv 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 ArT_o{ delta 25680 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 L2Q3x7`I-L@SG0Ni literal 117843 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 literal 6746 zcmb7}e~aA48OP5)@7?YFJ|_-t?Q_m;Q(w~T?X?sd0tJI<+T!LC;u0FTRGpP(cXX#; z(TwanN}&D2;HA^h5cM4t0)f7SKp@bUPzVJ25(0rh|Lk{08fm0$Q>IS z*bTPMZn8zTD}O&!oXD6DlQcd76`Zj1pBx?@{`hCfa75E!O#Nv13k|?|fZ&I}Bmw>( z6itKQ0Ll(92>c-B2=dnb%h`yn6|-b8vu$%NS07}fF!r(l0ce=dHJVCjP<&V@ zK4P~N7xp}0u-kzDef(a)?+$)1B2e}t9pIoaXD>rR&+Z^sdF_#y?yXj9u+^HD8LT6m z+ckwURSrfZ@)FF|UJ<5=(y}ZwWyZ1&{@3#b|C$y2N+bBaTHiot^1#R&l=5mMmTfts z#@2*FZ0c=LaNGgvW-Y{ka$V01TxNo0WEfdSHJ;IYcpMAQb_36iT2+Y${$|NoW+fR* zRwop=>wxl7?cPA~sKBa>(_;tglKXBujjS#Pk?FF~?otE$<9xu*EMV6g!1im!B{1WC zQ0kqfXZ0!RnLcg7ohTus1Ldt+m_ZrEKBuh=v&;;>hFOg)pAXrG7P7qtvfWx)iA;N( z!w(!>oq$&-vhdV!_#e3LNe6B5)egI^n=&2b}NK^J6k6 zVX=s#H|P?m9-MU}Cc?oL>6-2uzm zp(|K?YzF@JZ9J)sYC!*)573tupjR4zto_*l;^SE~mYG3Q%j$#zcO6iy2d9C;T{8BA z_U>aDn*3=Q)^PqiADnM2ICmRxp0D$}gj4#Q1!S3)fLii8A;E12Bx~#n(&@QNL@RkL zyNXf6u0nLOb7^5=E=nhxRS*4c_p1gd>)BvHX~(miEK9?wA+Zw^oOWQchORIP5+*H5 zmRUu~Hmf1MRE2!OSLu^GRSym6%?2dvA!Q&bzq5=iL&L}x*og=(=R>5w_MVQYVOAr$ zR|R}gM0cwm8qx2bf=K(l2%?6-PDF6of$0Bi(~o9eB`qV9LzYpE=eP>?qIlk^dT2a< zXyCDS;WC5Zbrz0gR_2c-t`iO1b)eaLU4MP!9RhzCR!TO3pvCMo4b9it~=L4y4Lf?PE=)Wc<_KHx9OO*czbmBguPBI~B5sEx=K zPKEHJ3Cck`Refii>RI%1x%4&(GSn2R0?|^Oi6j&G5!*VF{Rxd|O7LBks3$jxHhT7&6*vw5S{S#GNskb9f~QGl3oxe<_PlA&$~;vTLqqdq8~NvRvBp5xJk zMjqVwNSh}YNCL!38+$5QZow`Y0_K|KIUKS=!m68Cf8+`03X+#1w;FfOD z$*yL*G73~6rOIWqRIu#U5e&!T z(CZF^Zj@$@dI!}d!{^i)oN$`zwMip2nujT0Lm?GYRb1Y`BzM$$L*_&iBx2x)zQ|wS zz9TminmAY`6sy$Lz}8jEh(Nnq8uB_5BH^zNhiK*p$+=*0bP%T#tf*_sQVW2kBWQ@} z5txn@v=3f5{3&>Dren7?ylSb3|DhQki$lc7^B&ME+hV{@eWRBrS0NRTs!`4bl4hy1+~#47dIc}TF(-pjD6IY2$5uZv43 zh+R^m-E|p(9!z|(-auI+MDNoqfeTfR)-~pG8<-+{V%Lwx$boWSxT-b^)G1qLeyDOc zh)J;+RhjrSN6LgF>R|<+Ljj{yz{fQgR;LaPi61y9oU46TtKKO~-^kTqT0*<@N;!|RUO_|hX?8qt3#j;Pt@Tt4w>vLpW-|L1XPZ-*D1RQSc|yRF92!q*{u0O7AexC7y55dI;Ae*)p3 zv#;2fS~dHokgUEr3d!olx{$2i9}CIqRY^-eQSS_y+^}<1)7x-;WW2%;qD70^l8jw3 zO?FFRhsi^3hod;C(qEfC+iI+=`;8I%#;fjhwJ|=PE~&_|S6pk4Ro=lv9vh|`XKFjd z6V;7_0EvYd@W@=gSGIqInR%SQg~gA*kYF3Z-!wS#y>M9Vn~mnRs#&M(njg7A=BXtz TQQ5lcsja=-1=agYHahqpx){fE diff --git a/docs/_build/doctrees/examples.doctree b/docs/_build/doctrees/examples.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f39ec92e3de246c5e9d8f1e6d65820f5f4775ab4 GIT binary patch literal 8315 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 I8-tDi0mD%C+yDRo literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/history.doctree b/docs/_build/doctrees/history.doctree new file mode 100644 index 0000000000000000000000000000000000000000..68423cc749d920fb8dfe4567d9bf3e02490cb612 GIT binary patch literal 4039 zcmbVP?Qa~#8F%8G?X!L77YM4Fm>xnDL%BN#AyH9L8bv6yfkT9pNJwZkw>x(;_Uz7f zX4dh2sMLO-!qP}cuoV)2OTYKeYJbnZ-TFjA#9AlsJoD@`&&%(5nSXTt{hz(H;_-Vn z6*9RPu_#J(#BJ`kA{}NiPh9?e{>DG^zvsukYuFR3GZXUMuYn^JQbmR*`B%B`6T6ej zj;ilBEf1a4N%Ohrhz+s%RemhGzT>1*ytU=`AM$f)!9Vy&TBpq-Ctk4Lc*HMAho9j1 zIxqFwNEx(nxj69Mpix__`;AK5iNB#_!t+TsWqzAEXXG?e?=yw}!;&=oSf24QtgsMNcw%HMY z;rBXzZ@>-WcZK=G%KZJ&XngOZyOaALe*EeEw&q>mMVQ#!uvD}IfA9&5_`vW~57KO^ zWH_o-{fV8WdUu~+y${5Z_#^zc4yy_^vng-v@ke3lwjsG~cz!aZKc~yLJ2|TjZWy29 zU)J`>_7V`q(LWQq{--M9X7B|!lmWJOz$$rZ{g=;gJz?{4$u8c47q)<+E^=4Lsm_w9 z6^b%F#TtOELuYt9KdZf`p+Ma7n-yA-NXSJa%k@zS267ODkFzafXI{^M0y3*V#RYiS8&tU6tm%Z9kV4+%AG-Lra}BWip7r6+Cf#I>LT~o#<|}qRS0nI85p*!Wo8ssJw!U7%1yga zr9&`TysH%6NP6)#eNJYWFZLYMo!((^4T zokB|Pk5+b8M2P?TekpXRK>g|Ms~am{`h7A0z_SAWQ7|a?J%tvQu{npkBdo8Z4EPre z54DK`lnuZJ$53sV_>E8}GuQ}sppjN+5F5VFGN*$j$zPYiS})4tG-&V$uNDLeD4K*R z61Z1Tifo|JFG;E8S)_xDn9#J(FH&uJ(EhT3NazBZU`o911(CFDs>qN^%gs7ZkaN2* z#v(I{q=V32#TGPm@+Er1A(opWF?mALBE)+Kg${8lmk+M_14=f)CYb|;O2*RVpX|Tx z`zcQYqzI~I5*7~ICCZdRcghR@E8$#f-y4rXwxe|6gic1<%#ltviL+1uoPpyp!s8H* zEzpOroxB5o_RTC@5l@t*_}|vzk-3cUddAI2ayKi^Ks6W(7b_grb!>_hiqH}sZ22Pq zG7g%|Yzzo&N(j01`*x8yb`c0U7YaXs_lDAh`&}C|WZB;`q_l;jUMSY(GEh2XRSTky z4}B2$GTGqe!iD(yEK6|&&9X&rscHZk5hya50RvT0IHW3Jv*`+(j0w9+voaHD>O8~b z%F(nUr0)V62+keOxEX@$EZ{MdD!|lDMYquUpqiV3RW&OM+NEFT$vI80eyc1c$Xy^& zCXqyLxWF+p=O|5>To0fWkmWFoqnxAhQYrU`SE%JY3o@k5n#BgyQ;fo(ZxXS5KNdfV zAH*Z^nfOk8oB1y7xJ3$8X(0UZQarj8-(6Oz$ za8ya5T&?*^{o9n14^|=Q@l>k@7X|B!E5wGodqrZmKDGGh@QQrYT;p;i(alv^)efc% zRFV*r65xV96KbX4aoB)HvU#tfe-CGToj*iYV8lg!;qG7o1UeA2R^Kixa;T;@?QS{5 z|EU?`fBlFqMgt6HxF{g6F~IAA73dz#So|!OWBoii@_td>H)sO$ whfP1J<6ppVry&=qyi*OjC>?Xk;+^)@?|6d8<^RfYca5kOR$YU_n@vam2iH0SrvLx| literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree index e619b1a4ac8559a3b39865c08046d9edc399644d..79b0e2b01544df471b991478ba8d10bca351ff7a 100644 GIT binary patch literal 5453 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 literal 17879 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 KN3o4NpZ@@*99I(n literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/modules.doctree b/docs/_build/doctrees/modules.doctree index 186a5a8a1128332d8523ca5395820933c4e501c9..696c7e864247f76d2ffdd723f5b23a8fccf54fc4 100644 GIT binary patch delta 270 zcmdlhwoHVzfpw}h*F@IH$-5ZMCjRo^>|rZNEK1EQnKGH1DUMYoLoGvNavoE=7Ma_V9qeh zFwd~?LpKarC)^E88RnDMFq<)&PJYZB$I-)Dl39|II%Tsn%SuMZoXu}pjTjltH!HBO kW)kY*1i8PYvLLm1O6`;kvDzt{Uvv5}vN>chmnP`}01_Tv&Hw-a delta 549 zcmZvZK}!Nb6vx@sUELBSi9DEJZkULopZG z>DV=hj-I>q5&Q`CJ$kEU3LYMBhI#M*e(yi8^B)V!o${QY?JDP;kVAE5v@GF?^u4$h z8=!y+p$Z-}t}ug{bnJ=8j)-|`G;@cpZW{Gm(YU0-ug2ow8NFs$JGJIP48*zGCN{O0 zfH|&R)LVMeZ4Ryht~xE()~Pt*LDR4>yEW1kg}BQ@j5I9L#6eL=Km-;c07>stDurR` zSaxfmbt^jwSoYylh_Z^YhOv&3#z=I(tI8hi!+}?j8Xd?$9+Hs7<{;{A;hc$H9%U_^ z*_7t4Y|?I1Taa-%7yEPn9KH^s(vbv@HHhh;MRaJ9>03nppm?k__4$|87oS1#z;MX{ zByKnfI8HON4YJ;gye(zCzFd_d+S?7hNzzmAE0~w0Y%i|9%PUZUvcomsN_Nwx4*oV& V9vw(wE$frOckmOUqK64-PAPxiq!6A@9$fx}N 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 Y1!{8xYKzb4&ZyXII){UCa^O5~0Fw5tng9R* diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo index acd1aed..cbbaf3d 100644 --- a/docs/_build/html/.buildinfo +++ b/docs/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file records the configuration used when building these files. When it is not found, a full rebuild will be done. -config: cec21682d6cc0df78936fbd198ac0c57 +config: 11d168bc3ba21763cf541d100b9a19c3 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_build/html/_modules/euclidlike/backgrounds.html b/docs/_build/html/_modules/euclidlike/backgrounds.html index 1041421..82899f6 100644 --- a/docs/_build/html/_modules/euclidlike/backgrounds.html +++ b/docs/_build/html/_modules/euclidlike/backgrounds.html @@ -38,7 +38,7 @@

Source code for euclidlike.backgrounds

@@ -288,6 +285,14 @@

GalSim-Euclid-Like

Navigation

+

Related Topics

diff --git a/docs/_build/html/_modules/euclidlike/bandpass.html b/docs/_build/html/_modules/euclidlike/bandpass.html index 05560f0..76a7977 100644 --- a/docs/_build/html/_modules/euclidlike/bandpass.html +++ b/docs/_build/html/_modules/euclidlike/bandpass.html @@ -52,7 +52,7 @@

Source code for euclidlike.bandpass

 from . import vis_red_limit, vis_blue_limit
 
 
-[docs] +[docs] def getBandpasses(AB_zeropoint=True, default_thin_trunc=True, full_bandpass=False, **kwargs): """ Function to get the bandpass information for the Euclid VIS band and the three Euclid NISP passbands. @@ -185,6 +185,14 @@

GalSim-Euclid-Like

Navigation

+

Related Topics

diff --git a/docs/_build/html/_modules/euclidlike/euclidlike_psf.html b/docs/_build/html/_modules/euclidlike/euclidlike_psf.html index 47409b6..3b5022b 100644 --- a/docs/_build/html/_modules/euclidlike/euclidlike_psf.html +++ b/docs/_build/html/_modules/euclidlike/euclidlike_psf.html @@ -100,7 +100,7 @@

Source code for euclidlike.euclidlike_psf

 _get_quadrant_psf = LRU_Cache(__get_quadrant_psf)
 
 
-[docs] +[docs] def getPSF( ccd, bandpass, ccd_pos=None, wcs=None, @@ -231,7 +231,7 @@

Source code for euclidlike.euclidlike_psf

 
 
 
-[docs] +[docs] def getBrightPSF( ccd, bandpass, @@ -433,6 +433,14 @@

GalSim-Euclid-Like

Navigation

+

Related Topics

diff --git a/docs/_build/html/_modules/euclidlike/euclidlike_wcs.html b/docs/_build/html/_modules/euclidlike/euclidlike_wcs.html index 284db9a..ae3388b 100644 --- a/docs/_build/html/_modules/euclidlike/euclidlike_wcs.html +++ b/docs/_build/html/_modules/euclidlike/euclidlike_wcs.html @@ -119,7 +119,7 @@

Source code for euclidlike.euclidlike_wcs

 
 
 
-[docs] +[docs] def getWCS(world_pos, PA=None, date=None, CCDs=None, PA_is_FPA=False, SAA=None): """ This routine returns a dict containing a WCS for each of the Euclid CCDs. @@ -246,8 +246,6 @@

Source code for euclidlike.euclidlike_wcs

 
 
 
-
-[docs] def convertCenter(world_pos, CCD, PA=None, date=None, SAA=None, PA_is_FPA=False, tol=0.5*coord.arcsec): """ This is a simple helper routine that takes an input position ``world_pos`` that is meant to @@ -316,12 +314,11 @@

Source code for euclidlike.euclidlike_wcs

         shift_val = np.abs(world_pos.distanceTo(test_sca_pos)/coord.arcsec)
         fpa_cent = coord.CelestialCoord(fpa_cent.ra + delta_ra, fpa_cent.dec + delta_dec)
 
-    return fpa_cent
- + return fpa_cent
-[docs] +[docs] def findCCD(wcs_dict, world_pos, include_border=False): """ This is a subroutine to take a dict of WCS (one per CCD) from euclidlike.getWCS() and query @@ -583,8 +580,6 @@

Source code for euclidlike.euclidlike_wcs

     return date, CCDs, pa_fpa, pa_obsy
 
 
-
-[docs] def allowedPos(world_pos, date, SAA=None): """ This routine can be used to check whether Euclid would be allowed to look at a particular @@ -623,12 +618,9 @@

Source code for euclidlike.euclidlike_wcs

     # Check if it's within tolerance.
     min_ang = 90. - min_sun_angle/coord.degrees
     max_ang = 90. + max_sun_angle/coord.degrees
-    return min_ang <= angle_deg <= max_ang
- + return min_ang <= angle_deg <= max_ang -
-[docs] def bestPA(world_pos, date, SAA=None): """ This routine determines the best position angle for the observatory for a given observation date @@ -671,8 +663,7 @@

Source code for euclidlike.euclidlike_wcs

     # celestial north pole.  It is defined as position angle east of north.
     north = coord.CelestialCoord(y_obs.ra, 90.*coord.degrees)
     obs_pa = world_pos.angleBetween(y_obs, north)
-    return obs_pa
- + return obs_pa
@@ -700,6 +691,14 @@

GalSim-Euclid-Like

Navigation

+

Related Topics

diff --git a/docs/_build/html/_modules/euclidlike_imsim/bandpass.html b/docs/_build/html/_modules/euclidlike_imsim/bandpass.html new file mode 100644 index 0000000..5c34fef --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/bandpass.html @@ -0,0 +1,144 @@ + + + + + + + euclidlike_imsim.bandpass — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.bandpass

+import euclidlike
+from galsim.config import BandpassBuilder, RegisterBandpassType, GetAllParams
+
+
+
+[docs] +class EuclidlikeBandpassBuilder(BandpassBuilder): + """A class for loading a Bandpass from a file + + FileBandpass expected the following parameter: + + name (str) The name of the Euclid filter to get. (required) + """ +
+[docs] + def buildBandpass(self, config, base, logger): + """Build the Bandpass based on the specifications in the config dict. + + Parameters: + config: The configuration dict for the bandpass type. + base: The base configuration dict. + logger: If provided, a logger for logging debug statements. + + Returns: + the constructed Bandpass object. + """ + req = {'name': str} + kwargs, safe = GetAllParams(config, base, req=req) + + name = kwargs['name'] + # Hard set the limit due to PSF definition + bandpass = euclidlike.getBandpasses()[name] + + return bandpass, safe
+
+ + + +RegisterBandpassType('EuclidlikeBandpass', EuclidlikeBandpassBuilder()) +RegisterBandpassType('EuclidlikeBandpassTrimmed', EuclidlikeBandpassBuilder()) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/ccd.html b/docs/_build/html/_modules/euclidlike_imsim/ccd.html new file mode 100644 index 0000000..db285cb --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/ccd.html @@ -0,0 +1,331 @@ + + + + + + + euclidlike_imsim.ccd — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.ccd

+import galsim
+import galsim.config
+from galsim.config import RegisterImageType
+from galsim.config.image_scattered import ScatteredImageBuilder
+from galsim.errors import GalSimConfigValueError
+from galsim.image import Image
+from astropy.time import Time
+import numpy as np
+
+import euclidlike
+from euclidlike.instrument_params import gain, saturation
+from .noise import cfg_noise_key, parse_noise_config, get_noise
+
+
+
+[docs] +class EuclidlikeCCDImageBuilder(ScatteredImageBuilder): + +
+[docs] + def setup(self, config, base, image_num, obj_num, ignore, logger): + """Do the initialization and setup for building the image. + + This figures out the size that the image will be, but doesn't actually build it yet. + + Parameters: + config: The configuration dict for the image field. + base: The base configuration dict. + image_num: The current image number. + obj_num: The first object number in the image. + ignore: A list of parameters that are allowed to be in config that we can + ignore here. i.e. it won't be an error if these parameters are present. + logger: If given, a logger object to log progress. + + Returns: + xsize, ysize + """ + logger.debug( + "image %d: Building EuclidlikeCCD: image, obj = %d,%d", + image_num, + image_num, + obj_num, + ) + + self.nobjects = self.getNObj(config, base, image_num, logger=logger) + logger.debug("image %d: nobj = %d", image_num, self.nobjects) + + # These are allowed for Scattered, but we don't use them here. + extra_ignore = [ + "image_pos", + "world_pos", + "stamp_size", + "stamp_xsize", + "stamp_ysize", + "nobjects", + ] + req = {"CCD": int, "filter": str, "mjd": float, "exptime": float} + opt = { + "draw_method": str, + } + opt.update({key: bool for key in cfg_noise_key}) + params = galsim.config.GetAllParams( + config, base, req=req, opt=opt, ignore=ignore + extra_ignore + )[0] + + self.ccd = params["CCD"] + base["CCD"] = self.ccd + self.filter = params["filter"] + self.mjd = params["mjd"] + self.exptime = params["exptime"] + + self.cfg_noise = parse_noise_config(params) + + # If draw_method isn't in image field, it may be in stamp. Check. + self.draw_method = params.get( + "draw_method", base.get("stamp", {}).get("draw_method", "auto") + ) + + # If user hasn't overridden the bandpass to use, get the standard one. + if "bandpass" not in config: + base["bandpass"] = galsim.config.BuildBandpass( + base["image"], "bandpass", base, logger=logger + ) + + return euclidlike.n_pix_col, euclidlike.n_pix_row
+ + +
+[docs] + def buildImage(self, config, base, image_num, obj_num, logger): + """Build an Image containing multiple objects placed at arbitrary locations. + + Parameters: + config: The configuration dict for the image field. + base: The base configuration dict. + image_num: The current image number. + obj_num: The first object number in the image. + logger: If given, a logger object to log progress. + + Returns: + the final image and the current noise variance in the image as a tuple + """ + full_xsize = base["image_xsize"] + full_ysize = base["image_ysize"] + wcs = base["wcs"] + + full_image = Image(full_xsize, full_ysize, dtype=float) + full_image.setOrigin(base["image_origin"]) + full_image.wcs = wcs + full_image.setZero() + + full_image.header = galsim.FitsHeader() + full_image.header["EXPTIME"] = self.exptime + full_image.header["MJD-OBS"] = self.mjd + full_image.header["DATE-OBS"] = str(Time(self.mjd, format="mjd").datetime) + full_image.header["FILTER"] = self.filter + full_image.header["GAIN"] = gain + full_image.header["ZPTMAG"] = 2.5 * np.log10( + self.exptime * euclidlike.collecting_area + ) + + base["current_image"] = full_image + + if "image_pos" in config and "world_pos" in config: + raise GalSimConfigValueError( + "Both image_pos and world_pos specified for Scattered image.", + (config["image_pos"], config["world_pos"]), + ) + + if "image_pos" not in config and "world_pos" not in config: + xmin = base["image_origin"].x + xmax = xmin + full_xsize - 1 + ymin = base["image_origin"].y + ymax = ymin + full_ysize - 1 + config["image_pos"] = { + "type": "XY", + "x": {"type": "Random", "min": xmin, "max": xmax}, + "y": {"type": "Random", "min": ymin, "max": ymax}, + } + + nbatch = self.nobjects // 1000 + 1 + for batch in range(nbatch): + start_obj_num = self.nobjects * batch // nbatch + end_obj_num = self.nobjects * (batch + 1) // nbatch + nobj_batch = end_obj_num - start_obj_num + if nbatch > 1: + logger.warning( + "Start batch %d/%d with %d objects [%d, %d)", + batch + 1, + nbatch, + nobj_batch, + start_obj_num, + end_obj_num, + ) + stamps, current_vars = galsim.config.BuildStamps( + nobj_batch, base, logger=logger, obj_num=start_obj_num, do_noise=False + ) + base["index_key"] = "image_num" + + for k in range(nobj_batch): + # This is our signal that the object was skipped. + if stamps[k] is None: + continue + bounds = stamps[k].bounds & full_image.bounds + if not bounds.isDefined(): # pragma: no cover + # These noramlly show up as stamp==None, but technically it is possible + # to get a stamp that is off the main image, so check for that here to + # avoid an error. But this isn't covered in the imsim test suite. + continue + + logger.debug( + "image %d: full bounds = %s", image_num, str(full_image.bounds) + ) + logger.debug( + "image %d: stamp %d bounds = %s", + image_num, + k + start_obj_num, + str(stamps[k].bounds), + ) + logger.debug("image %d: Overlap = %s", image_num, str(bounds)) + full_image[bounds] += stamps[k][bounds] + stamps = None + + return full_image, None
+ + +
+[docs] + def addNoise(self, image, config, base, image_num, obj_num, current_var, logger): + """Add the final noise to a Scattered image + + Parameters: + image: The image onto which to add the noise. + config: The configuration dict for the image field. + base: The base configuration dict. + image_num: The current image number. + obj_num: The first object number in the image. + current_var: The current noise variance in each postage stamps. + logger: If given, a logger object to log progress. + """ + # check ignore noise + if self.cfg_noise["ignore_noise"]: + return + + if "noise_image" not in base.keys(): + get_noise(self.cfg_noise, config, base, logger) + + # We first have to apply gain and quantize the image + image /= gain + image.quantize() + + image += base["noise_image"] + + # Apply saturation + saturation_ADU = np.round(saturation/gain) + mask_saturated = image.array > saturation_ADU + base["saturated_mask"] = mask_saturated + image.array[mask_saturated] = saturation_ADU + + if self.cfg_noise["sky_subtract"]: + image -= base["sky_image"]
+
+ + + +# Register this as a valid type +RegisterImageType("euclidlike_ccd", EuclidlikeCCDImageBuilder()) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/noise.html b/docs/_build/html/_modules/euclidlike_imsim/noise.html new file mode 100644 index 0000000..36a03a4 --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/noise.html @@ -0,0 +1,384 @@ + + + + + + + euclidlike_imsim.noise — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.noise

+import numpy as np
+
+from astropy.time import Time
+
+import galsim
+from galsim.errors import GalSimConfigError
+
+import euclidlike
+from euclidlike.instrument_params import gain, read_noise
+
+# Some place holder stuff, will need to update later in euclidlike
+# This is just to avoid changing the code and don't have "errors"
+stray_light_fraction = 0.
+dark_current = 0.
+
+cfg_noise_key = [
+    "ignore_noise",
+    "stray_light",
+    "thermal_background",
+    "reciprocity_failure",
+    "dark_current",
+    "nonlinearity",
+    "ipc",
+    "read_noise",
+    "sky_subtract",
+]
+
+
+
+[docs] +def parse_noise_config(params): + + cfg_noise = {} + for key in cfg_noise_key: + cfg_noise[key] = params.get(key, False) + + cfg_noise["exptime"] = params["exptime"] + cfg_noise["mjd"] = params["mjd"] + + return cfg_noise
+ + + +
+[docs] +def get_noise(cfg_noise, cfg_image, base, logger): + + noise_img = base["current_image"].copy() + noise_img.fill(0) + + wcs = base["wcs"] + bp = base["bandpass"] + rng = galsim.config.GetRNG(cfg_image, base) + logger.info( + "image %d: Start EuclidlikeCCD detector effects", base.get("image_num", 0) + ) + + # Things that will eventually be subtracted (if sky_subtract) will have their expectation + # value added to sky_image. So technically, this includes things that aren't just sky. + # E.g. includes dark_current and thermal backgrounds. + sky_image = noise_img.copy() + sky_level = euclidlike.getSkyLevel( + bp, + world_pos=wcs.toWorld(noise_img.true_center), + date=Time(cfg_noise["mjd"], format="mjd").datetime, + ) + logger.debug("Adding sky_level = %s", sky_level) + if cfg_noise["stray_light"]: + logger.debug("Stray light fraction = %s", stray_light_fraction) + sky_level *= 1.0 + stray_light_fraction + wcs.makeSkyImage(sky_image, sky_level) + + # The image up to here is an expectation value. + # Realize it as an integer number of photons. + poisson_noise = galsim.noise.PoissonNoise(rng) + logger.debug("Adding poisson noise to sky photons") + sky_image1 = sky_image.copy() + sky_image1.addNoise(poisson_noise) + noise_img.quantize() + # the image won't necessarily be integers. + noise_img += sky_image1 + + # Apply the detector effects here. Not all of these are "noise" per se, but they + # happen interspersed with various noise effects, so apply them all in this step. + + if cfg_noise["dark_current"]: + dc = dark_current * cfg_noise["exptime"] + logger.debug("Adding dark current: %s", dc) + sky_image += dc + dark_noise = galsim.noise.DeviateNoise( + galsim.random.PoissonDeviate(rng, dc) + ) + noise_img.addNoise(dark_noise) + + if cfg_noise["read_noise"]: + logger.debug("Adding read noise %s", read_noise) + noise_img.addNoise(galsim.GaussianNoise(rng, sigma=read_noise)) + + logger.debug("Applying gain %s", gain) + noise_img /= gain + + # Make integer ADU now. + noise_img.quantize() + + sky_image /= gain + sky_image.quantize() + + base["noise_image"] = noise_img + base["sky_image"] = sky_image
+ + + +
+[docs] +class NoiseImageBuilder(galsim.config.ExtraOutputBuilder): + +
+[docs] + def initialize(self, data, scratch, config, base, logger): + """Do any initial setup for this builder at the start of a new output file. + + The base class implementation saves two work space items into self.data and self.scratch + that can be used to safely communicate across multiple processes. + + Parameters: + data: An empty list of length nimages to use as work space. + scratch: An empty dict that can be used as work space. + config: The configuration field for this output object. + base: The base configuration dict. + logger: If given, a logger object to log progress. [default: None] + """ + req = {"CCD": int, "filter": str, "mjd": float, "exptime": float} + opt = {key: bool for key in cfg_noise_key} + ignore = galsim.config.image.image_ignore + extra_ignore = [ + "image_pos", + "world_pos", + "stamp_size", + "stamp_xsize", + "stamp_ysize", + "nobjects", + ] + params = galsim.config.GetAllParams( + base["image"], base, req=req, opt=opt, ignore=ignore+extra_ignore, + )[0] + self.cfg_noise = parse_noise_config(params) + + self._check_input() + + self.data = data + self.scratch = scratch + self.final_data = None
+ + + def _check_input(self): + if self.cfg_noise["ignore_noise"]: + raise GalSimConfigError( + "You cannot ignore the noise and request the noise image at the same time." + " Either active the noise or remove the output noise image." + ) + +
+[docs] + def processImage(self, index, obj_nums, config, base, logger): + """Perform any necessary processing at the end of each image construction. + + This function will be called after each full image is built. + + Compute the noise for the current image and add it to the image. + It will also create an independent noise image. + The code optionally subtract the background if requested. + + Parameters: + index: The index in self.data to use for this image. This isn't the image_num + (which can be accessed at base['image_num'] if needed), but rather + an index that starts at 0 for the first image being worked on and + goes up to nimages-1. + obj_nums: The object numbers that were used for this image. + config: The configuration field for this output object. + base: The base configuration dict. + logger: If given, a logger object to log progress. [default: None] + """ + if "noise_image" not in base.keys(): + get_noise(self.cfg_noise, config, base, logger) + + noise_image = base["noise_image"].copy() + + if self.cfg_noise["sky_subtract"]: + noise_image -= base["sky_image"] + + self.data[index] = noise_image
+
+ + + +
+[docs] +class SkyImageBuilder(NoiseImageBuilder): + + def _check_input(self): + if self.cfg_noise["ignore_noise"]: + raise GalSimConfigError( + "You cannot ignore the noise and request the sky image at the same time." + " Either activate the noise or remove the output sky image." + ) + +
+[docs] + def processImage(self, index, obj_nums, config, base, logger): + """Perform any necessary processing at the end of each image construction. + + This function will be called after each full image is built. + + Compute the sky background and return it in an image. + + Parameters: + index: The index in self.data to use for this image. This isn't the image_num + (which can be accessed at base['image_num'] if needed), but rather + an index that starts at 0 for the first image being worked on and + goes up to nimages-1. + obj_nums: The object numbers that were used for this image. + config: The configuration field for this output object. + base: The base configuration dict. + logger: If given, a logger object to log progress. [default: None] + """ + if "noise_image" not in base.keys(): + get_noise(self.cfg_noise, config, base, logger) + + self.data[index] = base["sky_image"].copy()
+
+ + + +
+[docs] +class WeightImageBuilder(NoiseImageBuilder): + + def _check_input(self): + if self.cfg_noise["ignore_noise"]: + raise GalSimConfigError( + "You cannot ignore the noise and request the weight image at the same time." + " Either activate the noise or remove the output sky image." + ) + +
+[docs] + def processImage(self, index, obj_nums, config, base, logger): + """Perform any necessary processing at the end of each image construction. + + This function will be called after each full image is built. + + Compute the weight map from the noise image and return it in an image. + + Parameters: + index: The index in self.data to use for this image. This isn't the image_num + (which can be accessed at base['image_num'] if needed), but rather + an index that starts at 0 for the first image being worked on and + goes up to nimages-1. + obj_nums: The object numbers that were used for this image. + config: The configuration field for this output object. + base: The base configuration dict. + logger: If given, a logger object to log progress. [default: None] + """ + if "noise_image" not in base.keys(): + get_noise(self.cfg_noise, config, base, logger) + + noise_var = np.var(base["noise_image"].array) + + weight_image = galsim.ImageF(base["image_bounds"]) + weight_image += noise_var + weight_image.invertSelf() + + self.data[index] = weight_image
+
+ + + +galsim.config.RegisterExtraOutput('noise_image', NoiseImageBuilder()) +galsim.config.RegisterExtraOutput('sky_image', SkyImageBuilder()) +galsim.config.RegisterExtraOutput('weight_image', WeightImageBuilder()) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/obseq.html b/docs/_build/html/_modules/euclidlike_imsim/obseq.html new file mode 100644 index 0000000..74ece02 --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/obseq.html @@ -0,0 +1,227 @@ + + + + + + + euclidlike_imsim.obseq — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.obseq

+from astropy.time import Time
+import pandas as pd
+import galsim
+import galsim.config
+from galsim.angle import Angle
+from galsim.config import InputLoader, RegisterValueType, RegisterInputType
+from galsim.errors import GalSimConfigValueError
+
+
+OBS_KIND = [
+    "VIS_LONG",
+    "VIS_SHORT",
+    "NISP_J",
+    "NISP_H",
+    "NISP_Y",
+]
+
+
+[docs] +class ObSeqDataLoader(object): + """Read the exposure information from the observation sequence.""" + + _req_params = {"file_name": str, "visit": int, "obs_kind": str, "CCD": int} + + def __init__(self, file_name, visit, obs_kind, CCD, logger=None): + self.logger = galsim.config.LoggerWrapper(logger) + self.file_name = file_name + self.visit = visit + self.ccd = CCD + + if obs_kind not in OBS_KIND: + raise GalSimConfigValueError( + "Invalid obs_kind.", obs_kind, OBS_KIND + ) + self.obs_kind = obs_kind + + # try: + self.read_obseq() + # except: + # # Read visit info from the config file. + # self.logger.warning('Reading visit info from config file.') + +
+[docs] + def read_obseq(self): + """Read visit info from the obseq file.""" + if self.file_name is None: + raise ValueError( + "No obseq filename provided, trying to build from config information." + ) + if self.visit is None: + raise ValueError( + "The visit must be set when reading visit info from an obseq file." + ) + + self.logger.warning( + "Reading info from obseq file %s for visit %s", self.file_name, self.visit + ) + + ob = pd.read_pickle(self.file_name).loc[self.visit] + + self.ob = {} + for obs_kind in OBS_KIND: + _ob = {} + _ob["visit"] = self.visit + _ob["ccd"] = self.ccd + _ob["ra"] = ob.loc[obs_kind]["ra"] * galsim.degrees + _ob["dec"] = ob.loc[obs_kind]["dec"] * galsim.degrees + _ob["pa"] = ob.loc[obs_kind]["pa"] * galsim.degrees + _ob["saa"] = ob.loc[obs_kind]["saa"] * galsim.degrees + _ob["date"] = Time(ob.loc[obs_kind]["date"], format="mjd").datetime + _ob["mjd"] = ob.loc[obs_kind]["date"] + _ob["filter"] = ob.loc[obs_kind]["filter"] + _ob["exptime"] = ob.loc[obs_kind]["exptime"] + self.ob[obs_kind] = _ob
+ + +
+[docs] + def get(self, field, default=None, obs_kind=None): + + if obs_kind is None: + obs_kind = self.obs_kind + else: + if obs_kind not in OBS_KIND: + raise KeyError( + f"OpsimData obs_kind {obs_kind} not present in ob, " + f"must be in {OBS_KIND}." + ) + ob = self.ob[obs_kind] + + if field not in ob and default is None: + raise KeyError("OpsimData field %s not present in ob" % field) + + return ob.get(field, default)
+
+ + + +
+[docs] +def ObSeqData(config, base, value_type): + """Returns the obseq data for a pointing.""" + pointing = galsim.config.GetInputObj("obseq_data", config, base, "OpSeqDataLoader") + + req = {"field": str} + opt = {"obs_kind": str} + + kwargs, safe = galsim.config.GetAllParams(config, base, req=req, opt=opt) + field = kwargs["field"] + obs_kind = kwargs.get("obs_kind", None) + + val = value_type(pointing.get(field, obs_kind=obs_kind)) + return val, safe
+ + + +RegisterInputType( + "obseq_data", InputLoader(ObSeqDataLoader, file_scope=True, takes_logger=True) +) +RegisterValueType( + "ObSeqData", ObSeqData, [float, int, str, Angle], input_type="obseq_data" +) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/photonOps.html b/docs/_build/html/_modules/euclidlike_imsim/photonOps.html new file mode 100644 index 0000000..e60a325 --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/photonOps.html @@ -0,0 +1,194 @@ + + + + + + + euclidlike_imsim.photonOps — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.photonOps

+_w1 = 0.17519
+_w2 = 0.53146
+_w3 = 0.29335
+_s  = 0.3279
+_s1 = 0.4522*_s
+_s2 = 0.8050*_s
+_s3 = 1.4329*_s
+
+import numpy as np
+from galsim import PhotonOp,UniformDeviate,GaussianDeviate
+from galsim.config import PhotonOpBuilder,RegisterPhotonOpType,get_cls_params,GetAllParams,GetRNG
+
+
+[docs] +class ChargeDiff(PhotonOp): + """A photon operator that applies the effect of charge diffusion via a probablistic model limit. + """ + def __init__(self, rng=None, **kwargs): + + self.ud = UniformDeviate(rng) + self.gd1 = GaussianDeviate(rng, sigma=_s1) + self.gd2 = GaussianDeviate(rng, sigma=_s2) + self.gd3 = GaussianDeviate(rng, sigma=_s3) + +
+[docs] + def applyTo(self, photon_array, local_wcs=None, rng=None): + """Apply the charge diffusion effect to the photons + + Parameters: + photon_array: A `PhotonArray` to apply the operator to. + local_wcs: A `LocalWCS` instance defining the local WCS for the current photon + bundle in case the operator needs this information. [default: None] + rng: A random number generator to use if needed. [default: None] + """ + + # Choose which weighted Gausian to use in sech model approximation + u = np.empty(len(photon_array.x)) + self.ud.generate(u) + + # Selects appropriate fraction of photons corresponding to the first gaussian in the sech model + mask = u<_w1 + dx = np.empty(np.sum(mask)) + dy = np.empty(np.sum(mask)) + # Generate and apply the 2D gaussian shifts corresponding to the first gaussian + self.gd1.generate(dx) + self.gd1.generate(dy) + photon_array.x[mask] += dx + photon_array.y[mask] += dy + + # Selects appropriate fraction of photons corresponding to the second gaussian in the sech model + mask = (u>=_w1)&(u<=(1.-_w3)) + dx = np.empty(np.sum(mask)) + dy = np.empty(np.sum(mask)) + # Generate and apply the 2D gaussian shifts corresponding to the second gaussian + self.gd2.generate(dx) + self.gd2.generate(dy) + photon_array.x[mask] += dx + photon_array.y[mask] += dy + + # Selects appropriate fraction of photons corresponding to the third gaussian in the sech model + mask = u>(1.-_w3) + dx = np.empty(np.sum(mask)) + dy = np.empty(np.sum(mask)) + # Generate and apply the 2D gaussian shifts corresponding to the second gaussian + self.gd3.generate(dx) + self.gd3.generate(dy) + photon_array.x[mask] += dx + photon_array.y[mask] += dy
+
+ + + +
+[docs] +class ChargeDiffBuilder(PhotonOpBuilder): + """Build ChargeDiff photonOp + """ +
+[docs] + def buildPhotonOp(self, config, base, logger): + req, opt, single, takes_rng = get_cls_params(ChargeDiff) + kwargs, safe = GetAllParams(config, base, req, opt, single) + rng = GetRNG(config, base, logger, "Roman_stamp") + kwargs['rng'] = rng + return ChargeDiff(**kwargs)
+
+ + +RegisterPhotonOpType('ChargeDiff', ChargeDiffBuilder()) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/psf.html b/docs/_build/html/_modules/euclidlike_imsim/psf.html new file mode 100644 index 0000000..361ca93 --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/psf.html @@ -0,0 +1,304 @@ + + + + + + + euclidlike_imsim.psf — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.psf

+import galsim
+import euclidlike
+import galsim.config
+from galsim.config import RegisterObjectType, RegisterInputType, OpticalPSF, InputLoader
+
+import euclidlike
+
+
+
+[docs] +class EuclidlikePSF(object): + """Class building needed Euclidlike PSFs.""" + + def __init__( + self, + CCD=None, + WCS=None, + n_waves=None, + bpass=None, + extra_aberrations=None, + logger=None, + ): + + logger = galsim.config.LoggerWrapper(logger) + # n_waves parameter is only used for treatment of bright objects. In here we use n_waves = 5 + # to speed up computation of the ChromaticOpticalPSF used for bright objects. + if n_waves == -1: + n_waves = 5 + + corners = [ + galsim.PositionD(1, 1), + galsim.PositionD(1, euclidlike.n_pix_row), + galsim.PositionD(euclidlike.n_pix_col, 1), + galsim.PositionD(euclidlike.n_pix_col, euclidlike.n_pix_row), + ] + cc = galsim.PositionD(euclidlike.n_pix_col / 2, euclidlike.n_pix_row/ 2) + tags = ["ll", "lu", "ul", "uu"] + self.PSF = {} + pupil_bin = 8 + self.PSF[pupil_bin] = {} + for tag, CCD_pos in tuple(zip(tags, corners)): + self.PSF[pupil_bin][tag] = self._psf_call( + CCD, bpass, CCD_pos, WCS, pupil_bin, n_waves, logger, extra_aberrations + ) + for pupil_bin in [4, 2, "achromatic"]: + self.PSF[pupil_bin] = self._psf_call( + CCD, bpass, cc, WCS, pupil_bin, n_waves, logger, extra_aberrations + ) + + def _parse_pupil_bin(self, pupil_bin): + if pupil_bin == "achromatic": + return 8 + else: + return pupil_bin + + def _psf_call( + self, CCD, bpass, CCD_pos, WCS, pupil_bin, n_waves, logger, extra_aberrations + ): + + if pupil_bin == 8: + psf = euclidlike.getPSF( + CCD, + bpass.name, + ccd_pos=CCD_pos, + wcs=WCS, + # pupil_bin=pupil_bin, + # n_waves=n_waves, + logger=logger, + # Don't set wavelength for this one. + # We want this to be chromatic for photon shooting. + # wavelength = bpass.effective_wavelength, + # extra_aberrations=extra_aberrations, + ) + else: + psf = euclidlike.getBrightPSF( + CCD, + bpass.name, + ccd_pos=CCD_pos, + wcs=WCS, + pupil_bin=self._parse_pupil_bin(pupil_bin), + n_waves=n_waves, + logger=logger, + # Note: setting wavelength makes it achromatic. + # We only use pupil_bin = 2,4 for FFT objects. + wavelength=bpass.effective_wavelength, + ) + + # psf = euclidlike.getPSF( + # CCD, + # bpass.name, + # ccd_pos=CCD_pos, + # wcs=WCS, + # # pupil_bin=self._parse_pupil_bin(pupil_bin), + # # n_waves=n_waves, + # logger=logger, + # # Note: setting wavelength makes it achromatic. + # # We only use pupil_bin = 2,4 for FFT objects. + # wavelength=bpass.effective_wavelength, + # # extra_aberrations=extra_aberrations, + # ) + if pupil_bin == 4: + return psf.withGSParams(maximum_fft_size=16384, folding_threshold=1e-3) + elif pupil_bin == 2: + return psf.withGSParams(maximum_fft_size=16384, folding_threshold=1e-4) + else: + return psf.withGSParams(maximum_fft_size=16384) + +
+[docs] + def getPSF(self, pupil_bin, pos): + """ + Return a PSF to be convolved with sources. + PSF is sampled at 4 quadrants for each CCD. Returned PSF + corresponds to that of the quadrant of the CCD position. + + @param [in] what pupil binning to request. + """ + ## For now no interpolation is used + #wll = (euclidlike.n_pix_col - pos.x) * (euclidlike.n_pix_row - pos.y) + #wlu = (euclidlike.n_pix_col - pos.x) * (pos.y - 1) + #wul = (pos.x - 1) * (euclidlike.n_pix_row - pos.y) + #wuu = (pos.x - 1) * (pos.y - 1) + #return ( + # wll * psf["ll"] + wlu * psf["lu"] + wul * psf["ul"] + wuu * psf["uu"] + #) / ((euclidlike.n_pix_row - 1) * (euclidlike.n_pix_col - 1)) + + + psf = self.PSF[pupil_bin] + if pupil_bin != 8: + return psf + + quad_row = 'l' + quad_col = 'l' + if pos.y > euclidlike.n_pix_row/2: + quad_row = 'u' + if pos.x > euclidlike.n_pix_col/2: + quad_col = 'u' + quad_pos = quad_col + quad_row + return psf[quad_pos]
+
+ + + + + +
+[docs] +class PSFLoader(InputLoader): + """PSF loader.""" + + def __init__(self): + # Override some defaults in the base init. + super().__init__(init_func=EuclidlikePSF, takes_logger=True, use_proxy=False) + +
+[docs] + def getKwargs(self, config, base, logger): + logger.debug("Get kwargs for PSF") + + req = {} + opt = { + "n_waves": int, + } + ignore = ["extra_aberrations"] + + # If CCD is in base, then don't require it in the config file. + # (Presumably because using Euclidlike image type, which sets it there for convenience.) + if "CCD" in base: + opt["CCD"] = int + else: + req["CCD"] = int + + kwargs, safe = galsim.config.GetAllParams( + config, base, req=req, opt=opt, ignore=ignore + ) + + # If not given in kwargs, then it must have been in base, so this is ok. + if "CCD" not in kwargs: + kwargs["CCD"] = base["CCD"] + + kwargs["extra_aberrations"] = galsim.config.ParseAberrations( + "extra_aberrations", config, base, "EuclidlikePSF" + ) + kwargs["WCS"] = galsim.config.BuildWCS( + base["image"], "wcs", base, logger=logger + ) + kwargs["bpass"] = galsim.config.BuildBandpass( + base["image"], "bandpass", base, logger + )[0] + + logger.debug("kwargs = %s", kwargs) + + return kwargs, False
+
+ + + +# Register this as a valid type +RegisterInputType("euclidlike_psf", PSFLoader()) +# RegisterObjectType('euclidlike_psf', BuildEuclidlikePSF, input_type='euclidlikepsf_loader') +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/skycat.html b/docs/_build/html/_modules/euclidlike_imsim/skycat.html new file mode 100644 index 0000000..f31c627 --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/skycat.html @@ -0,0 +1,631 @@ + + + + + + + euclidlike_imsim.skycat — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.skycat

+"""
+Interface to obtain objects from skyCatalogs.
+"""
+
+import os
+import numpy as np
+import galsim
+from galsim.config import (
+    InputLoader,
+    RegisterInputType,
+    RegisterValueType,
+    RegisterObjectType,
+)
+
+import euclidlike
+
+
+
+[docs] +class SkyCatalogInterface: + """Interface to skyCatalogs package.""" + + _trivial_sed = galsim.SED( + galsim.LookupTable([100, 2600], [1, 1], interpolant="linear"), + wave_type="nm", + flux_type="fphotons", + ) + + def __init__( + self, + file_name, + exptime, + wcs=None, + mjd=None, + bandpass=None, + xsize=None, + ysize=None, + obj_types=None, + edge_pix=100, + max_flux=None, + logger=None, + ): + """ + Parameters + ---------- + file_name : str + Name of skyCatalogs yaml config file. + wcs : galsim.WCS + WCS of the image to render. + mjd : float + MJD of the midpoint of the exposure. + exptime : float + Exposure time. + xsize : int + Size in pixels of CCD in x-direction. + ysize : int + Size in pixels of CCD in y-direction. + obj_types : list-like [None] + List or tuple of object types to render, e.g., ('star', 'galaxy'). + If None, then consider all object types. + edge_pix : float [100] + Size in pixels of the buffer region around nominal image + to consider objects. + logger : logging.Logger [None] + Logger object. + """ + self.file_name = file_name + self.wcs = wcs + self.mjd = mjd + self.exptime = exptime + self.bandpass = bandpass + if xsize is not None: + self.xsize = xsize + else: + self.xsize = euclidlike.n_pix_col + if ysize is not None: + self.ysize = ysize + else: + self.ysize = euclidlike.n_pix_row + self.obj_types = obj_types + self.edge_pix = edge_pix + self.logger = galsim.config.LoggerWrapper(logger) + + if obj_types is not None: + self.logger.warning(f"Object types restricted to {obj_types}") + self.ccd_center = wcs.toWorld( + galsim.PositionD(self.xsize / 2.0, self.ysize / 2.0) + ) + self._objects = None + + @property + def objects(self): + from skycatalogs import skyCatalogs + + if self._objects is None: + + # Select objects from polygonal region bounded by CCD edges + corners = ( + (-self.edge_pix, -self.edge_pix), + (self.xsize + self.edge_pix, -self.edge_pix), + (self.xsize + self.edge_pix, self.ysize + self.edge_pix), + (-self.edge_pix, self.ysize + self.edge_pix), + ) + vertices = [] + for x, y in corners: + sky_coord = self.wcs.toWorld(galsim.PositionD(x, y)) + vertices.append( + (sky_coord.ra / galsim.degrees, sky_coord.dec / galsim.degrees) + ) + region = skyCatalogs.PolygonalRegion(vertices) + sky_cat = skyCatalogs.open_catalog(self.file_name) + self._objects = sky_cat.get_objects_by_region( + region, obj_type_set=self.obj_types, mjd=self.mjd + ) + if not self._objects: + self.logger.warning("No objects found on image.") + else: + self._build_dtype_dict() + return self._objects + + def _build_dtype_dict(self): + self._dtype_dict = {} + obj_types = [] + for coll in self._objects.get_collections(): + objects_type = coll._object_type_unique + if objects_type in obj_types: + continue + col_names = list(coll.native_columns) + for col_name in col_names: + try: + # Some columns cannot be read in snana + np_type = coll.get_native_attribute(col_name).dtype.type() + except Exception as e: + self.logger.warning( + f"The column {col_name} could not be read from skyCatalog." + ) + continue + if np_type is None: + py_type = str + else: + py_type = type(np_type.astype(object)) + self._dtype_dict[col_name] = py_type + +
+[docs] + def get_ccd_center(self): + """ + Return the CCD center. + """ + return self.ccd_center
+ + +
+[docs] + def getNObjects(self): + """ + Return the number of GSObjects to render + """ + return len(self.objects)
+ + +
+[docs] + def getApproxNObjects(self): + """ + Return the approximate number of GSObjects to render, as set in + the class initializer. + """ + return self.getNObjects()
+ + +
+[docs] + def getWorldPos(self, index): + """ + Return the sky coordinates of the skyCatalog object + corresponding to the specified index. + + Parameters + ---------- + index : int + Index of the (object_index, subcomponent) combination. + + Returns + ------- + galsim.CelestialCoord + """ + skycat_obj = self.objects[index] + ra, dec = skycat_obj.ra, skycat_obj.dec + return galsim.CelestialCoord(ra * galsim.degrees, dec * galsim.degrees)
+ + +
+[docs] + def getFlux(self, index, filter=None, mjd=None, exptime=None): + """ + Return the flux associated to an object. + + Parameters + ---------- + index : int + Index of the object in the self.objects catalog. + filter : str, optional + Name of the filter for which the flux is computed. If None, use the + filter provided during initialization. [Default: None] + mjd : float, optional + Date of the observation in MJD format. If None, use the + mjd provided during initialization. [Default: None] + exptime : int or float, optional + Exposure time of the observation. If None, use the + exptime provided during initialization. [Default: None] + + Returns + ------- + flux + Computer flux at the given date for the requested exposure time and + filter. + """ + + if filter is None: + filter = self.bandpass.name + if mjd is None: + mjd = self.mjd + if exptime is None: + exptime = self.exptime + + skycat_obj = self.objects[index] + # We cache the SEDs for potential later use + self._seds = skycat_obj.get_observer_sed_components() + for i, sed in enumerate(self._seds.values()): + if i == 0: + sed_sum = sed + else: + sed_sum += sed + raw_flux = skycat_obj.get_euclid_flux( + filter, + sed_sum, + mjd=mjd, + cache=False + ) + if hasattr(skycat_obj, "get_wl_params"): + _, _, mu = skycat_obj.get_wl_params() + else: + mu = 1. + flux = raw_flux * mu * exptime * euclidlike.collecting_area + + return flux
+ + +
+[docs] + def getValue(self, index, field): + """ + Return a skyCatalog value for the an object. + + Parameters + ---------- + index : int + Index of the object in the self.objects catalog. + field : str + Name of the field for which you want the value. + + Returns + ------- + int or float or str or None + The value associated to the field or None if the field do not exist. + """ + + skycat_obj = self.objects[index] + + if field not in self._dtype_dict: + # We cannot raise an error because one could have a field for snana + # in the config and we don't want to crash because there are no SN + # in this particular image. We then default to False which might not + # be the right type for the required column but we have no way of knowing + # the correct type if the column do not exist. + self.logger.warning(f"The field {field} was not found in skyCatalog.") + return None + elif field not in skycat_obj.native_columns: + if self._dtype_dict[field] is int: + # There are no "special value" for integer so we default to + # hopefully something completely off + return -9999 + elif self._dtype_dict[field] is float: + return np.nan + elif self._dtype_dict[field] is str: + return None + else: + return skycat_obj.get_native_attribute(field)
+ + +
+[docs] + def getObj(self, index, gsparams=None, rng=None, exptime=30): + """ + Return the galsim object for the skyCatalog object + corresponding to the specified index. If the skyCatalog + object is a galaxy, the returned galsim object will be + a galsim.Sum. + + Parameters + ---------- + index : int + Index of the object in the self.objects catalog. + + Returns + ------- + galsim.GSObject + """ + if not self.objects: + raise RuntimeError("Trying to get an object from an empty sky catalog") + + faint = False + skycat_obj = self.objects[index] + gsobjs = skycat_obj.get_gsobject_components(gsparams) + + # Compute the flux or get the cached value. + flux = self.getFlux(index) + if np.isnan(flux): + return None + + # Set up simple SED if too faint + if flux < 40: + faint = True + if not faint: + seds = skycat_obj.get_observer_sed_components(mjd=self.mjd) + + gs_obj_list = [] + for component in gsobjs: + if faint: + gsobjs[component] = gsobjs[component].evaluateAtWavelength( + self.bandpass + ) + gs_obj_list.append( + gsobjs[component] + * self._trivial_sed + * self.exptime + * euclidlike.collecting_area + ) + else: + if component in seds: + gs_obj_list.append( + gsobjs[component] + * seds[component] + * self.exptime + * euclidlike.collecting_area + ) + + if not gs_obj_list: + return None + + if len(gs_obj_list) == 1: + gs_object = gs_obj_list[0] + else: + gs_object = galsim.Add(gs_obj_list) + + # Give the object the right flux + gs_object.flux = flux + gs_object.withFlux(gs_object.flux, self.bandpass) + + # Get the object type + if (skycat_obj.object_type == "diffsky_galaxy") | ( + skycat_obj.object_type == "galaxy" + ): + gs_object.object_type = "galaxy" + if skycat_obj.object_type == "star": + gs_object.object_type = "star" + if skycat_obj.object_type == "snana": + gs_object.object_type = "transient" + + return gs_object
+
+ + + +
+[docs] +class SkyCatalogLoader(InputLoader): + """ + Class to load SkyCatalogInterface object. + """ + +
+[docs] + def getKwargs(self, config, base, logger): + req = {"file_name": str, "exptime": float} + opt = { + "edge_pix": float, + "obj_types": list, + "mjd": float, + } + kwargs, safe = galsim.config.GetAllParams(config, base, req=req, opt=opt) + wcs = galsim.config.BuildWCS(base["image"], "wcs", base, logger=logger) + kwargs["wcs"] = wcs + kwargs["logger"] = logger + + if "bandpass" not in config: + base["bandpass"] = galsim.config.BuildBandpass( + base["image"], "bandpass", base, logger=logger + )[0] + + kwargs["bandpass"] = base["bandpass"] + # Sky catalog object lists are created per CCD, so they are + # not safe to reuse. + safe = False + return kwargs, safe
+
+ + + +
+[docs] +def SkyCatObj(config, base, ignore, gsparams, logger): + """ + Build an object according to info in the sky catalog. + """ + skycat = galsim.config.GetInputObj("sky_catalog", config, base, "SkyCatObj") + + # Ensure that this sky catalog matches the CCD being simulated by + # comparing center locations on the sky. + world_center = base["world_center"] + ccd_center = skycat.get_ccd_center() + sep = ccd_center.distanceTo(base["world_center"]) / galsim.arcsec + # Centers must agree to within at least 1 arcsec: + if sep > 1.0: + message = ( + "skyCatalogs selection and CCD center do not agree: \n" + "skycat.ccd_center: " + f"{ccd_center.ra/galsim.degrees:.5f}, " + f"{ccd_center.dec/galsim.degrees:.5f}\n" + "world_center: " + f"{world_center.ra/galsim.degrees:.5f}, " + f"{world_center.dec/galsim.degrees:.5f} \n" + f"Separation: {sep:.2e} arcsec" + ) + raise RuntimeError(message) + + # Setup the indexing sequence if it hasn't been specified. The + # normal thing with a catalog is to just use each object in order, + # so we don't require the user to specify that by hand. We can do + # it for them. + galsim.config.SetDefaultIndex(config, skycat.getNObjects()) + + req = {"index": int} + opt = {"num": int} + kwargs, safe = galsim.config.GetAllParams(config, base, req=req, opt=opt) + index = kwargs["index"] + + rng = galsim.config.GetRNG(config, base, logger, "SkyCatObj") + + obj = skycat.getObj(index, gsparams=gsparams, rng=rng) + base["object_id"] = skycat.objects[index].id + + return obj, safe
+ + + +
+[docs] +def SkyCatWorldPos(config, base, value_type): + """Return a value from the object part of the skyCatalog""" + skycat = galsim.config.GetInputObj("sky_catalog", config, base, "SkyCatWorldPos") + + # Setup the indexing sequence if it hasn't been specified. The + # normal thing with a catalog is to just use each object in order, + # so we don't require the user to specify that by hand. We can do + # it for them. + galsim.config.SetDefaultIndex(config, skycat.getNObjects()) + + req = {"index": int} + opt = {"num": int} + kwargs, safe = galsim.config.GetAllParams(config, base, req=req, opt=opt) + index = kwargs["index"] + + pos = skycat.getWorldPos(index) + return pos, safe
+ + + +
+[docs] +def SkyCatValue(config, base, value_type): + """Return a value from the object part of the skyCatalog + """ + + skycat = galsim.config.GetInputObj("sky_catalog", config, base, "SkyCatValue") + + # Setup the indexing sequence if it hasn't been specified. The + # normal thing with a catalog is to just use each object in order, + # so we don't require the user to specify that by hand. We can do + # it for them. + galsim.config.SetDefaultIndex(config, skycat.getNObjects()) + + req = {"field": str, "index": int} + opt = {"obs_kind": str} + params, safe = galsim.config.GetAllParams(config, base, req=req, opt=opt) + field = params["field"] + index = params["index"] + obs_kind = params.get("obs_kind", None) + + if field == "flux": + if obs_kind is None: + val = skycat.getFlux(index) + else: + pointing = galsim.config.GetInputObj("obseq_data", config, base, "OpSeqDataLoader") + filter = pointing.get("filter", obs_kind=obs_kind) + exptime = pointing.get("exptime", obs_kind=obs_kind) + mjd = pointing.get("mjd", obs_kind=obs_kind) + val = skycat.getFlux(index, filter=filter, exptime=exptime, mjd=mjd) + else: + val = skycat.getValue(index, field) + + return val, safe
+ + + + +RegisterInputType("sky_catalog", SkyCatalogLoader(SkyCatalogInterface, has_nobj=True)) +RegisterObjectType("SkyCatObj", SkyCatObj, input_type="sky_catalog") +RegisterValueType( + "SkyCatWorldPos", SkyCatWorldPos, [galsim.CelestialCoord], input_type="sky_catalog" +) + +# Here we have to provide None as a type otherwise Galsim complains but I don't know why.. +RegisterValueType( + "SkyCatValue", SkyCatValue, [float, int, str, None] # , input_type="sky_catalog" +) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/stamp.html b/docs/_build/html/_modules/euclidlike_imsim/stamp.html new file mode 100644 index 0000000..00c4a59 --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/stamp.html @@ -0,0 +1,454 @@ + + + + + + + euclidlike_imsim.stamp — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.stamp

+import numpy as np
+import galsim
+import euclidlike
+import galsim.config
+from galsim.config import RegisterStampType, StampBuilder
+# import os, psutil
+# process = psutil.Process()
+
+# Parameter below determines the flux at which we switch from using Euclid-like PSF to the bright star PSF
+# This is done to avoid visual artifacts from using the Euclid-like PSF for very bright objects.
+# Tests to determine this value can be found here: https://github.com/GalSim-developers/GalSim-Euclid-Like/issues/46
+psf_switch_limit = 8e5
+
+
+[docs] +class Euclidlike_stamp(StampBuilder): + """This performs the tasks necessary for building the stamp for a single object. + + It uses the regular Basic functions for most things. + It specializes the quickSkip, buildProfile, and draw methods. + """ + _trivial_sed = galsim.SED( + galsim.LookupTable( + [100, 2600], + [1, 1], + interpolant='linear' + ), + wave_type='nm', flux_type='fphotons' + ) + +
+[docs] + def setup(self, config, base, xsize, ysize, ignore, logger): + """ + Do the initialization and setup for building a postage stamp. + + In the base class, we check for and parse the appropriate size and position values in + config (aka base['stamp'] or base['image']. + + Values given in base['stamp'] take precedence if these are given in both places (which + would be confusing, so probably shouldn't do that, but there might be a use case where it + would make sense). + + Parameters: + config: The configuration dict for the stamp field. + base: The base configuration dict. + xsize: The xsize of the image to build (if known). + ysize: The ysize of the image to build (if known). + ignore: A list of parameters that are allowed to be in config that we can + ignore here. i.e. it won't be an error if these parameters are present. + logger: A logger object to log progress. + + Returns: + xsize, ysize, image_pos, world_pos + """ + # print('stamp setup',process.memory_info().rss) + + gal = galsim.config.BuildGSObject(base, 'gal', logger=logger)[0] + if gal is None: + raise galsim.config.SkipThisObject('gal is None (invalid parameters)') + base['object_type'] = gal.object_type + bandpass = base['bandpass'] + if not hasattr(gal, 'flux'): + # In this case, the object flux has not been precomputed + # or cached by the skyCatalogs code. + gal.flux = gal.calculateFlux(bandpass) + self.flux = gal.flux + # Cap (star) flux at 30M photons to avoid gross artifacts when trying to draw the Euclid PSF in finite time and memory + flux_cap = 3e7 + if self.flux > flux_cap: + if (hasattr(gal, 'original') and hasattr(gal.original, 'original') and isinstance(gal.original.original, galsim.DeltaFunction)) or (isinstance(gal, galsim.DeltaFunction)): + gal = gal.withFlux(flux_cap, bandpass) + self.flux = flux_cap + gal.flux = flux_cap + base['flux'] = gal.flux + base['mag'] = -2.5 * np.log10(gal.flux) + bandpass.zeropoint + # print('stamp setup2',process.memory_info().rss) + + # Compute or retrieve the realized flux. + self.rng = galsim.config.GetRNG(config, base, logger, "Euclidlike_stamp") + self.realized_flux = galsim.PoissonDeviate(self.rng, mean=self.flux)() + base['realized_flux'] = self.realized_flux + + # Check if the realized flux is 0. + if self.realized_flux == 0: + # If so, we'll skip everything after this. + # The mechanism within GalSim to do this is to raise a special SkipThisObject class. + raise galsim.config.SkipThisObject('realized flux=0') + + # Otherwise figure out the stamp size + if self.flux < 10: + # For really faint things, don't try too hard. Just use 32x32. + image_size = 32 + self.pupil_bin = 'achromatic' + + else: + gal_achrom = gal.evaluateAtWavelength(bandpass.effective_wavelength) + if (hasattr(gal_achrom, 'original') and isinstance(gal_achrom.original, galsim.DeltaFunction)): + # For bright stars, set the following stamp size limits + if self.flux < psf_switch_limit: + image_size = 500 + self.pupil_bin = 8 + elif self.flux < 6e6: + image_size = 1000 + self.pupil_bin = 4 + else: + image_size = 1600 + self.pupil_bin = 2 + else: + self.pupil_bin = 8 + # # Get storead achromatic PSF + # psf = galsim.config.BuildGSObject(base, 'psf', logger=logger)[0]['achromatic'] + # obj = galsim.Convolve(gal_achrom, psf).withFlux(self.flux) + obj = gal_achrom.withGSParams(galsim.GSParams(stepk_minimum_hlr=20)) + image_size = obj.getGoodImageSize(euclidlike.pixel_scale) + + # print('stamp setup3',process.memory_info().rss) + base['pupil_bin'] = self.pupil_bin + logger.info('Object flux is %d', self.flux) + logger.info('Object %d will use stamp size = %s', base.get('obj_num', 0), image_size) + + # Determine where this object is going to go: + # This is the same as what the base StampBuilder does: + if 'image_pos' in config: + image_pos = galsim.config.ParseValue(config, 'image_pos', base, galsim.PositionD)[0] + else: + image_pos = None + + if 'world_pos' in config: + world_pos = galsim.config.ParseWorldPos(config, 'world_pos', base, logger) + else: + world_pos = None + + return image_size, image_size, image_pos, world_pos
+ + +
+[docs] + def buildPSF(self, config, base, gsparams, logger): + """Build the PSF object. + + For the Basic stamp type, this builds a PSF from the base['psf'] dict, if present, + else returns None. + + Parameters: + config: The configuration dict for the stamp field. + base: The base configuration dict. + gsparams: A dict of kwargs to use for a GSParams. More may be added to this + list by the galaxy object. + logger: A logger object to log progress. + + Returns: + the PSF + """ + if base.get('psf', {}).get('type', 'euclidlike_psf') != 'euclidlike_psf': + return galsim.config.BuildGSObject(base, 'psf', gsparams=gsparams, logger=logger)[0] + + euclidlike_psf = galsim.config.GetInputObj('euclidlike_psf', config, base, 'buildPSF') + psf = euclidlike_psf.getPSF(self.pupil_bin, base['image_pos']) + return psf
+ + +
+[docs] + def getDrawMethod(self, config, base, logger): + """Determine the draw method to use. + + @param config The configuration dict for the stamp field. + @param base The base configuration dict. + @param logger A logger object to log progress. + + @returns method + """ + method = galsim.config.ParseValue(config,'draw_method',base,str)[0] + if method not in galsim.config.valid_draw_methods: + raise galsim.GalSimConfigValueError("Invalid draw_method.", method, + galsim.config.valid_draw_methods) + if method == 'auto': + if self.pupil_bin in [4,2]: + logger.info('Auto -> Use FFT drawing for object %d.',base['obj_num']) + return 'fft' + else: + logger.info('Auto -> Use photon shooting for object %d.',base['obj_num']) + return 'phot' + else: + # If user sets something specific for the method, rather than auto, + # then respect their wishes. + logger.info('Use specified method=%s for object %d.',method,base['obj_num']) + return method
+ + +
+[docs] + @classmethod + def fix_seds(cls, prof, bandpass): + # If any SEDs are not currently using a LookupTable for the function or if they are + # using spline interpolation, then the codepath is quite slow. + # Better to fix them before doing WavelengthSampler. + + if (isinstance(prof, galsim.SimpleChromaticTransformation) and + (not isinstance(prof._flux_ratio._spec, galsim.LookupTable) + or prof._flux_ratio._spec.interpolant != 'linear')): + original = prof._original + sed = prof._flux_ratio + wave_list, _, _ = galsim.utilities.combine_wave_list(sed, bandpass) + f = np.broadcast_to(sed(wave_list), wave_list.shape) + new_spec = galsim.LookupTable(wave_list, f, interpolant='linear') + new_sed = galsim.SED( + new_spec, + 'nm', + 'fphotons' if sed.spectral else '1' + ) + prof._flux_ratio = new_sed + + # Also recurse onto any components. + if isinstance(prof, galsim.ChromaticObject): + if hasattr(prof, 'obj_list'): + for obj in prof.obj_list: + cls.fix_seds(obj, bandpass) + if hasattr(prof, 'original'): + cls.fix_seds(prof.original, bandpass)
+ + +
+[docs] + def draw(self, prof, image, method, offset, config, base, logger): + """Draw the profile on the postage stamp image. + + Parameters: + prof: The profile to draw. + image: The image onto which to draw the profile (which may be None). + method: The method to use in drawImage. + offset: The offset to apply when drawing. + config: The configuration dict for the stamp field. + base: The base configuration dict. + logger: A logger object to log progress. + + Returns: + the resulting image + """ + if prof is None: + # If was decide to do any rejection steps, this could be set to None, in which case, + # don't draw anything. + return image + + # Prof is normally a convolution here with obj_list being [gal, psf1, psf2,...] + # for some number of component PSFs. + # print('stamp draw',process.memory_info().rss) + + gal, *psfs = prof.obj_list if hasattr(prof, 'obj_list') else [prof] + + faint = self.flux < 40 + bandpass = base['bandpass'] + if faint: + logger.info("Flux = %.0f Using trivial sed", self.flux) + else: + self.fix_seds(gal, bandpass) + + image.wcs = base['wcs'] + + # Set limit on the size of photons batches to consider when + # calling gsobject.drawImage. + maxN = int(1e6) + if 'maxN' in config: + maxN = galsim.config.ParseValue(config, 'maxN', base, int)[0] + # print('stamp draw2',process.memory_info().rss) + + if method == 'fft': + fft_image = image.copy() + fft_offset = offset + kwargs = dict( + method='fft', + offset=fft_offset, + image=fft_image, + ) + if not faint and config.get('fft_photon_ops'): + kwargs.update({ + "photon_ops": galsim.config.BuildPhotonOps(config, 'fft_photon_ops', base, logger), + "maxN": maxN, + "rng": self.rng, + "n_subsample": 1, + }) + + # Go back to a combined convolution for fft drawing. + gal = gal.withFlux(self.flux, bandpass) + prof = galsim.Convolve([gal] + psfs) + try: + prof.drawImage(bandpass, **kwargs) + except galsim.errors.GalSimFFTSizeError as e: + # I think this shouldn't happen with the updates I made to how the image size + # is calculated, even for extremely bright things. So it should be ok to + # just report what happened, give some extra information to diagonose the problem + # and raise the error. + logger.error('Caught error trying to draw using FFT:') + logger.error('%s', e) + logger.error('You may need to add a gsparams field with maximum_fft_size to') + logger.error('either the psf or gal field to allow larger FFTs.') + logger.info('prof = %r', prof) + logger.info('fft_image = %s', fft_image) + logger.info('offset = %r', offset) + logger.info('wcs = %r', image.wcs) + raise + # Some pixels can end up negative from FFT numerics. Just set them to 0. + fft_image.array[fft_image.array < 0] = 0. + fft_image.addNoise(galsim.PoissonNoise(rng=self.rng)) + # In case we had to make a bigger image, just copy the part we need. + image += fft_image[image.bounds] + + else: + # We already calculated realized_flux above. Use that now and tell GalSim not + # recalculate the Poisson realization of the flux. + gal = gal.withFlux(self.realized_flux, bandpass) + # print('stamp draw3b ',process.memory_info().rss) + + if not faint and 'photon_ops' in config: + photon_ops = galsim.config.BuildPhotonOps(config, 'photon_ops', base, logger) + else: + photon_ops = [] + + # Put the psfs at the start of the photon_ops. + # Probably a little better to put them a bit later than the start in some cases + # (e.g. after TimeSampler, PupilAnnulusSampler), but leave that as a todo for now. + photon_ops = psfs + photon_ops + + # prof = galsim.Convolve([gal] + psfs) + + # print('-------- gal ----------',gal) + # print('-------- psf ----------',psfs) + + # print('stamp draw3a',process.memory_info().rss) + gal.drawImage(bandpass, + method='phot', + offset=offset, + rng=self.rng, + maxN=maxN, + n_photons=self.realized_flux, + image=image, + photon_ops=photon_ops, + sensor=None, + add_to_image=True, + poisson_flux=False) + # print('stamp draw3',process.memory_info().rss) + + return image
+
+ + + +# Register this as a valid type +RegisterStampType('Euclidlike_stamp', Euclidlike_stamp()) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/utils.html b/docs/_build/html/_modules/euclidlike_imsim/utils.html new file mode 100644 index 0000000..dfadbec --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/utils.html @@ -0,0 +1,250 @@ + + + + + + + euclidlike_imsim.utils — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.utils

+import numpy as np
+import galsim
+import galsim.config
+import galsim.roman as roman
+
+
+[docs] +class roman_utils(object): + """ + Class to contain a variety of helper routines to work with the simulation data. + """ + def __init__(self, config_file,visit=None,sca=None,image_name=None,setup_skycat=False): + """ + Setup information about a simulated Roman image. + Parameters: + config_file: the GalSim config file that produced the simulation + visit: the visit (observation sequence) number of the pointing + sca: the SCA number + image_name: the filename of the image (can be used instead of visit, sca) + setup_skycat: setup the skycatalog information to have access to + """ + config = galsim.config.ReadConfig(config_file)[0] + + self.visit,self.sca = self.check_input(visit,sca,image_name) + + if not setup_skycat: + del config['input']['sky_catalog'] + config['input']['obseq_data']['visit'] = self.visit + config['image']['SCA'] = self.sca + galsim.config.ProcessInput(config) + if setup_skycat: + self.skycat = galsim.config.GetInputObj('sky_catalog',config['input']['sky_catalog'],config,'sky_catalog') + self.PSF = galsim.config.GetInputObj('roman_psf',config['input']['roman_psf'],config,'roman_psf') + self.wcs = galsim.config.BuildWCS(config['image'], 'wcs', config) + self.bpass = galsim.config.BuildBandpass(config['image'], 'bandpass', config, None)[0] + self.photon_ops = galsim.config.BuildPhotonOps(config['stamp'], 'photon_ops', config, None) + self.rng = galsim.config.GetRNG(config, config['image'], None, "psf_image") + +
+[docs] + def check_input(self,visit,sca,image_name): + if image_name is not None: + print('Inferring visit and sca from image_name.') + start = 21 + end = -5 + if 'simple_model' in image_name: + start = 28 + if 'gz' in image_name: + end = -8 + tmp = np.array(image_name[start:end].split('_')).astype(int) + return tmp[0],tmp[1] + if (visit is None) | (sca is None): + raise ValueError('Insufficient information to construct visit info - all inputs are None.') + return visit,sca
+ + +
+[docs] + def getPSF(self,x=None,y=None,pupil_bin=8): + """ + Return Roman PSF for some image position. + Parameters: + x: x-position in SCA + y: y-position in SCA + pupil_bin: pupil image binning factor + Returns: + the chromatic GalSim PSF model object (does not include additional effects like charge diffusion!) + """ + if pupil_bin!=8: + if (x is not None)|(y is not None): + raise ValueError('x,y position for pupil_bin values other than 8 not supported. Using SCA center.') + return self.PSF.getPSF(pupil_bin,galsim.PositionD(roman.n_pix/2,roman.n_pix/2)) + if (x is None) | (y is None): + return self.PSF.getPSF(8,galsim.PositionD(roman.n_pix/2,roman.n_pix/2)) + return self.PSF.getPSF(8,galsim.PositionD(x,y))
+ + +
+[docs] + def getWCS(self): + """ + Return Roman WCS for image + """ + return self.wcs
+ + +
+[docs] + def getLocalWCS(self,x,y): + """ + Return Roman WCS for image + """ + return self.wcs.local(galsim.PositionD(x,y))
+ + +
+[docs] + def getBandpass(self): + """ + Return Roman bandpass for image + """ + return self.bpass
+ + +
+[docs] + def getPSF_Image(self,stamp_size,x=None,y=None,pupil_bin=8,sed=None, + oversampling_factor=1,include_photonOps=False,n_phot=1e6): + """ + Return a Roman PSF image for some image position + Parameters: + stamp_size: size of output PSF model stamp in native roman pixel_scale (oversampling_factor=1) + x: x-position in SCA + y: y-position in SCA + pupil_bin: pupil image binning factor + sed: SED to be used to draw the PSF - default is a flat SED. + oversampling_factor: factor by which to oversample native roman pixel_scale + include_photonOps: include additional contributions from other photon operators in effective psf image + Returns: + the PSF GalSim image object (use image.array to get a numpy array representation) + """ + if sed is None: + sed = galsim.SED(galsim.LookupTable([100, 2600], [1,1], interpolant='linear'), + wave_type='nm', flux_type='fphotons') + point = galsim.DeltaFunction()*sed + point = point.withFlux(1,self.bpass) + local_wcs = self.getLocalWCS(x,y) + wcs = galsim.JacobianWCS(dudx=local_wcs.dudx/oversampling_factor, + dudy=local_wcs.dudy/oversampling_factor, + dvdx=local_wcs.dvdx/oversampling_factor, + dvdy=local_wcs.dvdy/oversampling_factor) + stamp = galsim.Image(stamp_size*oversampling_factor,stamp_size*oversampling_factor,wcs=wcs) + if not include_photonOps: + psf = galsim.Convolve(point, self.getPSF(x,y,pupil_bin)) + return psf.drawImage(self.bpass,image=stamp,wcs=wcs,method='no_pixel') + photon_ops = [self.getPSF(x,y,pupil_bin)] + self.photon_ops + return point.drawImage(self.bpass, + method='phot', + rng=self.rng, + maxN=1e6, + n_photons=1e6, + image=stamp, + photon_ops=photon_ops, + poisson_flux=False)
+
+ +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/euclidlike_imsim/wcs.html b/docs/_build/html/_modules/euclidlike_imsim/wcs.html new file mode 100644 index 0000000..9c8bdad --- /dev/null +++ b/docs/_build/html/_modules/euclidlike_imsim/wcs.html @@ -0,0 +1,169 @@ + + + + + + + euclidlike_imsim.wcs — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for euclidlike_imsim.wcs

+from astropy.time import Time
+import galsim
+import euclidlike
+from galsim.config import WCSBuilder, RegisterWCSType
+from galsim.angle import Angle
+from galsim.celestial import CelestialCoord
+
+
+
+[docs] +class EuclidlikeWCS(WCSBuilder): + +
+[docs] + def buildWCS(self, config, base, logger): + + req = { + "CCD": int, + "ra": Angle, + "dec": Angle, + "pa": Angle, + "mjd": float, + } + opt = { + "saa": Angle, + "min_sun_angle": float, + "max_sun_angle": float, + "force_cvz": bool, + } + + kwargs, safe = galsim.config.GetAllParams( + config, + base, + req=req, + opt=opt, + ) + if "min_sun_angle" in kwargs: + euclidlike.instrument_params.min_sun_angle = \ + kwargs["min_sun_angle"] * galsim.degrees + euclidlike.euclidlike_wcs.min_sun_angle = \ + kwargs["min_sun_angle"] * galsim.degrees + if "max_sun_angle" in kwargs: + euclidlike.instrument_params.max_sun_angle = \ + kwargs["max_sun_angle"] * galsim.degrees + euclidlike.euclidlike_wcs.max_sun_angle = \ + kwargs["max_sun_angle"] * galsim.degrees + if "saa" in kwargs: + SAA = kwargs["saa"] + else: + SAA = None + pointing = CelestialCoord(ra=kwargs["ra"], dec=kwargs["dec"]) + wcs = euclidlike.getWCS( + world_pos=pointing, + PA=kwargs["pa"], + date=Time(kwargs["mjd"], format="mjd").datetime, + CCDs=kwargs["CCD"], + PA_is_FPA=True, + SAA=SAA, + )[kwargs["CCD"]] + return wcs
+
+ + + +RegisterWCSType("EuclidlikeWCS", EuclidlikeWCS()) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/index.html b/docs/_build/html/_modules/index.html index 4b0a73d..5eea8e7 100644 --- a/docs/_build/html/_modules/index.html +++ b/docs/_build/html/_modules/index.html @@ -35,6 +35,18 @@

All modules for which code is available

  • euclidlike.bandpass
  • euclidlike.euclidlike_psf
  • euclidlike.euclidlike_wcs
  • +
  • euclidlike_imsim.bandpass
  • +
  • euclidlike_imsim.ccd
  • +
  • euclidlike_imsim.noise
  • +
  • euclidlike_imsim.obseq
  • +
  • euclidlike_imsim.photonOps
  • +
  • euclidlike_imsim.psf
  • +
  • euclidlike_imsim.skycat
  • +
  • euclidlike_imsim.stamp
  • +
  • euclidlike_imsim.utils
  • +
  • euclidlike_imsim.wcs
  • +
  • scripts.download_psf
  • +
  • scripts.make_euclidlike_pupil_plane
  • @@ -62,6 +74,14 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/_modules/scripts/download_psf.html b/docs/_build/html/_modules/scripts/download_psf.html new file mode 100644 index 0000000..f4f4a05 --- /dev/null +++ b/docs/_build/html/_modules/scripts/download_psf.html @@ -0,0 +1,619 @@ + + + + + + + scripts.download_psf — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + +

    Source code for scripts.download_psf

    +
    +"""
    +A program to download the Euclid-like PSF sampled across the focal plane for discrete wavelengths.
    +The code below was adapted from: https://github.com/GalSim-developers/GalSim/blob/releases/2.5/galsim/download_cosmos.py
    +"""
    +
    +import os, sys, zipfile, subprocess, shutil, json
    +import argparse
    +import logging
    +from urllib.request import urlopen
    +
    +from galsim._version import __version__ as version
    +#from .meta_data import share_dir
    +from galsim.utilities import ensure_dir
    +from galsim.main import make_logger
    +
    +script_name = 'euclidlike_download_psf'
    +script_dir = os.path.dirname(__file__)
    +share_dir = os.path.join(script_dir, '..', 'euclidlike', 'data')
    +
    +
    +[docs] +def parse_args(command_args): + """Handle the command line arguments using either argparse (if available) or optparse. + """ + # Another potential option we might want to add is to download the smaller training sample + # rather than the full 4 GB file. Right now, this just downloads the larger catalog. + + # Short description strings common to both parsing mechanisms + description = "This program will download the Euclid-like PSF \n" + description += "and place them in the GalSim-Euclid-Like data directory so they can be used as\n " + description += "the default files for the euclid-like PSF.\n" + description += "See https://github.com/GalSim-developers/GalSim-Euclid-Like/wiki/Euclid-Like-PSF\n" + description += "for more details about the files being downloaded." + epilog = "Note: The unpacked files total almost 4 GB in size!\n" + + # Build the parser and add arguments + parser = argparse.ArgumentParser(description=description, epilog=epilog, add_help=True) + parser.add_argument( + '-v', '--verbosity', type=int, action='store', default=2, choices=(0, 1, 2, 3), + help='Integer verbosity level: min=0, max=3 [default=2]') + parser.add_argument( + '-f', '--force', action='store_const', default=False, const=True, + help='Force overwriting the current file if one exists') + parser.add_argument( + '-q', '--quiet', action='store_const', default=False, const=True, + help="Don't ask about re-downloading an existing file. (implied by verbosity=0)") + parser.add_argument( + '-u', '--unpack', action='store_const', default=False, const=True, + help='Re-unpack the tar file if not downloading') + parser.add_argument( + '--save', action='store_const', default=False, const=True, + help="Save the tarball after unpacking.") + parser.add_argument( + '-d', '--dir', action='store', default=None, + help="Install into an alternate directory and link from the euclidlike/data directory") + parser.add_argument( + '--nolink', action='store_const', default=False, const=True, + help="Don't link to the alternate directory from euclidlike/data") + args = parser.parse_args(command_args) + args.log_file = None + args.log_format = None + + # Return the args + return args
    + + +
    +[docs] +def get_input(): # pragma: no cover + # A level of indirection to make it easier to test functions using input. + # This one isn't covered, since we always mock it. + return input()
    + + +# Based on recipe 577058: http://code.activestate.com/recipes/577058/ +
    +[docs] +def query_yes_no(question, default="yes"): + """Ask a yes/no question via input() and return their answer. + + "question" is a string that is presented to the user. + "default" is the presumed answer if the user just hits <Enter>. + It must be "yes" (the default), "no" or None (meaning + an answer is required of the user). + + The "answer" return value is one of "yes" or "no". + """ + valid = {"yes":"yes", "y":"yes", "ye":"yes", + "no":"no", "n":"no"} + if default == None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + + while 1: + sys.stdout.write(question + prompt) + choice = get_input().lower() + if default is not None and choice == '': + choice = default + break + elif choice in valid.keys(): + break + else: + sys.stdout.write("Please respond with 'yes' or 'no' "\ + "(or 'y' or 'n').\n") + return valid[choice]
    + + + +
    +[docs] +def get_names(args, logger): + if args.dir is not None: + target_dir = os.path.expanduser(args.dir) + do_link = not args.nolink + else: + target_dir = share_dir + do_link = False + + url ='https://cosmo.vera.psc.edu/Euclid-like-PSFs/monopsfs_euclidlike.zip' + file_name = os.path.basename(url) + target = os.path.join(target_dir, file_name) + link_dir = os.path.join(share_dir, file_name)[:-len('.zip')] + unpack_dir = target[:-len('.zip')] + logger.warning('Downloading from url:\n %s',url) + logger.warning('Target location is:\n %s',target) + target_dir = unpack_dir + + return url, target, target_dir, link_dir, unpack_dir, do_link
    + + + + +
    +[docs] +def get_meta(url, args, logger): + logger.info('') + + # See how large the file to be downloaded is. + u = urlopen(url) + meta = u.info() + logger.debug("Meta information about url:\n%s",str(meta)) + file_name = os.path.basename(url) + file_size = int(meta.get("Content-Length")) + logger.info("Size of %s: %d MBytes" , file_name, file_size/1024**2) + + return meta
    + + +
    +[docs] +def check_existing(target, unpack_dir, meta, args, logger): + # Make sure the directory we want to put this file exists. + ensure_dir(target) + + do_download = True + # If file already exists + if os.path.isfile(target): + file_size = int(meta.get("Content-Length")) + logger.info("") + existing_file_size = os.path.getsize(target) + if args.force: + logger.info("Target file already exists. Size = %d MBytes. Forced re-download.", + existing_file_size/1024**2) + elif file_size == existing_file_size: + if args.quiet: + logger.info("Target file already exists. Not re-downloading.") + do_download = False + else: + q = "Target file already exists. Overwrite?" + yn = query_yes_no(q, default='no') + if yn == 'no': + do_download = False + else: + logger.warning("Target file already exists, but it seems to be either incomplete, " + "corrupt, or obsolete") + if args.quiet: + logger.info("Size of existing file = %d MBytes. Re-downloading.", + existing_file_size/1024**2) + else: + q = "Size of existing file = %d MBytes. Re-download?"%(existing_file_size/1024**2) + yn = query_yes_no(q, default='yes') + if yn == 'no': + do_download = False + elif unpack_dir is not None and os.path.isdir(unpack_dir): + logger.info("") + + # Check that this is the current version. + meta_file = os.path.join(unpack_dir, 'meta.json') + logger.debug('meta_file = %s',meta_file) + if os.path.isfile(meta_file): + logger.debug('meta_file exists') + with open(meta_file) as fp: + saved_meta_dict = json.load(fp) + # Get rid of the unicode + saved_meta_dict = dict([ (str(k),str(v)) for k,v in saved_meta_dict.items()]) + saved_meta_dict = {k.lower():v for k,v in saved_meta_dict.items()} + logger.debug("current meta information is %s",saved_meta_dict) + meta_dict = dict(meta) + meta_dict = {k.lower():v for k,v in meta_dict.items()} + logger.debug("url's meta information is %s",meta_dict) + + # There are several checksum tags. If any of them are present and match, + # then file is current. If they don't match, file is obsolete. + # If none are present, then they changed something, so do a longer check. + # (And try to get around to updating this list of checksum keys.) + checksum_keys = ['oc-checksum', 'content-md5', 'etag'] + obsolete = None + for k in checksum_keys: + if k in saved_meta_dict and k in meta_dict: + if saved_meta_dict[k] == meta_dict[k]: + logger.info("Checksum key %s matches. File is up to date."%k) + obsolete = False + else: + logger.info("Checksum key %s doesn't matches. File is obsolete."%k) + obsolete = True + break + + if obsolete is None: + # Check all meta data. If it all matches, then it's fine. + # Otherwise, the file is obsolete. + obsolete = False + for k in meta_dict: + # Skip some keys that don't imply obselescence. + if k.startswith('x-') or k.startswith('retry') or k.startswith('set-cookie'): + continue + if k == 'date' or k == 'last-modified' or k == 'server': + continue + # Others that are missing or different imply obsolete + if k not in saved_meta_dict: + logger.debug("key %s is missing in saved meta information",k) + obsolete = True + elif meta_dict[k] != saved_meta_dict[k]: + logger.debug("key %s differs: %s != %s",k,meta_dict[k],saved_meta_dict[k]) + obsolete = True + else: + logger.debug("key %s matches",k) + else: + logger.debug('meta_file does not exist') + obsolete = True + + if obsolete: + if args.quiet or args.force: + logger.warning("The version currently on disk is obsolete. " + "Downloading new version.") + else: + q = "The version currently on disk is obsolete. Download new version?" + yn = query_yes_no(q, default='yes') + if yn == 'no': + do_download = False + elif args.force: + logger.info("Target file has already been downloaded and unpacked. " + "Forced re-download.") + elif args.quiet: + logger.info("Target file has already been downloaded and unpacked. " + "Not re-downloading.") + args.save = True # Don't delete it! + do_download = False + else: + q = "Target file has already been downloaded and unpacked. Re-download?" + yn = query_yes_no(q, default='no') + if yn == 'no': + args.save = True + do_download = False + return do_download
    + + +
    +[docs] +def download(do_download, url, target, meta, args, logger): + if not do_download: return + logger.info("") + u = urlopen(url) + # This bit is based on one of the answers here: (by PabloG) + # http://stackoverflow.com/questions/22676/how-do-i-download-a-file-over-http-using-python + # The progress feature in that answer is important here, since downloading such a large file + # will take a while. + file_size = int(meta.get("Content-Length")) + try: + with open(target, 'wb') as f: + file_size_dl = 0 + block_sz = 32 * 1024 + next_dot = file_size/100. # For verbosity==1, the next size for writing a dot. + while True: + buffer = u.read(block_sz) + if not buffer: + break + + file_size_dl += len(buffer) + f.write(buffer) + + # Status bar + if args.verbosity >= 2: + status = r"Downloading: %5d / %d MBytes [%3.2f%%]" % ( + file_size_dl/1024**2, file_size/1024**2, file_size_dl*100./file_size) + status = status + '\b'*len(status) + sys.stdout.write(status) + sys.stdout.flush() + elif args.verbosity >= 1 and file_size_dl > next_dot: + sys.stdout.write('.') + sys.stdout.flush() + next_dot += file_size/100. + logger.info("Download complete.") + logger.info("") + except OSError as e: + # Try to give a reasonable suggestion for some common OSErrors. + logger.error("\n\nOSError: %s",str(e)) + if 'Permission denied' in str(e): + logger.error("Rerun using sudo %s",script_name) + logger.error("If this is not possible, you can download to an alternate location:") + logger.error(" %s -d dir_name --nolink\n",script_name) + elif 'Disk quota' in str(e) or 'No space' in str(e): + logger.error("You might need to download this in an alternate location and link:") + logger.error(" %s -d dir_name\n",script_name) + raise
    + + +
    +[docs] +def check_unpack(do_download, unpack_dir, target, args): + # Usually we unpack if we downloaded the tarball or if specified by the command line option. + do_unpack = do_download or args.unpack + + # If the unpack dir is missing, then need to unpack + if not os.path.exists(unpack_dir): + do_unpack = True + + # But of course if there is no tarball, we can't unpack it + if not os.path.isfile(target): + do_unpack = False + + # If we have a downloaded tar file, ask if it should be re-unpacked. + if not do_unpack and not args.quiet and os.path.isfile(target): + q = "Zip file is already unpacked. Re-unpack?" + yn = query_yes_no(q, default='no') + if yn == 'yes': + do_unpack=True + return do_unpack
    + + +
    +[docs] +def unpack(do_unpack, target, target_dir, unpack_dir, meta, args, logger): + if not do_unpack: return + logger.info("Unpacking the zip file...") + with zipfile.ZipFile(target, 'r') as zip_ref: + if args.verbosity >= 3: + zip_ref.printdir() + elif args.verbosity >= 2: + zip_ref.printdir() + + def is_within_directory(directory, target): + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + prefix = os.path.commonprefix([abs_directory, abs_target]) + return prefix == abs_directory + + def safe_extract(zip_ref, path=".", members=None): + # This is somewhat gratuitous for our use case, since we directly control the zip file, + # but it's a good practice to avoid security vulnerabilities. + members = [] + for member in zip_ref.namelist(): + if member != 'VIS_response.fits.gz': # not interested in downloading this file + members.append(member) + member_path = os.path.join(path, member) + if not is_within_directory(path, member_path): # pragma: no cover + raise Exception("Attempted Path Traversal in Zip File") + + zip_ref.extractall(path, members) + + safe_extract(zip_ref, target_dir) + + # Write the meta information to a file, meta.json to mark what version this all is. + meta_file = os.path.join(unpack_dir, 'meta.json') + with open(meta_file, 'w') as fp: + json.dump(dict(meta), fp) + + logger.info("Extracted contents of zip file.") + logger.info("")
    + + + +
    +[docs] +def check_remove(do_unpack, target, args): + # Usually, we remove the tarball if we unpacked it and command line doesn't specify to save it. + do_remove = do_unpack and not args.save + + # But if we didn't unpack it, and they didn't say to save it, ask if we should remove it. + if os.path.isfile(target) and not do_remove and not args.save and not args.quiet: + q = "Remove the zipfile?" + yn = query_yes_no(q, default='no') + if yn == 'yes': + do_remove = True + return do_remove
    + + +
    +[docs] +def remove_tarball(do_remove, target, logger): + if do_remove: + logger.info("Removing the zipfile to save space") + os.remove(target)
    + + + + + + +
    +[docs] +def download_psf(args, logger): + """The main script given the ArgParsed args and a logger + """ + # Give diagnostic about GalSim version + logger.debug("GalSim version: %s",version) + logger.debug("This download script is: %s",__file__) + logger.info("Type %s -h to see command line options.\n",script_name) + + # Some definitions: + # share_dir is the base galsim share directory, e.g. /usr/local/share/galsim/ + # url is the url from which we will download the tarball. + # target is the full path of the downloaded tarball + # target_dir is where we will put the downloaded file, usually == share_dir. + # link_dir is the directory where this would normally have been unpacked. + # unpack_dir is the directory that the tarball will unpack into. + + # caution about storage and ask user if they want to proceed. + q = "You are about to download 4Gb, do you want to proceed?" + yn = query_yes_no(q, default='no') + if yn == 'no': + return + + url, target, target_dir, link_dir, unpack_dir, do_link = get_names(args, logger) + + meta = get_meta(url, args, logger) + + # Check if the file already exists and if it is the right size + do_download = check_existing(target, unpack_dir, meta, args, logger) + + # Download the tarball + download(do_download, url, target, meta, args, logger) + + # Unpack the tarball + do_unpack = check_unpack(do_download, unpack_dir, target, args) + unpack(do_unpack, target, target_dir, unpack_dir, meta, args, logger) + + # Remove the tarball + do_remove = check_remove(do_unpack, target, args) + remove_tarball(do_remove, target, logger) + + # If we are downloading to an alternate directory, we (usually) link to it from share/galsim + make_link(do_link, unpack_dir, link_dir, args, logger)
    + + +
    +[docs] +def main(command_args): + """The whole process given command-line parameters in their native (non-ArgParse) form. + """ + args = parse_args(command_args) + logger = make_logger(args) + download_psf(args, logger)
    + + +
    +[docs] +def run_main(): + """Kick off the process grabbing the command-line parameters from sys.argv + """ + main(sys.argv[1:])
    + +
    + +
    + +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/scripts/make_euclidlike_pupil_plane.html b/docs/_build/html/_modules/scripts/make_euclidlike_pupil_plane.html new file mode 100644 index 0000000..39caf0c --- /dev/null +++ b/docs/_build/html/_modules/scripts/make_euclidlike_pupil_plane.html @@ -0,0 +1,295 @@ + + + + + + + scripts.make_euclidlike_pupil_plane — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + +

    Source code for scripts.make_euclidlike_pupil_plane

    +"""
    +This code has been taken from https://github.com/CosmoStat/wf-psf Liaudat et al.
    +
    +This is an implementation of the function `generate_pupil_obscurations` https://github.com/CosmoStat/wf-psf/blob/87e0c8e9770199cd276f5f0551054cb4902d53bb/src/wf_psf/sims/SimPSFToolkit.py#L233
    +
    +NOTE from Tobias Liaudat:
    +"Simple procedure considering only the 2D plane.
    +No 3D projections wrt the angle of the FoV is done."
    +"""  # noqa
    +from argparse import ArgumentParser
    +import os
    +import importlib.util
    +from importlib.resources import files
    +
    +import numpy as np
    +from scipy.signal import convolve2d
    +
    +import galsim
    +
    +
    +# Telescope parameters
    +AS_diam = 1200  # Aperture stop diameter [mm]
    +M1_diam = 395  # Mirror 1 cap stopper diameter [mm]
    +
    +sp_lenght = 700  # Spider length [mm]
    +sp_width = 12  # Spider width [mm]
    +
    +AS_centre = [0, 0]
    +M1_centre = [0, 51]
    +
    +sp1_angle = 106.78 - 90  # [degrees]
    +sp2_angle = 50.11 - 90  # [degrees]
    +sp3_angle = -10.76 - 90  # [degrees]
    +
    +sp1_x_pos = 260  # [mm]
    +sp1_y_pos = 240  # [mm]
    +sp2_x_pos = -330  # [mm]
    +sp2_y_pos = 130  # [mm]
    +sp3_x_pos = 70  # [mm]
    +sp3_y_pos = -330  # [mm]
    +
    +
    +
    +[docs] +def make_EuclidLike_pupil_plane(N_pix=2048, do_filter=True, N_filter=3): + # Build pupil plane + pupil_plane = np.ones((N_pix, N_pix)) + + # coordinates of map in [mm] + W, H = np.meshgrid( + np.linspace(-AS_diam // 2, AS_diam // 2, N_pix), + np.linspace(-AS_diam // 2, AS_diam // 2, N_pix), + ) + + # Calculate the Aperture stop and draw it ### + aperture_stop_mask = np.sqrt( + (W - AS_centre[0]) ** 2 + (H - AS_centre[1]) ** 2 + ) <= (AS_diam / 2) + pupil_plane[~aperture_stop_mask] = 0 + + # Calculate the M1/M2 obscurations and draw them ### + M1_mask = np.sqrt((W - M1_centre[0]) ** 2 + (H - M1_centre[1]) ** 2) <= ( + M1_diam / 2 + ) + pupil_plane[M1_mask] = 0 + + # Calculate the spiders and draw them + # Spider 1 + sp1_a = np.tan(sp1_angle * (np.pi / 180)) + sp1_b = sp1_y_pos - sp1_a * sp1_x_pos + + sp1_mask_1 = sp1_a * W + sp1_b - sp_width / 2 * np.sqrt(1 + sp1_a**2) < H + sp1_mask_2 = sp1_a * W + sp1_b + sp_width / 2 * np.sqrt(1 + sp1_a**2) > H + sp1_mask = np.logical_and(sp1_mask_1, sp1_mask_2) + + sp1_length_mask = np.sqrt((W - sp1_x_pos) ** 2 + (H - sp1_y_pos) ** 2) <= ( + sp_lenght / 2 + ) + sp1_mask = np.logical_and(sp1_mask, sp1_length_mask) + + # Spider 2 + sp2_a = np.tan(sp2_angle * (np.pi / 180)) + sp2_b = sp2_y_pos - sp2_a * sp2_x_pos + + sp2_mask_1 = sp2_a * W + sp2_b - sp_width / 2 * np.sqrt(1 + sp2_a**2) < H + sp2_mask_2 = sp2_a * W + sp2_b + sp_width / 2 * np.sqrt(1 + sp2_a**2) > H + sp2_mask = np.logical_and(sp2_mask_1, sp2_mask_2) + + sp2_length_mask = np.sqrt((W - sp2_x_pos) ** 2 + (H - sp2_y_pos) ** 2) <= ( + sp_lenght / 2 + ) + sp2_mask = np.logical_and(sp2_mask, sp2_length_mask) + + # Spider 3 + sp3_a = np.tan(sp3_angle * (np.pi / 180)) + sp3_b = sp3_y_pos - sp3_a * sp3_x_pos + + sp3_mask_1 = sp3_a * W + sp3_b - sp_width / 2 * np.sqrt(1 + sp3_a**2) < H + sp3_mask_2 = sp3_a * W + sp3_b + sp_width / 2 * np.sqrt(1 + sp3_a**2) > H + sp3_mask = np.logical_and(sp3_mask_1, sp3_mask_2) + + sp3_length_mask = np.sqrt((W - sp3_x_pos) ** 2 + (H - sp3_y_pos) ** 2) <= ( + sp_lenght / 2 + ) + sp3_mask = np.logical_and(sp3_mask, sp3_length_mask) + + # Draw the three spider arms + pupil_plane[sp1_mask] = 0 + pupil_plane[sp2_mask] = 0 + pupil_plane[sp3_mask] = 0 + + # Low-pass filter the image + if do_filter: + top_hat_filter = np.ones((N_filter, N_filter)) + + pupil_plane = convolve2d( + pupil_plane, + top_hat_filter, + boundary="fill", + mode="same", + fillvalue=0, + ) + pupil_plane /= np.sum(top_hat_filter) + + # Get pupil scale + pupil_scale = AS_diam / N_pix + + return pupil_plane, pupil_scale
    + + + +if __name__ == "__main__": + parser = ArgumentParser() + parser.add_argument( + "-o", + "--output", + dest="output_path", + help="Path where to save the pupil plane. Default to the euclidlike" + " data directory if it exist.", + type=str, + ) + parser.add_argument( + "-N", + "--N_pix", + dest="Npix", + help="N pixels used to save the pupil plane. [Default: 2048]", + type=int, + default=2048, + ) + parser.add_argument( + "-filter", + "--do_filter", + dest="DoFilter", + help="Wether to apply a Top-Hat filter. [Default: True]", + type=bool, + default=True, + ) + parser.add_argument( + "-Nf", + "--N_filter", + dest="Nfilter", + help="N pixels used for the Top-Hat filter. [Default: 3]", + type=int, + default=3, + ) + + args = parser.parse_args() + + # Deal with the output + if args.output_path is None: + if importlib.util.find_spec("euclidlike") is None: + raise ValueError( + "No output path provided and euclidlike not found." + " Please provide an output path." + ) + output_path = str( + files("euclidlike.data").joinpath("euclid_pupil_plane.fits.gz") + ) + else: + output_path = os.path.abspath(args.output_path) + + pupil_plane, pupil_scale = make_EuclidLike_pupil_plane( + args.Npix, + args.DoFilter, + args.Nfilter, + ) + + # Galsim need the pupil scale in m/pixel + pupil_img = galsim.Image(pupil_plane, scale=pupil_scale / 1000) + pupil_img.write(output_path) + print(f"Pupil plane saved at: {output_path}") +
    + +
    + +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_sources/euclidlike.rst.txt b/docs/_build/html/_sources/euclidlike.rst.txt index c09a526..d4f2d47 100644 --- a/docs/_build/html/_sources/euclidlike.rst.txt +++ b/docs/_build/html/_sources/euclidlike.rst.txt @@ -1,53 +1,153 @@ -euclidlike package -================== +The Euclid-like Module +################################ -Submodules ----------- +The ``euclidlike`` module contains telescope information and functionality needed for image simulations. +The demo script end_to_end_demo.py shows how to use many of the atrributes and functions described here. -euclidlike.backgrounds module ------------------------------ -.. automodule:: euclidlike.backgrounds - :members: - :undoc-members: - :show-inheritance: +Module-level Attributes +======================= -euclidlike.bandpass module --------------------------- +There are several of attributes of the ``euclidlike`` module which define some numerical +parameters related to a Euclid-like geometry. Some of these parameters relate to the entire +wide-field imager. Others, especially the return values of the functions to get the +PSF and WCS, are specific to each CCD and therefore are indexed based on the detector number. +All detector-related arrays are 0-indexed, which might differ from the CCD indices for Euclid, +which run 1-1 to n_row-n_col. -.. automodule:: euclidlike.bandpass - :members: - :undoc-members: - :show-inheritance: +gain + The gain for all CCDs is expected to be the roughly the same. -euclidlike.euclidlike\_psf module ---------------------------------- +pixel_scale + The pixel scale in units of arcsec/pixel. -.. automodule:: euclidlike.euclidlike_psf - :members: - :undoc-members: - :show-inheritance: +diameter + The telescope diameter in meters. -euclidlike.euclidlike\_wcs module ---------------------------------- +obscuration + The linear obscuration of the telescope, expressed as a fraction of the diameter. -.. automodule:: euclidlike.euclidlike_wcs - :members: - :undoc-members: - :show-inheritance: +collecting_area + The actual collecting area after accounting for obscuration, struts, etc. in + units of cm^2. -euclidlike.instrument\_params module ------------------------------------- +long_exptime + The typical exposure time for the longer exposures used for VIS images, in units of seconds. + The number that is stored is for a single dither. -.. automodule:: euclidlike.instrument_params - :members: - :undoc-members: - :show-inheritance: +short_exptime_nisp + The typical exposure time for the shorter NISP imaging exposures used for VIS images, in units of seconds. + The number that is stored is for a single dither. -Module contents ---------------- +short_exptime_vis + The typical exposure time for the shorter exposures with VIS taken in parallel with NISP imaging, in units of seconds. + The number that is stored is for a single dither. -.. automodule:: euclidlike - :members: - :undoc-members: - :show-inheritance: +n_dithers + The number of dithers per filter. + +n_ccd + The number of CCDs in the focal plane. + +n_ccd_row + The number of CCDs in the each focal plane row. + +n_ccd_col + The number of CCDs in the each focal plane column. + +n_pix_row + Each CCD has n_pix_row total pixels in each row. +n_pix_col + Each CCD has n_pix_col total pixels in each column. + +pixel_scale_mm + The physical pixel size, in units of mm. + +plate_scale + The plate scale, in units of arcsec / mm + +read_noise + Total readout noise, in units of e-. + +saturation + Pixel saturation, in units of e-. + +det2ccd + Mapping from DETID to CCDID. + +ccd2det + Mapping from CCDID to DETID. + +min_sun_angle + Minimum allowed angle from the telescope solar panels to the sun, in degrees. + +max_sun_angle + Maximum allowed angle from the telescope solar panels to the sun, in degrees. + +vis_bands + List of available VIS bands +nisp_bands + List of available NISP bands + +vis_blue_limit + Bandpass blue limit needed for consistency with the wavelength range covered by ur tabulated + PSF images, in nm. + +vis_red_limit + Bandpass red limit needed for consistency with the wavelength range covered by ur tabulated + PSF images, in nm. + +For example, to get the gain value, use euclidlike.gain. + +#.. automodule:: euclidlike.instrument_params +# :members: +# :undoc-members: + + +Euclid-like Functions +=============== + +This module also contains the following routines: + +`euclidlike.getBandpasses` + A utility to get a dictionary containing galsim.Bandpass objects for each of + the Euclid-like imaging bandpasses, which by default have AB zeropoints given using + the GalSim zeropoint convention (see `getBandpasses` docstring for more details). + +`euclidlike.getSkyLevel` + A utility to find the expected sky level due to zodiacal light at a given + position, in a given band. + +`euclidlike.getZodiBackground` + This helper routine is enables the calculation of the zodiacal light, in photons/m^2/arcsec^2/sec + +`euclidlike.getPSF` + A routine to get a chromatic representation of the PSF in a single CCD. + PSFs are based on precomputed, oversampled (by 3x) PSF images on a grid in wavelength and + focal plane position. + +`euclidlike.getBrightPSF` + Get a fake optical PSF for very bright objects. + +`euclidlike.getWCS` + This routine returns a dict containing a WCS for each of the Euclid CCDs. + +`euclidlike.findCCD` + This is a helper routine to calculate the minimum and maximum pixel values that should be + considered within a CCD. + + + +.. autofunction:: euclidlike.getBandpasses + +.. autofunction:: euclidlike.getSkyLevel + +.. autofunction:: euclidlike.getZodiBackground + +.. autofunction:: euclidlike.getPSF + +.. autofunction:: euclidlike.getBrightPSF + +.. autofunction:: euclidlike.getWCS + +.. autofunction:: euclidlike.findCCD diff --git a/docs/_build/html/_sources/euclidlike_imsim.rst.txt b/docs/_build/html/_sources/euclidlike_imsim.rst.txt index bc6626f..244a9b5 100644 --- a/docs/_build/html/_sources/euclidlike_imsim.rst.txt +++ b/docs/_build/html/_sources/euclidlike_imsim.rst.txt @@ -1,109 +1,64 @@ -euclidlike\_imsim package -========================= +The Euclid-like ImSim Module +################################ -Submodules ----------- +This module contains configuration scripts to produce large-scale Euclid-like simulation runs based on the information in ``euclidlike``. +It is based heavily on `roman_imsim `_. -euclidlike\_imsim.bandpass module ---------------------------------- +Classes and Functions +===================== .. automodule:: euclidlike_imsim.bandpass :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.ccd module ----------------------------- .. automodule:: euclidlike_imsim.ccd :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.detector\_physics module ------------------------------------------- .. automodule:: euclidlike_imsim.detector_physics :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.noise module ------------------------------- .. automodule:: euclidlike_imsim.noise :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.obseq module ------------------------------- .. automodule:: euclidlike_imsim.obseq :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.photonOps module ----------------------------------- .. automodule:: euclidlike_imsim.photonOps :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.psf module ----------------------------- .. automodule:: euclidlike_imsim.psf :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.scafile module --------------------------------- .. automodule:: euclidlike_imsim.scafile :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.skycat module -------------------------------- .. automodule:: euclidlike_imsim.skycat :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.stamp module ------------------------------- .. automodule:: euclidlike_imsim.stamp :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.utils module ------------------------------- .. automodule:: euclidlike_imsim.utils :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.wcs module ----------------------------- .. automodule:: euclidlike_imsim.wcs :members: :undoc-members: - :show-inheritance: -Module contents ---------------- -.. automodule:: euclidlike_imsim - :members: - :undoc-members: - :show-inheritance: +Use +==== +Example files needed for large-scale Euclid-like simulation runs are included in ``GalSim-Euclid-Like/config``. + +.. include:: ../config/README.rst + diff --git a/docs/_build/html/_sources/examples.rst.txt b/docs/_build/html/_sources/examples.rst.txt new file mode 100644 index 0000000..07f898e --- /dev/null +++ b/docs/_build/html/_sources/examples.rst.txt @@ -0,0 +1,29 @@ +Examples +========= + +The ``GalSim-Euclid-Like/examples`` directory contains example files for how use the euclidlike module. + +End-to-end demo +--------------- + +`end_to_end_demo.py.py <../examples/end_to_end_demo.py>`_ + +This first demo is the euclidlike-equivalent of `demo 13 `_ in ``GalSim``. This demo uses the Euclid-like PSF, WCS, and background noise to produce a realistic scene of galaxies and stars as observed from a Euclid-like Telescope. + +** Features introduced in the Python file**: + +- euclidlike.getBandpasses(AB_zeropoint) +- euclidlike.getWCS(world_pos, CCDs_CCD, date) +- euclidlike.getPSF(use_CCD, filter_name, wcs) +- euclidlike.getSkyLevel(bandpass, world_pos) + +The output generated from this file can be visualized by running the script `end_to_end_demo.py.py <../examples/end_to_end_demo.py>`_ + + +Focal Plane Layout +------------------ + +`plot_VIS.py <../examples/plot_VIS.py>`_ + +This Jupyter Notebook shows the display of the focal plane used in the euclidlike package, along with the CCD centers and ID convention. + diff --git a/docs/_build/html/_sources/history.rst.txt b/docs/_build/html/_sources/history.rst.txt new file mode 100644 index 0000000..d35e38d --- /dev/null +++ b/docs/_build/html/_sources/history.rst.txt @@ -0,0 +1,11 @@ +Revision History +################ + +.. include:: ../CHANGELOG.rst + + +Older Versions +============== + +.. toctree:: + older \ No newline at end of file diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt index 55d881e..3f160f3 100644 --- a/docs/_build/html/_sources/index.rst.txt +++ b/docs/_build/html/_sources/index.rst.txt @@ -1,63 +1,24 @@ -GalSim-Euclid-Like -================== - -Helper functions to generate simulations of Euclid-like images using GalSim. - -This repository contains information about the Euclid space telescope and survey that is needed to -produce simulations using `GalSim `_. Some of the -information provided is approximate, aimed towards fast simulations rather than full accuracy in -representation of Euclid images. Places where the information is only approximate are flagged and -described in the docstring, and we particularly highlight that the PSF is only approximate; -for details, see the docstring of the ``getPSF()`` method. This library should enable generation of -Euclid-like images of sufficient fidelity for preliminary exploration of object detection, -photometry, deblending, and joint analysis with ground-based observatories. For -applications requiring high precision such as weak lensing, the higher fidelity simulations -available within the Euclid Consortium should be used. - -This repository includes two distinct packages: - -* ``euclidlike``: has basic observatory, instrumentation, and survey information for Euclid. - This package can be used on its own along with GalSim to produce Euclid-like simulations. - -* ``euclidlike_imsim``: has configuration scripts to produce large-scale Euclid-like simulation runs - based on the information in ``euclidlike``. It is based heavily on `roman_imsim `_. - - -References -================== +.. GalSim-Euclid-Like documentation master file + -For more information about `GalSim `_, please see its README and documentation. +GalSim-Euclid-Like: Euclid-like images using GalSim +============================================== -For more information about Euclid, please see the `Euclid Consortium website `_ and papers linked from there. +.. toctree:: + :maxdepth: 2 -Attribution for software and data used by particular routines in this library is given in the docstring for the relevant routine. + overview + install + euclidlike + euclidlike_imsim + examples + history -Installation -================== - -Please view the `installation instructions `_ for details on how to install GalSim-Euclid-Like. - -Downloading relevant data -================== -The Euclid-like PSF is constructed from precomputed oversampled images on a grid in focal plane position and wavelength. To use the full FOV PSF within GalSim-Euclid-Like, the images must be downloaded by running:: - - $ euclidlike_download_psf - -in the terminal after installation of GalSim-Euclid-Like. To install in an alternative directory to the default, use the ``--dir`` argument. Refer to the ``getPSF`` documentation for further details about the PSF. -Getting started -================== -Please see the examples/ directory for demos illustrating the use of this code. - -Communicating with the developers +Indices and tables ================== -Feel free to `open a GitHub issue `_ to reach the developers with questions, comments, and bug reports. New contributors are also welcome and can indicate their interest in developing this code base through the Issues. - -Attribution -================== - -This software is open source and may be used according to the terms of its `license `_. - -When using this software, please provide the URL to the repository in the resulting paper or note. Once there is a Zenodo DOI or journal article, this README will be updated and we will ask those using the code in their research to cite the relevant journal article. +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/_build/html/_sources/install.rst.txt b/docs/_build/html/_sources/install.rst.txt new file mode 100644 index 0000000..63b62ca --- /dev/null +++ b/docs/_build/html/_sources/install.rst.txt @@ -0,0 +1,4 @@ +Installation +######## + +.. include:: ../INSTALL.rst \ No newline at end of file diff --git a/docs/_build/html/_sources/modules.rst.txt b/docs/_build/html/_sources/modules.rst.txt index 269fdea..dc909a1 100644 --- a/docs/_build/html/_sources/modules.rst.txt +++ b/docs/_build/html/_sources/modules.rst.txt @@ -1,9 +1,6 @@ -GalSim-Euclid-Like -================== - .. toctree:: :maxdepth: 4 euclidlike euclidlike_imsim - scripts + scripts \ No newline at end of file diff --git a/docs/_build/html/_sources/overview.rst.txt b/docs/_build/html/_sources/overview.rst.txt new file mode 100644 index 0000000..803a9ee --- /dev/null +++ b/docs/_build/html/_sources/overview.rst.txt @@ -0,0 +1,4 @@ +Overview +######## + +.. include:: ../README.rst \ No newline at end of file diff --git a/docs/_build/html/_sources/scripts.rst.txt b/docs/_build/html/_sources/scripts.rst.txt index 28a2437..11b271d 100644 --- a/docs/_build/html/_sources/scripts.rst.txt +++ b/docs/_build/html/_sources/scripts.rst.txt @@ -1,6 +1,11 @@ scripts package =============== +.. automodule:: scripts + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- @@ -19,11 +24,3 @@ scripts.make\_euclidlike\_pupil\_plane module :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: scripts - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/euclidlike.html b/docs/_build/html/euclidlike.html index ae374c6..f539977 100644 --- a/docs/_build/html/euclidlike.html +++ b/docs/_build/html/euclidlike.html @@ -5,7 +5,7 @@ - euclidlike package — GalSim-Euclid-Like 0.0.1 documentation + The Euclid-like Module — GalSim-Euclid-Like 0.0.1 documentation @@ -14,6 +14,8 @@ + + @@ -31,17 +33,142 @@
    -
    -

    euclidlike package

    -
    -

    Submodules

    +
    +

    The Euclid-like Module

    +

    The euclidlike module contains telescope information and functionality needed for image simulations. +The demo script end_to_end_demo.py shows how to use many of the atrributes and functions described here.

    +
    +

    Module-level Attributes

    +

    There are several of attributes of the euclidlike module which define some numerical +parameters related to a Euclid-like geometry. Some of these parameters relate to the entire +wide-field imager. Others, especially the return values of the functions to get the +PSF and WCS, are specific to each CCD and therefore are indexed based on the detector number. +All detector-related arrays are 0-indexed, which might differ from the CCD indices for Euclid, +which run 1-1 to n_row-n_col.

    +
    +
    gain

    The gain for all CCDs is expected to be the roughly the same.

    +
    +
    pixel_scale

    The pixel scale in units of arcsec/pixel.

    +
    +
    diameter

    The telescope diameter in meters.

    +
    +
    obscuration

    The linear obscuration of the telescope, expressed as a fraction of the diameter.

    +
    +
    collecting_area
    +
    The actual collecting area after accounting for obscuration, struts, etc. in

    units of cm^2.

    +
    +
    +
    +
    long_exptime

    The typical exposure time for the longer exposures used for VIS images, in units of seconds. +The number that is stored is for a single dither.

    +
    +
    short_exptime_nisp

    The typical exposure time for the shorter NISP imaging exposures used for VIS images, in units of seconds. +The number that is stored is for a single dither.

    +
    +
    short_exptime_vis

    The typical exposure time for the shorter exposures with VIS taken in parallel with NISP imaging, in units of seconds. +The number that is stored is for a single dither.

    +
    +
    n_dithers

    The number of dithers per filter.

    +
    +
    n_ccd

    The number of CCDs in the focal plane.

    +
    +
    n_ccd_row

    The number of CCDs in the each focal plane row.

    +
    +
    n_ccd_col

    The number of CCDs in the each focal plane column.

    +
    +
    n_pix_row

    Each CCD has n_pix_row total pixels in each row.

    +
    +
    n_pix_col

    Each CCD has n_pix_col total pixels in each column.

    +
    +
    pixel_scale_mm

    The physical pixel size, in units of mm.

    +
    +
    plate_scale

    The plate scale, in units of arcsec / mm

    +
    +
    read_noise

    Total readout noise, in units of e-.

    +
    +
    saturation

    Pixel saturation, in units of e-.

    +
    +
    det2ccd

    Mapping from DETID to CCDID.

    +
    +
    ccd2det

    Mapping from CCDID to DETID.

    +
    +
    min_sun_angle

    Minimum allowed angle from the telescope solar panels to the sun, in degrees.

    +
    +
    max_sun_angle

    Maximum allowed angle from the telescope solar panels to the sun, in degrees.

    +
    +
    vis_bands

    List of available VIS bands

    +
    +
    nisp_bands

    List of available NISP bands

    +
    +
    vis_blue_limit

    Bandpass blue limit needed for consistency with the wavelength range covered by ur tabulated +PSF images, in nm.

    +
    +
    vis_red_limit

    Bandpass red limit needed for consistency with the wavelength range covered by ur tabulated +PSF images, in nm.

    +
    +
    +

    For example, to get the gain value, use euclidlike.gain.

    +

    #.. automodule:: euclidlike.instrument_params +# :members: +# :undoc-members:

    -
    -

    euclidlike.backgrounds module

    -

    This file includes any routines needed to define the background level, for which the main contribution (currently the only one implemented) is zodiacal light.

    +
    +

    Euclid-like Functions

    +

    This module also contains the following routines:

    +
    +
    euclidlike.getBandpasses

    A utility to get a dictionary containing galsim.Bandpass objects for each of +the Euclid-like imaging bandpasses, which by default have AB zeropoints given using +the GalSim zeropoint convention (see getBandpasses docstring for more details).

    +
    +
    euclidlike.getSkyLevel

    A utility to find the expected sky level due to zodiacal light at a given +position, in a given band.

    +
    +
    euclidlike.getZodiBackground

    This helper routine is enables the calculation of the zodiacal light, in photons/m^2/arcsec^2/sec

    +
    +
    euclidlike.getPSF

    A routine to get a chromatic representation of the PSF in a single CCD. +PSFs are based on precomputed, oversampled (by 3x) PSF images on a grid in wavelength and +focal plane position.

    +
    +
    euclidlike.getBrightPSF

    Get a fake optical PSF for very bright objects.

    +
    +
    euclidlike.getWCS

    This routine returns a dict containing a WCS for each of the Euclid CCDs.

    +
    +
    euclidlike.findCCD

    This is a helper routine to calculate the minimum and maximum pixel values that should be +considered within a CCD.

    +
    +
    +
    +
    +euclidlike.getBandpasses(AB_zeropoint=True, default_thin_trunc=True, full_bandpass=False, **kwargs)[source]
    +

    Function to get the bandpass information for the Euclid VIS band and the three Euclid NISP passbands.

    +

    This routine reads in files containing a list of wavelengths and +transmission values for the Euclid bands. The files are located in the +euclidlike.data directory. The routine then creates a Bandpass object +using the LookupTable class from the GalSim package, and returns a dict with bandpasses for the +keys.

    +

    The bandpasses are publicly available from IPAC: +http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Euclid&gname2=VIS&asttype=. +https://euclid.esac.esa.int/msp/refdata/nisp/NISP-PHOTO-PASSBANDS-V1

    +

    These are relatively old files that do not include the latest estimates of system response. +They correspond to end-of-life estimates, with some expected degradation of the QE and filter +transmission over time. This can lead to flux estimates that are suppressed by 5-10% from +beginning-of-life flux estimates.

    +

    The VIS bandpass red and blue limits are set not by the transmission curve but by the range of +wavelengths over which we have tabulated PSF images. The wavelength range is read in from the +instrument parameter file.

    +

    Args: +AB_zeropoint (bool) : If True, set the zeropoint of the bandpass to the AB magnitude system. [default: True] +default_thin_trunc (bool) : If True, use the default thinning and truncation parameters. [default: True] +full_bandpass (bool): if True, use the full bandpass without red/blue limits needed for PSF

    +
    +

    calculations. [default: False]

    +
    +

    kwargs : Additional keyword arguments to pass to either Bandpass.thin or Bandpass.truncate.

    +
    +
    -
    -euclidlike.backgrounds.getSkyLevel(bandpass, world_pos=None, exptime=None, epoch=2025, date=None)[source]
    +
    +euclidlike.getSkyLevel(bandpass, world_pos=None, exptime=None, epoch=2025, date=None)[source]

    Get the expected sky level for a Euclid observation due to zodiacal light for this bandpass and position.

    This routine can take an arbitray galsim.Bandpass() and calculate the zodiacal background @@ -82,123 +209,8 @@

    Submodules -
    -euclidlike.backgrounds.getZodiBackground(ecl_lat, ecl_dlon, lambda_min, lambda_max, Tlambda, T)[source]
    -

    This helper routine is used with permission from Chris Hirata’s Exposure Time Calculator and enables the -calculation of the zodiacal light in photons/m^2/arcsec^2/sec. The ETC may be found here:

    -

    http://www.tapir.caltech.edu/~chirata/web/software/space-etc/

    -

    The code was ported from C to python by Michael Troxel (matroxel on GitHub). The units are -exactly as in the original C code, and we convert to any other needed units outside of this -routine, in user-facing code.

    -
    -
    Parameters:
    -
      -
    • ecl_lat – Ecliptic latitude (degrees)

    • -
    • ecl_dlon – Ecliptic longitude (degrees)

    • -
    • lambda_min – Minimum wavelength for the bandpass (microns)

    • -
    • lambda_max – Maximum wavelength for the bandpass (microns)

    • -
    • Tlambda – Numpy array containing a grid of wavelength values for the bandpass (microns)

    • -
    • T – Numpy array containing the throughput (normalized to be between 0-1) for the -bandpass

    • -
    -
    -
    Returns:
    -

    A floating point value for the zodiacal light in photons/m^2/arcsec^2/sec

    -
    -
    -

    - -
    -
    -

    euclidlike.bandpass module

    -

    @file bandpass.py

    -

    This file includes any routines needed to define the Euclid bandpasses. -This module is heavily based on the roman bandpass.py file from the GalSim package. -https://github.com/GalSim-developers/GalSim/blob/releases/2.5/galsim/roman/roman_bandpass.py

    -

    The Euclid VIS bandpass is read in from the Euclid_VIS.vis.dat file which can be downloaded from -http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Euclid&gname2=VIS&asttype=.

    -

    The Euclid NISP bandpasses are read in from files downloaded from -https://euclid.esac.esa.int/msp/refdata/nisp/NISP-PHOTO-PASSBANDS-V1

    -
    -
    -euclidlike.bandpass.getBandpasses(AB_zeropoint=True, default_thin_trunc=True, full_bandpass=False, **kwargs)[source]
    -

    Function to get the bandpass information for the Euclid VIS band and the three Euclid NISP passbands.

    -

    This routine reads in files containing a list of wavelengths and -transmission values for the Euclid bands. The files are located in the -euclidlike.data directory. The routine then creates a Bandpass object -using the LookupTable class from the GalSim package, and returns a dict with bandpasses for the -keys.

    -

    The bandpasses are publicly available from IPAC: -http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?mode=browse&gname=Euclid&gname2=VIS&asttype=. -https://euclid.esac.esa.int/msp/refdata/nisp/NISP-PHOTO-PASSBANDS-V1

    -

    These are relatively old files that do not include the latest estimates of system response. -They correspond to end-of-life estimates, with some expected degradation of the QE and filter -transmission over time. This can lead to flux estimates that are suppressed by 5-10% from -beginning-of-life flux estimates.

    -

    The VIS bandpass red and blue limits are set not by the transmission curve but by the range of -wavelengths over which we have tabulated PSF images. The wavelength range is read in from the -instrument parameter file.

    -

    Args: -AB_zeropoint (bool) : If True, set the zeropoint of the bandpass to the AB magnitude system. [default: True] -default_thin_trunc (bool) : If True, use the default thinning and truncation parameters. [default: True] -full_bandpass (bool): if True, use the full bandpass without red/blue limits needed for PSF

    -
    -

    calculations. [default: False]

    -
    -

    kwargs : Additional keyword arguments to pass to either Bandpass.thin or Bandpass.truncate.

    -
    - -
    -
    -

    euclidlike.euclidlike_psf module

    -
    -
    -euclidlike.euclidlike_psf.getBrightPSF(ccd, bandpass, ccd_pos=None, pupil_bin=4, wcs=None, n_waves=None, wavelength=None, gsparams=None, logger=None)[source]
    -

    Get a fake optical PSF for very bright objects in Euclid-like simulations. -Depending on the inputs, this routine returns a chromatic or achromatic PSF using the -Euclid telescope diameter and Euclid-like aperture.

    -

    Args: -ccd (int): Single value specifying the CCD for which the PSF should be

    -
    -

    loaded.

    -
    -
    -
    bandpass (str): Single string specifying the bandpass to use when

    defining the pupil plane configuration and/or interpolation of -chromatic PSFs.

    -
    -
    ccd_pos: Single galsim.PositionD indicating the position within the CCD

    for which the PSF should be created. If None, the exact center of the -CCD is chosen. [default: None]

    -
    -
    wcs: The WCS to use to project the PSF into world coordinates. [default:

    galsim.PixelScale(euclidlike.pixel_scale)]

    -
    -
    n_waves (int): Number of wavelengths to use for setting up interpolation of the

    chromatic PSF objects, which can lead to much faster image -rendering. If None, then no interpolation is used. Note that -users who want to interpolate can always set up the interpolation -later on even if they do not do so when calling getPSF. -[default: None]

    -
    -
    wavelength (float): An option to get an achromatic PSF for a single

    wavelength, for users who do not care about chromaticity of the PSF. If -None, then the fully chromatic PSF is returned as an -InterpolatedChromaticObject. Alternatively the user should supply -either (a) a wavelength in nanometers, and they will get an -InterpolatedImage object for that wavelength, or (b) a bandpass object, -in which case they will get an InterpolatedImage objects defined at the -effective wavelength of that bandpass. [default: None]

    -
    -
    gsparams: An optional GSParams argument. See the docstring for GSParams

    for details. [default: None]

    -
    -
    -
    -
    Returns:
    -

    A single PSF object (either an InterpolatedChromaticObject or an -InterpolatedImage depending on the inputs).

    -
    -
    -
    - -
    -
    -euclidlike.euclidlike_psf.getPSF(ccd, bandpass, ccd_pos=None, wcs=None, wavelength=None, gsparams=None, logger=None, psf_dir=None)[source]
    +
    +euclidlike.getPSF(ccd, bandpass, ccd_pos=None, wcs=None, wavelength=None, gsparams=None, logger=None, psf_dir=None)[source]

    Get a single PSF for a Euclid-like simulation.

    These PSFs are based on precomputed, oversampled (by 3x) PSF images on a grid in wavelength and focal plane position. These images were provided by Lance Miller and Chris Duncan. They are @@ -276,152 +288,54 @@

    Submodules -

    euclidlike.euclidlike_wcs module

    -

    @file euclidlike_wcs.py

    -

    This file includes any routines needed to define and use the Euclid-like WCS. -Current version is based on the focal plane description detailed in -Scaramella et al. (Fig. 2 and Table 1). -The distortion coefficients were derived from the ERO release.

    -

    Scaramella et al.: https://arxiv.org/abs/2108.01201

    -
    -euclidlike.euclidlike_wcs.allowedPos(world_pos, date, SAA=None)[source]
    -

    This routine can be used to check whether Euclid would be allowed to look at a particular -position (world_pos) on a given date. This is determined by the angle of this position -relative to the Sun.

    -

    In general, Euclid can point at angles relative to the Sun in the range 90+20 & 90-3 degrees. -Obviously, pointing too close to the Sun would result in overly high sky backgrounds. It is -less obvious why Euclid cannot look at a spot directly opposite from the Sun (180 degrees on the -sky). The reason is that the observatory is aligned such that if the observer is looking at -some sky position, the solar panels are oriented at 90 degrees from that position. So it’s -always optimal for the observatory to be pointing at an angle of 90 degrees relative to the -Sun. It is also permitted to look within [-3, + 20] degrees of that optimal position.

    -
    -
    Parameters:
    -
      -
    • world_pos – A galsim.CelestialCoord indicating the position at which the observer -wishes to look.

    • -
    • date – A python datetime object indicating the desired date of observation.

    • -
    • SAA – A galsim.Angle representing the Solar Aspect Angle -of the telescope for the observation. If not provided, -it will be computed internally.

    • -
    +
    +euclidlike.getBrightPSF(ccd, bandpass, ccd_pos=None, pupil_bin=4, wcs=None, n_waves=None, wavelength=None, gsparams=None, logger=None)[source]
    +

    Get a fake optical PSF for very bright objects in Euclid-like simulations. +Depending on the inputs, this routine returns a chromatic or achromatic PSF using the +Euclid telescope diameter and Euclid-like aperture.

    +

    Args: +ccd (int): Single value specifying the CCD for which the PSF should be

    +
    +

    loaded.

    +
    +
    +
    bandpass (str): Single string specifying the bandpass to use when

    defining the pupil plane configuration and/or interpolation of +chromatic PSFs.

    -
    Returns:
    -

    True or False, indicating whether it is permitted to look at this position on this date.

    +
    ccd_pos: Single galsim.PositionD indicating the position within the CCD

    for which the PSF should be created. If None, the exact center of the +CCD is chosen. [default: None]

    -
    -
    - -
    -
    -euclidlike.euclidlike_wcs.bestPA(world_pos, date, SAA=None)[source]
    -

    This routine determines the best position angle for the observatory for a given observation date -and position on the sky.

    -

    The best/optimal position angle is determined by the fact that the solar panels are at 90 -degrees to the position being observed, and it is best to have those facing the Sun as directly -as possible. Note that if a given world_pos is not actually observable on the given -date, then this routine will return None.

    -
    -
    Parameters:
    -
      -
    • world_pos – A galsim.CelestialCoord indicating the position at which the observer -wishes to look.

    • -
    • date – A python datetime object indicating the desired date of observation.

    • -
    • SAA – A galsim.Angle representing the Solar Aspect Angle -of the telescope for the observation. If not provided, -it will be computed internally.

    • -
    +
    wcs: The WCS to use to project the PSF into world coordinates. [default:

    galsim.PixelScale(euclidlike.pixel_scale)]

    -
    Returns:
    -

    the best position angle for the observatory, as a galsim.Angle, or None if the position -is not observable.

    +
    n_waves (int): Number of wavelengths to use for setting up interpolation of the

    chromatic PSF objects, which can lead to much faster image +rendering. If None, then no interpolation is used. Note that +users who want to interpolate can always set up the interpolation +later on even if they do not do so when calling getPSF. +[default: None]

    -
    -
    - -
    -
    -euclidlike.euclidlike_wcs.convertCenter(world_pos, CCD, PA=None, date=None, SAA=None, PA_is_FPA=False, tol=coord.Angle(2.42406840554768e-06, coord.radians))[source]
    -

    This is a simple helper routine that takes an input position world_pos that is meant to -correspond to the position of the center of an CCD, and tells where the center of the focal -plane array should be. The goal is to provide a position that can be used as an input to -getWCS(), which wants the center of the focal plane array.

    -

    The results of the calculation are deterministic if given a fixed position angle (PA). If it’s -not given one, it will try to determine the best one for this location and date, like getWCS() -does.

    -

    Because of distortions varying across the focal plane, this routine has to iteratively correct -its initial result based on empirical tests. The tol kwarg can be used to adjust how -careful it will be, but it always does at least one iteration.

    -
    -
    Parameters:
    -
      -
    • world_pos – A galsim.CelestialCoord indicating the position to observe at the center of the -given CCD. Note that if the given position is not observable on -the given date, then the routine will raise an exception.

    • -
    • CCD – A single number giving the CCD for which the center should be located at -world_pos.

    • -
    • PA – galsim.Angle representing the position angle of the observatory +Y axis, unless -PA_is_FPA=True, in which case it’s the position angle of the FPA. For -users to do not care about this, then leaving this as None will result in the -routine using the supplied date and world_pos to select the optimal -orientation for the observatory. Note that if a user supplies a PA value, -the routine does not check whether this orientation is actually allowed. -[default: None]

    • -
    • SAA – A galsim.Angle representing the Solar Aspect Angle -of the telescope for the observation. If not provided, -it will be computed internally.

    • -
    • date – The date of the observation, as a python datetime object. If None, then the -vernal equinox in 2025 will be used. [default: None]

    • -
    • PA_is_FPA – If True, then the position angle that was provided was the PA of the focal -plane array, not the observatory. [default: False]

    • -
    • tol – Tolerance for errors due to distortions, as a galsim.Angle. -[default: 0.5*galsim.arcsec]

    • -
    +
    wavelength (float): An option to get an achromatic PSF for a single

    wavelength, for users who do not care about chromaticity of the PSF. If +None, then the fully chromatic PSF is returned as an +InterpolatedChromaticObject. Alternatively the user should supply +either (a) a wavelength in nanometers, and they will get an +InterpolatedImage object for that wavelength, or (b) a bandpass object, +in which case they will get an InterpolatedImage objects defined at the +effective wavelength of that bandpass. [default: None]

    -
    Returns:
    -

    A CelestialCoord object indicating the center of the focal plane array.

    +
    gsparams: An optional GSParams argument. See the docstring for GSParams

    for details. [default: None]

    -
    - -
    -
    -euclidlike.euclidlike_wcs.findCCD(wcs_dict, world_pos, include_border=False)[source]
    -

    This is a subroutine to take a dict of WCS (one per CCD) from euclidlike.getWCS() and query -which CCD a particular real-world coordinate would be located on. The position (world_pos) -should be specified as a galsim.CelestialCoord. If the position is not located on any of the -CCDs, the result will be None. Note that if wcs_dict does not include all CCDs in it, then -it’s possible the position might lie on one of the CCDs that was not included.

    -

    Depending on what the user wants to do with the results, they may wish to use the -include_border keyword. This keyword determines whether or not to include an additional -border corresponding to half of the gaps between CCDs. For example, if a user is drawing a -single image they may wish to only know whether a given position falls onto a CCD, and if so, -which one (ignoring everything in the gaps). In contrast, a user who plans to make a sequence -of dithered images might find it most useful to know whether the position is either on a CCD or -close enough that in a small dither sequence it might appear on the CCD at some point. Use of -include_border switches between these scenarios.

    -
    Parameters:
    -
      -
    • wcs_dict – The dict of WCS’s output from euclidlike.getWCS().

    • -
    • world_pos – A galsim.CelestialCoord indicating the sky position of interest.

    • -
    • include_border – If True, then include the half-border around CCD to cover the gap -between each sensor. [default: False]

    • -
    -
    -
    Returns:
    -

    an integer value of the CCD on which the position falls, or None if the position is not -on any CCD.

    +
    Returns:
    +

    A single PSF object (either an InterpolatedChromaticObject or an +InterpolatedImage depending on the inputs).

    -
    -euclidlike.euclidlike_wcs.getWCS(world_pos, PA=None, date=None, CCDs=None, PA_is_FPA=False, SAA=None)[source]
    +
    +euclidlike.getWCS(world_pos, PA=None, date=None, CCDs=None, PA_is_FPA=False, SAA=None)[source]

    This routine returns a dict containing a WCS for each of the Euclid CCDs. The Euclid CCDs are labeled 0-35, so these numbers are used as the keys in the dict. Alternatively the user can request a subset of the CCDs using @@ -475,14 +389,38 @@

    Submodules -

    euclidlike.instrument_params module

    -

    Basic information GalSim needs to produce Euclid-like simulations.

    -

    When editing this file, you should also modify the imports in __init__.py

    -

    -
    -

    Module contents

    +
    +
    +euclidlike.findCCD(wcs_dict, world_pos, include_border=False)[source]
    +

    This is a subroutine to take a dict of WCS (one per CCD) from euclidlike.getWCS() and query +which CCD a particular real-world coordinate would be located on. The position (world_pos) +should be specified as a galsim.CelestialCoord. If the position is not located on any of the +CCDs, the result will be None. Note that if wcs_dict does not include all CCDs in it, then +it’s possible the position might lie on one of the CCDs that was not included.

    +

    Depending on what the user wants to do with the results, they may wish to use the +include_border keyword. This keyword determines whether or not to include an additional +border corresponding to half of the gaps between CCDs. For example, if a user is drawing a +single image they may wish to only know whether a given position falls onto a CCD, and if so, +which one (ignoring everything in the gaps). In contrast, a user who plans to make a sequence +of dithered images might find it most useful to know whether the position is either on a CCD or +close enough that in a small dither sequence it might appear on the CCD at some point. Use of +include_border switches between these scenarios.

    +
    +
    Parameters:
    +
      +
    • wcs_dict – The dict of WCS’s output from euclidlike.getWCS().

    • +
    • world_pos – A galsim.CelestialCoord indicating the sky position of interest.

    • +
    • include_border – If True, then include the half-border around CCD to cover the gap +between each sensor. [default: False]

    • +
    +
    +
    Returns:
    +

    an integer value of the CCD on which the position falls, or None if the position is not +on any CCD.

    +
    +
    +
    +
    @@ -512,11 +450,25 @@

    GalSim-Euclid-Like

    Navigation

    + diff --git a/docs/_build/html/euclidlike_imsim.html b/docs/_build/html/euclidlike_imsim.html index b9034a0..e6d31e5 100644 --- a/docs/_build/html/euclidlike_imsim.html +++ b/docs/_build/html/euclidlike_imsim.html @@ -5,7 +5,7 @@ - euclidlike_imsim package — GalSim-Euclid-Like 0.0.1 documentation + The Euclid-like ImSim Module — GalSim-Euclid-Like 0.0.1 documentation @@ -14,6 +14,8 @@ + + @@ -31,49 +33,736 @@
    -
    -

    euclidlike_imsim package

    -
    -

    Submodules

    -
    -
    -

    euclidlike_imsim.bandpass module

    -
    -
    -

    euclidlike_imsim.ccd module

    -
    -
    -

    euclidlike_imsim.detector_physics module

    -
    -
    -

    euclidlike_imsim.noise module

    -
    -
    -

    euclidlike_imsim.obseq module

    -
    -
    -

    euclidlike_imsim.photonOps module

    -
    -
    -

    euclidlike_imsim.psf module

    -
    -
    -

    euclidlike_imsim.scafile module

    -
    -
    -

    euclidlike_imsim.skycat module

    -
    -
    -

    euclidlike_imsim.stamp module

    +
    +

    The Euclid-like ImSim Module

    +

    This module contains configuration scripts to produce large-scale Euclid-like simulation runs based on the information in euclidlike. +It is based heavily on roman_imsim.

    +
    +

    Classes and Functions

    +
    +
    +class euclidlike_imsim.bandpass.EuclidlikeBandpassBuilder[source]
    +

    A class for loading a Bandpass from a file

    +

    FileBandpass expected the following parameter:

    +
    +

    name (str) The name of the Euclid filter to get. (required)

    +
    +
    +
    +buildBandpass(config, base, logger)[source]
    +

    Build the Bandpass based on the specifications in the config dict.

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the bandpass type.

    • +
    • base – The base configuration dict.

    • +
    • logger – If provided, a logger for logging debug statements.

    • +
    +
    +
    Returns:
    +

    the constructed Bandpass object.

    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder[source]
    +
    +
    +addNoise(image, config, base, image_num, obj_num, current_var, logger)[source]
    +

    Add the final noise to a Scattered image

    +
    +
    Parameters:
    +
      +
    • image – The image onto which to add the noise.

    • +
    • config – The configuration dict for the image field.

    • +
    • base – The base configuration dict.

    • +
    • image_num – The current image number.

    • +
    • obj_num – The first object number in the image.

    • +
    • current_var – The current noise variance in each postage stamps.

    • +
    • logger – If given, a logger object to log progress.

    • +
    +
    +
    +
    + +
    +
    +buildImage(config, base, image_num, obj_num, logger)[source]
    +

    Build an Image containing multiple objects placed at arbitrary locations.

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the image field.

    • +
    • base – The base configuration dict.

    • +
    • image_num – The current image number.

    • +
    • obj_num – The first object number in the image.

    • +
    • logger – If given, a logger object to log progress.

    • +
    +
    +
    Returns:
    +

    the final image and the current noise variance in the image as a tuple

    +
    +
    +
    + +
    +
    +setup(config, base, image_num, obj_num, ignore, logger)[source]
    +

    Do the initialization and setup for building the image.

    +

    This figures out the size that the image will be, but doesn’t actually build it yet.

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the image field.

    • +
    • base – The base configuration dict.

    • +
    • image_num – The current image number.

    • +
    • obj_num – The first object number in the image.

    • +
    • ignore – A list of parameters that are allowed to be in config that we can +ignore here. i.e. it won’t be an error if these parameters are present.

    • +
    • logger – If given, a logger object to log progress.

    • +
    +
    +
    Returns:
    +

    xsize, ysize

    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.noise.NoiseImageBuilder[source]
    +
    +
    +initialize(data, scratch, config, base, logger)[source]
    +

    Do any initial setup for this builder at the start of a new output file.

    +

    The base class implementation saves two work space items into self.data and self.scratch +that can be used to safely communicate across multiple processes.

    +
    +
    Parameters:
    +
      +
    • data – An empty list of length nimages to use as work space.

    • +
    • scratch – An empty dict that can be used as work space.

    • +
    • config – The configuration field for this output object.

    • +
    • base – The base configuration dict.

    • +
    • logger – If given, a logger object to log progress. [default: None]

    • +
    +
    +
    +
    + +
    +
    +processImage(index, obj_nums, config, base, logger)[source]
    +

    Perform any necessary processing at the end of each image construction.

    +

    This function will be called after each full image is built.

    +

    Compute the noise for the current image and add it to the image. +It will also create an independent noise image. +The code optionally subtract the background if requested.

    +
    +
    Parameters:
    +
      +
    • index – The index in self.data to use for this image. This isn’t the image_num +(which can be accessed at base[‘image_num’] if needed), but rather +an index that starts at 0 for the first image being worked on and +goes up to nimages-1.

    • +
    • obj_nums – The object numbers that were used for this image.

    • +
    • config – The configuration field for this output object.

    • +
    • base – The base configuration dict.

    • +
    • logger – If given, a logger object to log progress. [default: None]

    • +
    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.noise.SkyImageBuilder[source]
    +
    +
    +processImage(index, obj_nums, config, base, logger)[source]
    +

    Perform any necessary processing at the end of each image construction.

    +

    This function will be called after each full image is built.

    +

    Compute the sky background and return it in an image.

    +
    +
    Parameters:
    +
      +
    • index – The index in self.data to use for this image. This isn’t the image_num +(which can be accessed at base[‘image_num’] if needed), but rather +an index that starts at 0 for the first image being worked on and +goes up to nimages-1.

    • +
    • obj_nums – The object numbers that were used for this image.

    • +
    • config – The configuration field for this output object.

    • +
    • base – The base configuration dict.

    • +
    • logger – If given, a logger object to log progress. [default: None]

    • +
    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.noise.WeightImageBuilder[source]
    +
    +
    +processImage(index, obj_nums, config, base, logger)[source]
    +

    Perform any necessary processing at the end of each image construction.

    +

    This function will be called after each full image is built.

    +

    Compute the weight map from the noise image and return it in an image.

    +
    +
    Parameters:
    +
      +
    • index – The index in self.data to use for this image. This isn’t the image_num +(which can be accessed at base[‘image_num’] if needed), but rather +an index that starts at 0 for the first image being worked on and +goes up to nimages-1.

    • +
    • obj_nums – The object numbers that were used for this image.

    • +
    • config – The configuration field for this output object.

    • +
    • base – The base configuration dict.

    • +
    • logger – If given, a logger object to log progress. [default: None]

    • +
    +
    +
    +
    + +
    + +
    +
    +euclidlike_imsim.noise.get_noise(cfg_noise, cfg_image, base, logger)[source]
    +
    + +
    +
    +euclidlike_imsim.noise.parse_noise_config(params)[source]
    +
    + +
    +
    +euclidlike_imsim.obseq.ObSeqData(config, base, value_type)[source]
    +

    Returns the obseq data for a pointing.

    +
    + +
    +
    +class euclidlike_imsim.obseq.ObSeqDataLoader(file_name, visit, obs_kind, CCD, logger=None)[source]
    +

    Read the exposure information from the observation sequence.

    +
    +
    +get(field, default=None, obs_kind=None)[source]
    +
    + +
    +
    +read_obseq()[source]
    +

    Read visit info from the obseq file.

    +
    + +
    + +
    +
    +class euclidlike_imsim.photonOps.ChargeDiff(rng=None, **kwargs)[source]
    +

    A photon operator that applies the effect of charge diffusion via a probablistic model limit.

    +
    +
    +applyTo(photon_array, local_wcs=None, rng=None)[source]
    +

    Apply the charge diffusion effect to the photons

    +
    +
    Parameters:
    +
      +
    • photon_array – A PhotonArray to apply the operator to.

    • +
    • local_wcs – A LocalWCS instance defining the local WCS for the current photon +bundle in case the operator needs this information. [default: None]

    • +
    • rng – A random number generator to use if needed. [default: None]

    • +
    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.photonOps.ChargeDiffBuilder[source]
    +

    Build ChargeDiff photonOp

    +
    +
    +buildPhotonOp(config, base, logger)[source]
    +

    Build the PhotonOp based on the specifications in the config dict.

    +

    Note: Sub-classes must override this function with a real implementation.

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the PhotonOp

    • +
    • base – The base configuration dict.

    • +
    • logger – If provided, a logger for logging debug statements.

    • +
    +
    +
    Returns:
    +

    the constructed PhotonOp object.

    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.psf.EuclidlikePSF(CCD=None, WCS=None, n_waves=None, bpass=None, extra_aberrations=None, logger=None)[source]
    +

    Class building needed Euclidlike PSFs.

    +
    +
    +getPSF(pupil_bin, pos)[source]
    +

    Return a PSF to be convolved with sources. +PSF is sampled at 4 quadrants for each CCD. Returned PSF +corresponds to that of the quadrant of the CCD position.

    +

    @param [in] what pupil binning to request.

    +
    + +
    + +
    +
    +class euclidlike_imsim.psf.PSFLoader[source]
    +

    PSF loader.

    +
    +
    +getKwargs(config, base, logger)[source]
    +

    Parse the config dict and return the kwargs needed to build the input object.

    +

    The default implementation looks for special class attributes called:

    +
    +
    _req_params

    A dict of required parameters and their types.

    +
    +
    _opt_params

    A dict of optional parameters and their types.

    +
    +
    _single_params

    A list of dicts of parameters such that one and only one of +parameter in each dict is required.

    +
    +
    _takes_rng

    A bool value saying whether an rng object is required.

    +
    +
    +

    See galsim.Catalog for an example of a class that sets these attributes.

    +

    In addition to the kwargs, we also return a bool value, safe, that indicates whether +the constructed object will be safe to keep around for multiple files (True) of if +it will need to be rebuilt for each output file (False).

    +
    +
    Parameters:
    +
      +
    • config – The config dict for this input item

    • +
    • base – The base config dict

    • +
    • logger – If given, a logger object to log progress. [default: None]

    • +
    +
    +
    Returns:
    +

    kwargs, safe

    +
    +
    +
    + +
    + +

    Interface to obtain objects from skyCatalogs.

    +
    +
    +euclidlike_imsim.skycat.SkyCatObj(config, base, ignore, gsparams, logger)[source]
    +

    Build an object according to info in the sky catalog.

    +
    + +
    +
    +euclidlike_imsim.skycat.SkyCatValue(config, base, value_type)[source]
    +

    Return a value from the object part of the skyCatalog

    +
    + +
    +
    +euclidlike_imsim.skycat.SkyCatWorldPos(config, base, value_type)[source]
    +

    Return a value from the object part of the skyCatalog

    +
    + +
    +
    +class euclidlike_imsim.skycat.SkyCatalogInterface(file_name, exptime, wcs=None, mjd=None, bandpass=None, xsize=None, ysize=None, obj_types=None, edge_pix=100, max_flux=None, logger=None)[source]
    +

    Interface to skyCatalogs package.

    +
    +
    +getApproxNObjects()[source]
    +

    Return the approximate number of GSObjects to render, as set in +the class initializer.

    +
    + +
    +
    +getFlux(index, filter=None, mjd=None, exptime=None)[source]
    +

    Return the flux associated to an object.

    +
    +
    Parameters:
    +
      +
    • index (int) – Index of the object in the self.objects catalog.

    • +
    • filter (str, optional) – Name of the filter for which the flux is computed. If None, use the +filter provided during initialization. [Default: None]

    • +
    • mjd (float, optional) – Date of the observation in MJD format. If None, use the +mjd provided during initialization. [Default: None]

    • +
    • exptime (int or float, optional) – Exposure time of the observation. If None, use the +exptime provided during initialization. [Default: None]

    • +
    +
    +
    Returns:
    +

    Computer flux at the given date for the requested exposure time and +filter.

    +
    +
    Return type:
    +

    flux

    +
    +
    +
    + +
    +
    +getNObjects()[source]
    +

    Return the number of GSObjects to render

    +
    + +
    +
    +getObj(index, gsparams=None, rng=None, exptime=30)[source]
    +

    Return the galsim object for the skyCatalog object +corresponding to the specified index. If the skyCatalog +object is a galaxy, the returned galsim object will be +a galsim.Sum.

    +
    +
    Parameters:
    +

    index (int) – Index of the object in the self.objects catalog.

    +
    +
    Return type:
    +

    galsim.GSObject

    +
    +
    +
    + +
    +
    +getValue(index, field)[source]
    +

    Return a skyCatalog value for the an object.

    +
    +
    Parameters:
    +
      +
    • index (int) – Index of the object in the self.objects catalog.

    • +
    • field (str) – Name of the field for which you want the value.

    • +
    +
    +
    Returns:
    +

    The value associated to the field or None if the field do not exist.

    +
    +
    Return type:
    +

    int or float or str or None

    +
    +
    +
    + +
    +
    +getWorldPos(index)[source]
    +

    Return the sky coordinates of the skyCatalog object +corresponding to the specified index.

    +
    +
    Parameters:
    +

    index (int) – Index of the (object_index, subcomponent) combination.

    +
    +
    Return type:
    +

    galsim.CelestialCoord

    +
    +
    +
    + +
    +
    +get_ccd_center()[source]
    +

    Return the CCD center.

    +
    + +
    +
    +property objects
    +
    + +
    + +
    +
    +class euclidlike_imsim.skycat.SkyCatalogLoader(init_func, has_nobj=False, file_scope=False, takes_logger=False, use_proxy=True, worker_init=None, worker_initargs=None)[source]
    +

    Class to load SkyCatalogInterface object.

    +
    +
    +getKwargs(config, base, logger)[source]
    +

    Parse the config dict and return the kwargs needed to build the input object.

    +

    The default implementation looks for special class attributes called:

    +
    +
    _req_params

    A dict of required parameters and their types.

    +
    +
    _opt_params

    A dict of optional parameters and their types.

    +
    +
    _single_params

    A list of dicts of parameters such that one and only one of +parameter in each dict is required.

    +
    +
    _takes_rng

    A bool value saying whether an rng object is required.

    +
    +
    +

    See galsim.Catalog for an example of a class that sets these attributes.

    +

    In addition to the kwargs, we also return a bool value, safe, that indicates whether +the constructed object will be safe to keep around for multiple files (True) of if +it will need to be rebuilt for each output file (False).

    +
    +
    Parameters:
    +
      +
    • config – The config dict for this input item

    • +
    • base – The base config dict

    • +
    • logger – If given, a logger object to log progress. [default: None]

    • +
    +
    +
    Returns:
    +

    kwargs, safe

    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.stamp.Euclidlike_stamp[source]
    +

    This performs the tasks necessary for building the stamp for a single object.

    +

    It uses the regular Basic functions for most things. +It specializes the quickSkip, buildProfile, and draw methods.

    +
    +
    +buildPSF(config, base, gsparams, logger)[source]
    +

    Build the PSF object.

    +

    For the Basic stamp type, this builds a PSF from the base[‘psf’] dict, if present, +else returns None.

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the stamp field.

    • +
    • base – The base configuration dict.

    • +
    • gsparams – A dict of kwargs to use for a GSParams. More may be added to this +list by the galaxy object.

    • +
    • logger – A logger object to log progress.

    • +
    +
    +
    Returns:
    +

    the PSF

    +
    +
    +
    + +
    +
    +draw(prof, image, method, offset, config, base, logger)[source]
    +

    Draw the profile on the postage stamp image.

    +
    +
    Parameters:
    +
      +
    • prof – The profile to draw.

    • +
    • image – The image onto which to draw the profile (which may be None).

    • +
    • method – The method to use in drawImage.

    • +
    • offset – The offset to apply when drawing.

    • +
    • config – The configuration dict for the stamp field.

    • +
    • base – The base configuration dict.

    • +
    • logger – A logger object to log progress.

    • +
    +
    +
    Returns:
    +

    the resulting image

    +
    +
    +
    + +
    +
    +classmethod fix_seds(prof, bandpass)[source]
    +
    + +
    +
    +getDrawMethod(config, base, logger)[source]
    +

    Determine the draw method to use.

    +

    @param config The configuration dict for the stamp field. +@param base The base configuration dict. +@param logger A logger object to log progress.

    +

    @returns method

    +
    + +
    +
    +setup(config, base, xsize, ysize, ignore, logger)[source]
    +

    Do the initialization and setup for building a postage stamp.

    +

    In the base class, we check for and parse the appropriate size and position values in +config (aka base[‘stamp’] or base[‘image’].

    +

    Values given in base[‘stamp’] take precedence if these are given in both places (which +would be confusing, so probably shouldn’t do that, but there might be a use case where it +would make sense).

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the stamp field.

    • +
    • base – The base configuration dict.

    • +
    • xsize – The xsize of the image to build (if known).

    • +
    • ysize – The ysize of the image to build (if known).

    • +
    • ignore – A list of parameters that are allowed to be in config that we can +ignore here. i.e. it won’t be an error if these parameters are present.

    • +
    • logger – A logger object to log progress.

    • +
    +
    +
    Returns:
    +

    xsize, ysize, image_pos, world_pos

    +
    +
    +
    + +
    + +
    +
    +class euclidlike_imsim.utils.roman_utils(config_file, visit=None, sca=None, image_name=None, setup_skycat=False)[source]
    +

    Class to contain a variety of helper routines to work with the simulation data.

    +
    +
    +check_input(visit, sca, image_name)[source]
    +
    + +
    +
    +getBandpass()[source]
    +

    Return Roman bandpass for image

    +
    + +
    +
    +getLocalWCS(x, y)[source]
    +

    Return Roman WCS for image

    +
    + +
    +
    +getPSF(x=None, y=None, pupil_bin=8)[source]
    +

    Return Roman PSF for some image position. +:param x: x-position in SCA +:param y: y-position in SCA +:param pupil_bin: pupil image binning factor

    +
    +
    Returns:
    +

    the chromatic GalSim PSF model object (does not include additional effects like charge diffusion!)

    +
    +
    +
    + +
    +
    +getPSF_Image(stamp_size, x=None, y=None, pupil_bin=8, sed=None, oversampling_factor=1, include_photonOps=False, n_phot=1000000.0)[source]
    +

    Return a Roman PSF image for some image position +:param stamp_size: size of output PSF model stamp in native roman pixel_scale (oversampling_factor=1) +:param x: x-position in SCA +:param y: y-position in SCA +:param pupil_bin: pupil image binning factor +:param sed: SED to be used to draw the PSF - default is a flat SED. +:param oversampling_factor: factor by which to oversample native roman pixel_scale +:param include_photonOps: include additional contributions from other photon operators in effective psf image

    +
    +
    Returns:
    +

    the PSF GalSim image object (use image.array to get a numpy array representation)

    +
    +
    +
    + +
    +
    +getWCS()[source]
    +

    Return Roman WCS for image

    +
    + +
    + +
    +
    +class euclidlike_imsim.wcs.EuclidlikeWCS[source]
    +
    +
    +buildWCS(config, base, logger)[source]
    +

    Build the WCS based on the specifications in the config dict.

    +

    Note: Sub-classes must override this function with a real implementation.

    +
    +
    Parameters:
    +
      +
    • config – The configuration dict for the wcs type.

    • +
    • base – The base configuration dict.

    • +
    • logger – If provided, a logger for logging debug statements.

    • +
    +
    +
    Returns:
    +

    the constructed WCS object.

    +
    +
    +
    + +
    +
    -
    -

    euclidlike_imsim.utils module

    +
    +

    Use

    +

    Example files needed for large-scale Euclid-like simulation runs are included in GalSim-Euclid-Like/config.

    -
    -

    euclidlike_imsim.wcs module

    +
    +

    Config imsim

    +

    was.yaml: euclidlike_imsim example config file. +You will want to update the following entries:

    +
      +
    • input.obseq_data.file_name: path to the observing sequence. Link to euclidlike/data/euclid_obseq.fits

    • +
    • input.sky_catalog.file_name: path to the skyCatalog to use

    • +
    • output.dir: path to the output directory for the simulated images

    • +
    • output.truth.dir: path to the output directory for the true catalogs

    • +
    +

    To run the code:

    +
    galsim was.yaml
    +
    +
    +

    You might want to specify some config entries on the command line, like:

    +
    galsim was.yaml input.obseq_data.visit=33690 image.CCD=1
    +
    +
    -
    -

    Module contents

    +
    +

    Config SLURM

    +

    slurm_runner.sh contains the SLURM configuration to run “large scale” simulations. +You will want to update the following lines:

    +
      +
    • #!/bin/zsh: depending on the shell you are using, you might want to change it to: #!/bin/bash

    • +
    • #SBATCH --output=/path/to/slurm-%A-%a.out: SLURM stdout file

    • +
    • #SBATCH --error=/path/to/slurm-%A-%a.err: SLURM stderr file

    • +
    • source activate [env_name]: conda environment to use

    • +
    • file_list='/path/to/run_list.txt': file containing the pointings to simulate (see note below)

    • +
    +

    The run_list.txt is a 2-column file with the pointing and the CCD_ID to simulate. It should look like:

    +
    33688 0
    +33688 1
    +33688 2
    +[...]
    +33688 35
    +33689 0
    +33689 1
    +[...]
    +
    +
    @@ -103,11 +792,27 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/examples.html b/docs/_build/html/examples.html new file mode 100644 index 0000000..4fd9454 --- /dev/null +++ b/docs/_build/html/examples.html @@ -0,0 +1,135 @@ + + + + + + + + Examples — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + +
    +

    Examples

    +

    The GalSim-Euclid-Like/examples directory contains example files for how use the euclidlike module.

    +
    +

    End-to-end demo

    +

    end_to_end_demo.py.py

    +

    This first demo is the euclidlike-equivalent of demo 13 in GalSim. This demo uses the Euclid-like PSF, WCS, and background noise to produce a realistic scene of galaxies and stars as observed from a Euclid-like Telescope.

    +

    ** Features introduced in the Python file**:

    +
      +
    • euclidlike.getBandpasses(AB_zeropoint)

    • +
    • euclidlike.getWCS(world_pos, CCDs_CCD, date)

    • +
    • euclidlike.getPSF(use_CCD, filter_name, wcs)

    • +
    • euclidlike.getSkyLevel(bandpass, world_pos)

    • +
    +

    The output generated from this file can be visualized by running the script end_to_end_demo.py.py

    +
    +
    +

    Focal Plane Layout

    +

    plot_VIS.py

    +

    This Jupyter Notebook shows the display of the focal plane used in the euclidlike package, along with the CCD centers and ID convention.

    +
    +
    + + +
    + +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html index 9c9d874..5f05424 100644 --- a/docs/_build/html/genindex.html +++ b/docs/_build/html/genindex.html @@ -37,16 +37,30 @@

    Index

    A | B | C + | D | E | F | G + | I | M + | N + | O + | P + | Q + | R + | S + | U + | W

    A

    +
    @@ -54,7 +68,17 @@

    A

    B

    +
    @@ -62,7 +86,33 @@

    B

    C

    + +
    + +

    D

    + + +
    @@ -71,56 +121,98 @@

    E

    F

    +
    @@ -128,19 +220,73 @@

    F

    G

    +
    + +

    I

    + +
    @@ -148,23 +294,174 @@

    G

    M

    +
    + +

    N

    + + +
    + +

    O

    + + + +
    + +

    P

    + + + +
    + +

    Q

    + + +
    + +

    R

    + + + +
    + +

    S

    + + + +
    + +

    U

    + + +
    + +

    W

    + +
    @@ -195,6 +492,14 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/history.html b/docs/_build/html/history.html new file mode 100644 index 0000000..9f69abb --- /dev/null +++ b/docs/_build/html/history.html @@ -0,0 +1,123 @@ + + + + + + + + Revision History — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + +
    +

    Revision History

    +
    +

    Changes from v0.0.0 to v0.0.1

    +

    Made repo public.

    +
    +
    +

    Older Versions

    +
    +
    +
    +
    + + +
    + +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html index 5cb8389..73125c7 100644 --- a/docs/_build/html/index.html +++ b/docs/_build/html/index.html @@ -5,7 +5,7 @@ - GalSim-Euclid-Like — GalSim-Euclid-Like 0.0.1 documentation + GalSim-Euclid-Like: Euclid-like images using GalSim — GalSim-Euclid-Like 0.0.1 documentation @@ -14,6 +14,7 @@ + @@ -31,57 +32,56 @@
    -
    -

    GalSim-Euclid-Like

    -

    Helper functions to generate simulations of Euclid-like images using GalSim.

    -

    This repository contains information about the Euclid space telescope and survey that is needed to -produce simulations using GalSim. Some of the -information provided is approximate, aimed towards fast simulations rather than full accuracy in -representation of Euclid images. Places where the information is only approximate are flagged and -described in the docstring, and we particularly highlight that the PSF is only approximate; -for details, see the docstring of the getPSF() method. This library should enable generation of -Euclid-like images of sufficient fidelity for preliminary exploration of object detection, -photometry, deblending, and joint analysis with ground-based observatories. For -applications requiring high precision such as weak lensing, the higher fidelity simulations -available within the Euclid Consortium should be used.

    -

    This repository includes two distinct packages:

    -

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/install.html b/docs/_build/html/install.html new file mode 100644 index 0000000..11726e8 --- /dev/null +++ b/docs/_build/html/install.html @@ -0,0 +1,150 @@ + + + + + + + + Installation — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + +
    +

    Installation

    +
    +

    Installation Instructions

    +

    The GalSim-Euclid-Like repository contains two python libraries and currently supports Python versions 3.10 and above.

    +

    System requirements: Given the heavy dependance on GalSim, GalSim-Euclid-Like currently only supports Linux and Mac OSX. For +further details on system requirements for GalSim see GalSim Installation.

    +
    +

    Dependencies

    +

    GalSim-Euclid-Like requires python>=3.10 and the following dependencies:

    +
    numpy>=1.17,
    +galsim>=2.6,
    +astropy>=2.0
    +
    +
    +
    +
    +

    Installation

    +

    The source code for GalSim-Euclid-Like has not been published to pypi. To install from source code:

    +
    git clone git@github.com:GalSim-developers/GalSim-Euclid-Like.git
    +
    +
    +

    and install by running:

    +
    conda create -n euclidlike python=3.10
    +cd GalSim-Euclid-Like
    +conda activate euclidlike
    +pip install .
    +
    +
    +

    To make sure the installation is successful, do the following:

    +
    $ python
    +>>> import euclidlike
    +>>> euclidlike.getBandpasses()
    +
    +
    +
    +
    +
    + + +
    + +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/modules.html b/docs/_build/html/modules.html index 71109a5..b8967d7 100644 --- a/docs/_build/html/modules.html +++ b/docs/_build/html/modules.html @@ -5,7 +5,7 @@ - GalSim-Euclid-Like — GalSim-Euclid-Like 0.0.1 documentation + <no title> — GalSim-Euclid-Like 0.0.1 documentation @@ -31,65 +31,144 @@
    -
    -

    GalSim-Euclid-Like

    -
    +
    -
    @@ -117,6 +196,14 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv index 5e4256bceadf392c54838055191bcba9a87b61d0..24e0d91f5f04a04fef6f3cb0d3d82eed5a892f0d 100644 GIT binary patch delta 1149 zcmV-@1cLkB1MUfsfPb}_OK;;g5PP2%DXlZP-rbtGl zVynNtq)5rs!(NM2PDx14H%|`74wNau8NqvqH<)J2pID0&jQnW%XsUq>s#MUp>J)kja9t%YW4*nFQwo=keMGM$6_b zD+xrOqQR+J-fS-}V&c#3P80I`5|a!Htso^@)9o3)Cpcc~pZBgGAa^XArYB9azz`^c zW27q5#~f`T%=?SX7-iWvh6M!pe1TqvwO;ucz5rQrUo>s~_D@*Ni0cT>kg7AZ7*i}U zBKSWD@^ysF3xAe^5J4$2Y}IsTi$ISxqm{3q8}V$04skQusv2_A*63(Yz7oVyA;6%L zl+g{|`V-k&z+2#@sTuL}dIfI}NTNVvPM{}-{1ZCL(mC)=;yADXlqIJidT{xUNk*S} z=yTh0;^ht%TX?{mjc4q}P%+}1RNq;!n+`MV%3dIvhkxqD9`H6LG9=623N|6kVw}I&QW{KqU`d|N6)FJ(YNC`8sURj|k zlZlydh_LM=l~8O@3Z9uf57cS>ovSDC_)SFK5qMV2JLd|eqjiiP8csdHR&#eDD zbOxIh=rA*KgO7=TOw5c`nSM~lel^5-*+CzMONmM7L|HT9g5`)NEzhHP2AnwELAp;c z<)sXAumg3z(wi0f#8O1;S820B11`-uUJ~>fb$^r^;PoL5Ek8wYE`>G4qx=RO)3&bn zO{4|pvg?jr8+g&IXY4?UdJU5PhlnYH_MX5I3yEp}Q+|i^14IEidxro(NjXaQUV!G0 zAmJvClL2}rX&a4~w5kx~Elg29`2WIn(mBG^Q&5#K!PGBX=F6pKc$qBzRzguF6^Mi~ zFMoik)I_3UjR^5Wlr-^<-n2rmW9@VfUUEzlP7sAjxBddh?3o7kG@|2@nK9-ST_^Pw z<_uFQemN;woR%XYv%8F?(c(6`R;JbxecwT3Y+LC4=xgoUWyPky`lugBjvMiquW)|J zl%txj2#5(L3?+=}&vs)>%}%v#R#ew(8Gi~GCBLe>B(Ws$+n5?mGdNzaq<`F~_yZ9Y zvxSYKuCu#NNU@$RL{tj>4w=K_wy4>akSW&m1&lq9W*zCu9#drQ(1Z*Q1+Iy$YDL96 zhQsxGMkI`)XS?AHC@!k^pV@O4tA7{95zYj2`EoRM-ND$kUV(3c)}>P)C1?#qA9ik5 zo2;o{Z)_R6OuJ-G{SEI}=#KTLS-m-N?QsX`Q<%1>y2N^Eq_|XJjQGW?MYCaKOu(#% zwwPQ6c4<&lO+C10o3&nHI68k|%uA()R@$|xnNl4+?t2imQ>=R4RLE`wpd#IM6`3`2 Per5Jw^x6LbIiyTvfciFj delta 358 zcmV-s0h#{p3EcybfPbZw%WlFj5JmTVg{5|zsNJ$F=|h#M6e){J-5_HRiG^RX9ccc( z4o)B`v?zFI&&)k{W~>Bi!Wrdk3rII}p=iwkJs>!S)5-~c7ZS-mN@j!98k22lR4u8E zQ>P`kV%scX2fQV1YDpYZ5n7 + + + + + + + Overview — GalSim-Euclid-Like 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + +
    + +
    +

    Overview

    +
    +

    GalSim-Euclid-Like

    +

    Helper functions to generate simulations of Euclid-like images using GalSim.

    +

    This repository contains information about the Euclid space telescope and survey that is needed to +produce simulations using GalSim. Some of the +information provided is approximate, aimed towards fast simulations rather than full accuracy in +representation of Euclid images. Places where the information is only approximate are flagged and +described in the docstring, and we particularly highlight that the PSF is only approximate; +for details, see the docstring of the getPSF() method. This library should enable generation of +Euclid-like images of sufficient fidelity for preliminary exploration of object detection, +photometry, deblending, and joint analysis with ground-based observatories. For +applications requiring high precision such as weak lensing, the higher fidelity simulations +available within the Euclid Consortium should be used.

    +

    This repository includes two distinct packages:

    +
      +
    • euclidlike: has basic observatory, instrumentation, and survey information for Euclid. +This package can be used on its own along with GalSim to produce Euclid-like simulations.

    • +
    • euclidlike_imsim: has configuration scripts to produce large-scale Euclid-like simulation runs +based on the information in euclidlike. It is based heavily on roman_imsim.

    • +
    +
    +
    +

    References

    +

    For more information about GalSim, please see its README and documentation.

    +

    For more information about Euclid, please see the Euclid Consortium website and papers linked from there.

    +

    Attribution for software and data used by particular routines in this library is given in the docstring for the relevant routine.

    +
    +
    +

    Installation

    +

    Please view the installation instructions for details on how to install GalSim-Euclid-Like.

    +
    +
    +

    Downloading relevant data

    +

    The Euclid-like PSF is constructed from precomputed oversampled images on a grid in focal plane position and wavelength. To use the full FOV PSF within GalSim-Euclid-Like, the images must be downloaded by running:

    +
    $ euclidlike_download_psf
    +
    +
    +

    in the terminal after installation of GalSim-Euclid-Like. To install in an alternative directory to the default, use the --dir argument. Refer to the getPSF documentation for further details about the PSF.

    +
    +
    +

    Getting started

    +

    Please see the examples/ directory for demos illustrating the use of this code.

    +
    +
    +

    Communicating with the developers

    +

    Feel free to open a GitHub issue to reach the developers with questions, comments, and bug reports. New contributors are also welcome and can indicate their interest in developing this code base through the Issues.

    +
    +
    +

    Attribution

    +

    This software is open source and may be used according to the terms of its license.

    +

    When using this software, please provide the URL to the repository in the resulting paper or note. Once there is a Zenodo DOI or journal article, this README will be updated and we will ask those using the code in their research to cite the relevant journal article.

    +
    +
    + + +
    + +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/py-modindex.html b/docs/_build/html/py-modindex.html index f0b916e..9330300 100644 --- a/docs/_build/html/py-modindex.html +++ b/docs/_build/html/py-modindex.html @@ -37,7 +37,8 @@

    Python Module Index

    - e + e | + s
    @@ -48,32 +49,76 @@

    Python Module Index

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    - euclidlike + euclidlike_imsim
        - euclidlike.backgrounds + euclidlike_imsim.bandpass
        - euclidlike.bandpass + euclidlike_imsim.ccd
        - euclidlike.euclidlike_psf + euclidlike_imsim.noise
        - euclidlike.euclidlike_wcs + euclidlike_imsim.obseq
        - euclidlike.instrument_params + euclidlike_imsim.photonOps +
        + euclidlike_imsim.psf +
        + euclidlike_imsim.skycat +
        + euclidlike_imsim.stamp +
        + euclidlike_imsim.utils +
        + euclidlike_imsim.wcs +
     
    + s
    + scripts +
        + scripts.download_psf +
        + scripts.make_euclidlike_pupil_plane
    @@ -103,6 +148,14 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/scripts.html b/docs/_build/html/scripts.html index bd95c86..87be1ee 100644 --- a/docs/_build/html/scripts.html +++ b/docs/_build/html/scripts.html @@ -31,19 +31,115 @@
    -
    -

    scripts package

    +
    +

    scripts package

    Submodules

    -
    -

    scripts.download_psf module

    -
    -
    -

    scripts.make_euclidlike_pupil_plane module

    +
    +

    scripts.download_psf module

    +

    A program to download the Euclid-like PSF sampled across the focal plane for discrete wavelengths. +The code below was adapted from: https://github.com/GalSim-developers/GalSim/blob/releases/2.5/galsim/download_cosmos.py

    +
    +
    +scripts.download_psf.check_existing(target, unpack_dir, meta, args, logger)[source]
    +
    + +
    +
    +scripts.download_psf.check_remove(do_unpack, target, args)[source]
    +
    + +
    +
    +scripts.download_psf.check_unpack(do_download, unpack_dir, target, args)[source]
    +
    + +
    +
    +scripts.download_psf.download(do_download, url, target, meta, args, logger)[source]
    +
    + +
    +
    +scripts.download_psf.download_psf(args, logger)[source]
    +

    The main script given the ArgParsed args and a logger

    +
    + +
    +
    +scripts.download_psf.get_input()[source]
    +
    + +
    +
    +scripts.download_psf.get_meta(url, args, logger)[source]
    +
    + +
    +
    +scripts.download_psf.get_names(args, logger)[source]
    +
    + +
    +
    +scripts.download_psf.main(command_args)[source]
    +

    The whole process given command-line parameters in their native (non-ArgParse) form.

    +
    + +
    + +
    + +
    +
    +scripts.download_psf.parse_args(command_args)[source]
    +

    Handle the command line arguments using either argparse (if available) or optparse.

    +
    + +
    +
    +scripts.download_psf.query_yes_no(question, default='yes')[source]
    +

    Ask a yes/no question via input() and return their answer.

    +

    “question” is a string that is presented to the user. +“default” is the presumed answer if the user just hits <Enter>.

    +
    +

    It must be “yes” (the default), “no” or None (meaning +an answer is required of the user).

    +
    +

    The “answer” return value is one of “yes” or “no”.

    +
    + +
    +
    +scripts.download_psf.remove_tarball(do_remove, target, logger)[source]
    +
    + +
    +
    +scripts.download_psf.run_main()[source]
    +

    Kick off the process grabbing the command-line parameters from sys.argv

    +
    + +
    +
    +scripts.download_psf.unpack(do_unpack, target, target_dir, unpack_dir, meta, args, logger)[source]
    +
    +
    -
    -

    Module contents

    +
    +

    scripts.make_euclidlike_pupil_plane module

    +

    This code has been taken from https://github.com/CosmoStat/wf-psf Liaudat et al.

    +

    This is an implementation of the function generate_pupil_obscurations https://github.com/CosmoStat/wf-psf/blob/87e0c8e9770199cd276f5f0551054cb4902d53bb/src/wf_psf/sims/SimPSFToolkit.py#L233

    +

    NOTE from Tobias Liaudat: +“Simple procedure considering only the 2D plane. +No 3D projections wrt the angle of the FoV is done.”

    +
    +
    +scripts.make_euclidlike_pupil_plane.make_EuclidLike_pupil_plane(N_pix=2048, do_filter=True, N_filter=3)[source]
    +
    +
    @@ -73,6 +169,14 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/search.html b/docs/_build/html/search.html index 8a6504c..e5c04c5 100644 --- a/docs/_build/html/search.html +++ b/docs/_build/html/search.html @@ -81,6 +81,14 @@

    GalSim-Euclid-Like

    Navigation

    +

    Related Topics

    diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js index bd0afe7..ea6848e 100644 --- a/docs/_build/html/searchindex.js +++ b/docs/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"alltitles": {"Attribution": [[2, "attribution"]], "Communicating with the developers": [[2, "communicating-with-the-developers"]], "Downloading relevant data": [[2, "downloading-relevant-data"]], "GalSim-Euclid-Like": [[2, null], [3, null]], "Getting started": [[2, "getting-started"]], "Installation": [[2, "installation"]], "Module contents": [[0, "module-euclidlike"], [1, "module-contents"], [4, "module-contents"]], "References": [[2, "references"]], "Submodules": [[0, "submodules"], [1, "submodules"], [4, "submodules"]], "euclidlike package": [[0, null]], "euclidlike.backgrounds module": [[0, "module-euclidlike.backgrounds"]], "euclidlike.bandpass module": [[0, "module-euclidlike.bandpass"]], "euclidlike.euclidlike_psf module": [[0, "module-euclidlike.euclidlike_psf"]], "euclidlike.euclidlike_wcs module": [[0, "module-euclidlike.euclidlike_wcs"]], "euclidlike.instrument_params module": [[0, "module-euclidlike.instrument_params"]], "euclidlike_imsim package": [[1, null]], "euclidlike_imsim.bandpass module": [[1, "euclidlike-imsim-bandpass-module"]], "euclidlike_imsim.ccd module": [[1, "euclidlike-imsim-ccd-module"]], "euclidlike_imsim.detector_physics module": [[1, "euclidlike-imsim-detector-physics-module"]], "euclidlike_imsim.noise module": [[1, "euclidlike-imsim-noise-module"]], "euclidlike_imsim.obseq module": [[1, "euclidlike-imsim-obseq-module"]], "euclidlike_imsim.photonOps module": [[1, "euclidlike-imsim-photonops-module"]], "euclidlike_imsim.psf module": [[1, "euclidlike-imsim-psf-module"]], "euclidlike_imsim.scafile module": [[1, "euclidlike-imsim-scafile-module"]], "euclidlike_imsim.skycat module": [[1, "euclidlike-imsim-skycat-module"]], "euclidlike_imsim.stamp module": [[1, "euclidlike-imsim-stamp-module"]], "euclidlike_imsim.utils module": [[1, "euclidlike-imsim-utils-module"]], "euclidlike_imsim.wcs module": [[1, "euclidlike-imsim-wcs-module"]], "scripts package": [[4, null]], "scripts.download_psf module": [[4, "scripts-download-psf-module"]], "scripts.make_euclidlike_pupil_plane module": [[4, "scripts-make-euclidlike-pupil-plane-module"]]}, "docnames": ["euclidlike", "euclidlike_imsim", "index", "modules", "scripts"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1}, "filenames": ["euclidlike.rst", "euclidlike_imsim.rst", "index.rst", "modules.rst", "scripts.rst"], "indexentries": {"allowedpos() (in module euclidlike.euclidlike_wcs)": [[0, "euclidlike.euclidlike_wcs.allowedPos", false]], "bestpa() (in module euclidlike.euclidlike_wcs)": [[0, "euclidlike.euclidlike_wcs.bestPA", false]], "convertcenter() (in module euclidlike.euclidlike_wcs)": [[0, "euclidlike.euclidlike_wcs.convertCenter", false]], "euclidlike": [[0, "module-euclidlike", false]], "euclidlike.backgrounds": [[0, "module-euclidlike.backgrounds", false]], "euclidlike.bandpass": [[0, "module-euclidlike.bandpass", false]], "euclidlike.euclidlike_psf": [[0, "module-euclidlike.euclidlike_psf", false]], "euclidlike.euclidlike_wcs": [[0, "module-euclidlike.euclidlike_wcs", false]], "euclidlike.instrument_params": [[0, "module-euclidlike.instrument_params", false]], "findccd() (in module euclidlike.euclidlike_wcs)": [[0, "euclidlike.euclidlike_wcs.findCCD", false]], "getbandpasses() (in module euclidlike.bandpass)": [[0, "euclidlike.bandpass.getBandpasses", false]], "getbrightpsf() (in module euclidlike.euclidlike_psf)": [[0, "euclidlike.euclidlike_psf.getBrightPSF", false]], "getpsf() (in module euclidlike.euclidlike_psf)": [[0, "euclidlike.euclidlike_psf.getPSF", false]], "getskylevel() (in module euclidlike.backgrounds)": [[0, "euclidlike.backgrounds.getSkyLevel", false]], "getwcs() (in module euclidlike.euclidlike_wcs)": [[0, "euclidlike.euclidlike_wcs.getWCS", false]], "getzodibackground() (in module euclidlike.backgrounds)": [[0, "euclidlike.backgrounds.getZodiBackground", false]], "module": [[0, "module-euclidlike", false], [0, "module-euclidlike.backgrounds", false], [0, "module-euclidlike.bandpass", false], [0, "module-euclidlike.euclidlike_psf", false], [0, "module-euclidlike.euclidlike_wcs", false], [0, "module-euclidlike.instrument_params", false]]}, "objects": {"": [[0, 0, 0, "-", "euclidlike"]], "euclidlike": [[0, 0, 0, "-", "backgrounds"], [0, 0, 0, "-", "bandpass"], [0, 0, 0, "-", "euclidlike_psf"], [0, 0, 0, "-", "euclidlike_wcs"], [0, 0, 0, "-", "instrument_params"]], "euclidlike.backgrounds": [[0, 1, 1, "", "getSkyLevel"], [0, 1, 1, "", "getZodiBackground"]], "euclidlike.bandpass": [[0, 1, 1, "", "getBandpasses"]], "euclidlike.euclidlike_psf": [[0, 1, 1, "", "getBrightPSF"], [0, 1, 1, "", "getPSF"]], "euclidlike.euclidlike_wcs": [[0, 1, 1, "", "allowedPos"], [0, 1, 1, "", "bestPA"], [0, 1, 1, "", "convertCenter"], [0, 1, 1, "", "findCCD"], [0, 1, 1, "", "getWCS"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"]}, "objtypes": {"0": "py:module", "1": "py:function"}, "terms": {"": 0, "0": 0, "01201": 0, "06": 0, "1": 0, "10": 0, "17": 0, "180": 0, "2": 0, "20": 0, "2023": 0, "2025": 0, "2108": 0, "3": 0, "30": 0, "35": 0, "3x": 0, "4": 0, "42406840554768e": 0, "5": 0, "90": 0, "A": 0, "As": 0, "But": 0, "For": [0, 2], "If": 0, "In": 0, "It": [0, 2], "The": [0, 2], "These": 0, "To": 2, "__init__": 0, "ab": 0, "ab_zeropoint": 0, "aberr": 0, "about": [0, 2], "access": 0, "accord": 2, "account": 0, "accross": 0, "accuraci": [0, 2], "achromat": 0, "across": 0, "actual": 0, "addit": 0, "adjust": 0, "adopt": 0, "after": 2, "aim": 2, "al": 0, "alias": 0, "align": 0, "all": 0, "allow": 0, "allowedpo": [0, 3], "along": 2, "also": [0, 2], "altern": [0, 2], "alwai": 0, "an": [0, 2], "analysi": 2, "angl": 0, "ani": 0, "apertur": 0, "appear": 0, "applic": [0, 2], "appropi": 0, "approxim": [0, 2], "ar": [0, 2], "arbitrai": 0, "arcsec": 0, "area": 0, "arg": 0, "argument": [0, 2], "around": 0, "arrai": 0, "articl": 2, "arxiv": 0, "ask": 2, "aspect": 0, "assum": 0, "asttyp": 0, "avail": [0, 2], "awai": 0, "axi": 0, "b": 0, "background": 3, "baffl": 0, "band": 0, "bandpass": 3, "base": [0, 2], "basic": [0, 2], "becaus": 0, "befor": 0, "begin": 0, "being": 0, "best": 0, "bestpa": [0, 3], "between": 0, "blob": 0, "blue": 0, "bool": 0, "border": 0, "boxi": 0, "bright": 0, "brighter": 0, "brows": 0, "bug": 2, "c": 0, "cab": 0, "calcul": 0, "call": 0, "caltech": 0, "can": [0, 2], "cannot": 0, "care": 0, "carri": 0, "case": 0, "ccd": [0, 3], "ccd_po": 0, "celestialcoord": 0, "center": 0, "certain": 0, "chang": 0, "charg": 0, "check": 0, "chirata": 0, "choos": 0, "chosen": 0, "chri": 0, "chromat": 0, "cite": 2, "class": 0, "close": 0, "code": [0, 2], "coeffici": 0, "collecting_area": 0, "column": 0, "com": 0, "combin": 0, "command": 0, "comment": 2, "compromis": 0, "comput": 0, "configur": [0, 2], "consortium": 2, "construct": [0, 2], "contain": [0, 2], "content": 3, "contrast": 0, "contribut": 0, "contributor": 2, "convers": 0, "convert": 0, "convertcent": [0, 3], "coord": 0, "coordin": 0, "correct": 0, "correspond": 0, "cover": 0, "creat": 0, "csic": 0, "current": 0, "curv": 0, "dat": 0, "data": 0, "date": 0, "datetim": 0, "deblend": 2, "decent": 0, "decontamin": 0, "default": [0, 2], "default_thin_trunc": 0, "defin": 0, "degrad": 0, "degre": 0, "demo": 2, "depend": 0, "deriv": 0, "describ": 2, "descript": 0, "desir": 0, "detail": [0, 2], "detect": 2, "detector": 0, "detector_phys": 3, "determin": 0, "determinist": 0, "develop": 0, "diamet": 0, "dichroic": 0, "dict": 0, "diffus": 0, "dir": 2, "directli": 0, "directori": [0, 2], "discret": 0, "distinct": 2, "distort": 0, "dither": 0, "divid": 0, "do": 0, "docstr": [0, 2], "document": 2, "doe": 0, "doi": 2, "done": 0, "download": 0, "download_psf": 3, "draw": 0, "due": 0, "duncan": 0, "e": 0, "each": 0, "earli": 0, "earth": 0, "ecl_dlon": 0, "ecl_lat": 0, "eclipt": 0, "edit": 0, "edu": 0, "effect": 0, "either": 0, "empir": 0, "enabl": [0, 2], "end": 0, "enough": 0, "epoch": 0, "equinox": 0, "ero": 0, "error": 0, "esa": 0, "esac": 0, "estim": 0, "et": 0, "etc": 0, "euclid": 0, "euclid_lik": 0, "euclid_vi": 0, "euclidlik": [2, 3], "euclidlike_download_psf": [0, 2], "euclidlike_imsim": [2, 3], "euclidlike_psf": 3, "euclidlike_wc": 3, "even": 0, "everyth": 0, "exact": 0, "exactli": 0, "exampl": [0, 2], "except": 0, "expect": 0, "explor": 2, "exposur": 0, "exptim": 0, "face": 0, "fact": 0, "fair": 0, "fake": 0, "fall": 0, "fals": 0, "fast": 2, "faster": 0, "fatter": 0, "feel": 2, "fidel": 2, "fig": 0, "figur": 0, "file": 0, "filter": 0, "find": 0, "findccd": [0, 3], "fix": 0, "flag": 2, "float": 0, "flux": 0, "focal": [0, 2], "focu": 0, "folding_threshold": 0, "follow": 0, "format": 0, "found": 0, "fov": 2, "fpa": 0, "fps3": 0, "free": 2, "from": [0, 2], "full": [0, 2], "full_bandpass": 0, "fulli": 0, "function": [0, 2], "further": 2, "futur": 0, "galsim": 0, "gap": 0, "gener": [0, 2], "get": 0, "getbandpass": [0, 3], "getbrightpsf": [0, 3], "getpsf": [0, 2, 3], "getskylevel": [0, 3], "getwc": [0, 3], "getzodibackground": [0, 3], "github": [0, 2], "give": 0, "given": [0, 2], "gname": 0, "gname2": 0, "goal": 0, "good": 0, "grid": [0, 2], "ground": 2, "gsparam": 0, "guid": 0, "ha": [0, 2], "half": 0, "handl": 0, "have": 0, "heavili": [0, 2], "helper": [0, 2], "here": 0, "high": [0, 2], "higher": 2, "highlight": 2, "hirata": 0, "how": [0, 2], "howev": 0, "http": 0, "i": [0, 2], "ic": 0, "id": 0, "ignor": 0, "illustr": 2, "imag": [0, 2], "implement": 0, "import": 0, "includ": [0, 2], "include_bord": 0, "incorpor": 0, "index": 0, "indic": [0, 2], "ineffici": 0, "infer": 0, "inform": [0, 2], "initi": 0, "input": 0, "instruct": 2, "instrument": [0, 2], "instrument_param": 3, "int": 0, "inta": 0, "integ": 0, "interest": [0, 2], "intern": 0, "interpol": 0, "interpolatedchromaticobject": 0, "interpolatedimag": 0, "ipac": 0, "isr": 0, "issu": 2, "iter": 0, "its": [0, 2], "joint": 2, "journal": 2, "kei": 0, "keyword": 0, "know": 0, "knowledg": 0, "kwarg": 0, "label": 0, "lack": 0, "lambda_max": 0, "lambda_min": 0, "lanc": 0, "larg": 2, "later": 0, "latest": 0, "latitud": 0, "lead": 0, "least": 0, "leav": 0, "lens": [0, 2], "less": 0, "level": 0, "librari": 2, "licens": 2, "lie": 0, "life": 0, "light": 0, "like": 0, "limit": 0, "linear": 0, "link": 2, "list": 0, "load": 0, "locat": 0, "logger": 0, "longer": 0, "longitud": 0, "look": 0, "lookup": 0, "lookupt": 0, "lower": 0, "m": 0, "magnitud": 0, "mai": [0, 2], "main": 0, "make": 0, "make_euclidlike_pupil_plan": 3, "makeskyimag": 0, "matroxel": 0, "maximum": 0, "mean": 0, "meant": 0, "measur": 0, "method": 2, "michael": 0, "micron": 0, "might": 0, "miller": 0, "minimum": 0, "mode": 0, "model": 0, "modifi": 0, "modul": 3, "more": 2, "most": 0, "msp": 0, "much": 0, "multipli": 0, "must": [0, 2], "n_wave": 0, "nanomet": 0, "need": [0, 2], "new": 2, "nisp": 0, "nois": 3, "non": 0, "none": 0, "nonlinear": 0, "normal": 0, "note": [0, 2], "np": 0, "number": 0, "numpi": 0, "object": [0, 2], "obliqu": 0, "obscur": 0, "obseq": 3, "observ": 0, "observatori": [0, 2], "obtain": 0, "obviou": 0, "obvious": 0, "old": 0, "omit": 0, "onc": 2, "one": 0, "onli": [0, 2], "onto": 0, "open": 2, "opposit": 0, "optic": 0, "optim": 0, "option": 0, "orbit": 0, "order": 0, "org": 0, "orient": 0, "origin": 0, "other": 0, "otherwis": 0, "out": 0, "output": 0, "outsid": 0, "outskirt": 0, "over": 0, "overli": 0, "oversampl": [0, 2], "own": 2, "pa": 0, "pa_is_fpa": 0, "packag": [2, 3], "panel": 0, "paper": 2, "paramet": 0, "part": 0, "particular": [0, 2], "particularli": 2, "pass": 0, "passband": 0, "pattern": 0, "per": 0, "perfectli": 0, "permiss": 0, "permit": 0, "photo": 0, "photometri": 2, "photon": 0, "photonop": 3, "php": 0, "pi": 0, "pix": 0, "pixel": 0, "pixel_scal": 0, "pixelscal": 0, "place": 2, "plan": 0, "plane": [0, 2], "pleas": 2, "point": 0, "polar": 0, "port": 0, "posit": [0, 2], "positiond": 0, "possibl": 0, "possibli": 0, "post": 0, "precis": [0, 2], "precomput": [0, 2], "preliminari": 2, "process": 0, "produc": [0, 2], "project": 0, "properli": 0, "provid": [0, 2], "psf": [0, 2, 3], "psf_dir": 0, "publicli": 0, "pupil": 0, "pupil_bin": 0, "py": 0, "python": 0, "qe": 0, "quadrant": 0, "queri": 0, "question": 2, "radian": 0, "rais": 0, "rang": 0, "rather": 2, "reach": 2, "read": 0, "readm": 2, "readout": 0, "real": 0, "realist": 0, "reason": 0, "red": 0, "refdata": 0, "refer": 0, "reflect": 0, "rel": 0, "releas": 0, "remov": 0, "render": 0, "renorm": 0, "report": 2, "repositori": 2, "repres": 0, "represent": 2, "request": 0, "requir": [0, 2], "research": 2, "respect": 0, "respons": 0, "result": [0, 2], "return": 0, "roman": 0, "roman_bandpass": 0, "roman_imsim": 2, "routin": [0, 2], "row": 0, "run": 2, "saa": 0, "sampl": 0, "scafil": 3, "scale": 2, "scaramella": 0, "scenario": 0, "script": [2, 3], "sec": 0, "second": 0, "sed": 0, "see": [0, 2], "select": 0, "sensibli": 0, "sensor": 0, "septemb": 0, "sequenc": 0, "set": 0, "sever": 0, "shape": 0, "shear": 0, "should": [0, 2], "show": 0, "signatur": 0, "simpl": 0, "simpli": 0, "simplifi": 0, "simul": [0, 2], "singl": 0, "size": 0, "sky": 0, "skycat": 3, "slower": 0, "small": 0, "so": 0, "softwar": [0, 2], "solar": 0, "some": [0, 2], "sourc": [0, 2], "space": [0, 2], "spatial": 0, "specifi": 0, "spider": 0, "spot": 0, "stamp": 3, "star": 0, "store": 0, "str": 0, "string": 0, "submodul": 3, "subroutin": 0, "subset": 0, "suffici": 2, "sum": 0, "sun": 0, "suppli": 0, "suppress": 0, "surfac": 0, "survei": 2, "svo": 0, "svo2": 0, "switch": 0, "system": 0, "t": 0, "tabl": 0, "tabul": 0, "take": 0, "tapir": 0, "telescop": [0, 2], "tell": 0, "term": 2, "termin": [0, 2], "test": 0, "than": [0, 2], "thei": 0, "theori": 0, "therefor": 0, "thi": [0, 2], "thin": 0, "those": [0, 2], "thought": 0, "three": 0, "through": 2, "throughput": 0, "time": 0, "tlambda": 0, "tol": 0, "toler": 0, "too": 0, "toward": [0, 2], "transfer": 0, "transmiss": 0, "troxel": 0, "true": 0, "truncat": 0, "try": 0, "two": 2, "uncertain": 0, "unit": 0, "unless": 0, "up": 0, "updat": 2, "url": 2, "us": [0, 2], "user": 0, "util": 3, "v1": 0, "valu": 0, "vari": 0, "variat": 0, "veri": 0, "vernal": 0, "version": 0, "vi": 0, "view": 2, "vignet": 0, "wa": 0, "wai": 0, "want": 0, "wavefront": 0, "wavelength": [0, 2], "wc": [0, 3], "wcs_dict": 0, "we": [0, 2], "weak": [0, 2], "web": 0, "websit": 2, "welcom": 2, "were": 0, "what": 0, "when": [0, 2], "where": [0, 2], "whether": 0, "which": 0, "who": 0, "why": 0, "wish": 0, "within": [0, 2], "without": 0, "world": 0, "world_po": 0, "would": 0, "www": 0, "y": 0, "you": 0, "zenodo": 2, "zeropoint": 0, "zodiac": 0}, "titles": ["euclidlike package", "euclidlike_imsim package", "GalSim-Euclid-Like", "GalSim-Euclid-Like", "scripts package"], "titleterms": {"attribut": 2, "background": 0, "bandpass": [0, 1], "ccd": 1, "commun": 2, "content": [0, 1, 4], "data": 2, "detector_phys": 1, "develop": 2, "download": 2, "download_psf": 4, "euclid": [2, 3], "euclidlik": 0, "euclidlike_imsim": 1, "euclidlike_psf": 0, "euclidlike_wc": 0, "galsim": [2, 3], "get": 2, "instal": 2, "instrument_param": 0, "like": [2, 3], "make_euclidlike_pupil_plan": 4, "modul": [0, 1, 4], "nois": 1, "obseq": 1, "packag": [0, 1, 4], "photonop": 1, "psf": 1, "refer": 2, "relev": 2, "scafil": 1, "script": 4, "skycat": 1, "stamp": 1, "start": 2, "submodul": [0, 1, 4], "util": 1, "wc": 1}}) \ No newline at end of file +Search.setIndex({"alltitles": {"Attribution": [[15, "attribution"]], "Changes from v0.0.0 to v0.0.1": [[11, "changes-from-v0-0-0-to-v0-0-1"]], "Classes and Functions": [[1, "module-euclidlike_imsim.bandpass"], [9, "module-euclidlike_imsim.bandpass"]], "Communicating with the developers": [[15, "communicating-with-the-developers"]], "Config SLURM": [[9, "config-slurm"]], "Config imsim": [[9, "config-imsim"]], "Dependencies": [[13, "dependencies"]], "Downloading relevant data": [[15, "downloading-relevant-data"]], "End-to-end demo": [[2, "end-to-end-demo"], [10, "end-to-end-demo"]], "Euclid-like Functions": [[0, "euclid-like-functions"], [8, "euclid-like-functions"]], "Examples": [[2, null], [10, null]], "Focal Plane Layout": [[2, "focal-plane-layout"], [10, "focal-plane-layout"]], "GalSim-Euclid-Like": [[15, "galsim-euclid-like"]], "GalSim-Euclid-Like: Euclid-like images using GalSim": [[4, null], [12, null]], "Getting started": [[15, "getting-started"]], "Indices and tables": [[4, "indices-and-tables"], [12, "indices-and-tables"]], "Installation": [[5, null], [13, null], [13, "id1"], [15, "installation"]], "Installation Instructions": [[13, "installation-instructions"]], "Module-level Attributes": [[0, "module-level-attributes"], [8, "module-level-attributes"]], "Older Versions": [[11, "older-versions"]], "Overview": [[7, null], [15, null]], "References": [[15, "references"]], "Revision History": [[11, null]], "Submodules": [[16, "submodules"]], "The Euclid-like ImSim Module": [[1, null], [9, null]], "The Euclid-like Module": [[0, null], [8, null]], "Use": [[1, "use"], [9, "use"]], "scripts package": [[16, null]], "scripts.download_psf module": [[16, "module-scripts.download_psf"]], "scripts.make_euclidlike_pupil_plane module": [[16, "module-scripts.make_euclidlike_pupil_plane"]]}, "docnames": [".ipynb_checkpoints/euclidlike-checkpoint", ".ipynb_checkpoints/euclidlike_imsim-checkpoint", ".ipynb_checkpoints/examples-checkpoint", ".ipynb_checkpoints/history-checkpoint", ".ipynb_checkpoints/index-checkpoint", ".ipynb_checkpoints/install-checkpoint", ".ipynb_checkpoints/modules-checkpoint", ".ipynb_checkpoints/overview-checkpoint", "euclidlike", "euclidlike_imsim", "examples", "history", "index", "install", "modules", "overview", "scripts"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1}, "filenames": [".ipynb_checkpoints/euclidlike-checkpoint.rst", ".ipynb_checkpoints/euclidlike_imsim-checkpoint.rst", ".ipynb_checkpoints/examples-checkpoint.rst", ".ipynb_checkpoints/history-checkpoint.rst", ".ipynb_checkpoints/index-checkpoint.rst", ".ipynb_checkpoints/install-checkpoint.rst", ".ipynb_checkpoints/modules-checkpoint.rst", ".ipynb_checkpoints/overview-checkpoint.rst", "euclidlike.rst", "euclidlike_imsim.rst", "examples.rst", "history.rst", "index.rst", "install.rst", "modules.rst", "overview.rst", "scripts.rst"], "indexentries": {"addnoise() (euclidlike_imsim.ccd.euclidlikeccdimagebuilder method)": [[1, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder.addNoise", false], [9, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder.addNoise", false]], "applyto() (euclidlike_imsim.photonops.chargediff method)": [[1, "euclidlike_imsim.photonOps.ChargeDiff.applyTo", false], [9, "euclidlike_imsim.photonOps.ChargeDiff.applyTo", false]], "buildbandpass() (euclidlike_imsim.bandpass.euclidlikebandpassbuilder method)": [[1, "euclidlike_imsim.bandpass.EuclidlikeBandpassBuilder.buildBandpass", false], [9, "euclidlike_imsim.bandpass.EuclidlikeBandpassBuilder.buildBandpass", false]], "buildimage() (euclidlike_imsim.ccd.euclidlikeccdimagebuilder method)": [[1, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder.buildImage", false], [9, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder.buildImage", false]], "buildphotonop() (euclidlike_imsim.photonops.chargediffbuilder method)": [[1, "euclidlike_imsim.photonOps.ChargeDiffBuilder.buildPhotonOp", false], [9, "euclidlike_imsim.photonOps.ChargeDiffBuilder.buildPhotonOp", false]], "buildpsf() (euclidlike_imsim.stamp.euclidlike_stamp method)": [[1, "euclidlike_imsim.stamp.Euclidlike_stamp.buildPSF", false], [9, "euclidlike_imsim.stamp.Euclidlike_stamp.buildPSF", false]], "buildwcs() (euclidlike_imsim.wcs.euclidlikewcs method)": [[1, "euclidlike_imsim.wcs.EuclidlikeWCS.buildWCS", false], [9, "euclidlike_imsim.wcs.EuclidlikeWCS.buildWCS", false]], "chargediff (class in euclidlike_imsim.photonops)": [[1, "euclidlike_imsim.photonOps.ChargeDiff", false], [9, "euclidlike_imsim.photonOps.ChargeDiff", false]], "chargediffbuilder (class in euclidlike_imsim.photonops)": [[1, "euclidlike_imsim.photonOps.ChargeDiffBuilder", false], [9, "euclidlike_imsim.photonOps.ChargeDiffBuilder", false]], "check_existing() (in module scripts.download_psf)": [[16, "scripts.download_psf.check_existing", false]], "check_input() (euclidlike_imsim.utils.roman_utils method)": [[1, "euclidlike_imsim.utils.roman_utils.check_input", false], [9, "euclidlike_imsim.utils.roman_utils.check_input", false]], "check_remove() (in module scripts.download_psf)": [[16, "scripts.download_psf.check_remove", false]], "check_unpack() (in module scripts.download_psf)": [[16, "scripts.download_psf.check_unpack", false]], "download() (in module scripts.download_psf)": [[16, "scripts.download_psf.download", false]], "download_psf() (in module scripts.download_psf)": [[16, "scripts.download_psf.download_psf", false]], "draw() (euclidlike_imsim.stamp.euclidlike_stamp method)": [[1, "euclidlike_imsim.stamp.Euclidlike_stamp.draw", false], [9, "euclidlike_imsim.stamp.Euclidlike_stamp.draw", false]], "euclidlike_imsim.bandpass": [[1, "module-euclidlike_imsim.bandpass", false], [9, "module-euclidlike_imsim.bandpass", false]], "euclidlike_imsim.ccd": [[1, "module-euclidlike_imsim.ccd", false], [9, "module-euclidlike_imsim.ccd", false]], "euclidlike_imsim.noise": [[1, "module-euclidlike_imsim.noise", false], [9, "module-euclidlike_imsim.noise", false]], "euclidlike_imsim.obseq": [[1, "module-euclidlike_imsim.obseq", false], [9, "module-euclidlike_imsim.obseq", false]], "euclidlike_imsim.photonops": [[1, "module-euclidlike_imsim.photonOps", false], [9, "module-euclidlike_imsim.photonOps", false]], "euclidlike_imsim.psf": [[1, "module-euclidlike_imsim.psf", false], [9, "module-euclidlike_imsim.psf", false]], "euclidlike_imsim.skycat": [[1, "module-euclidlike_imsim.skycat", false], [9, "module-euclidlike_imsim.skycat", false]], "euclidlike_imsim.stamp": [[1, "module-euclidlike_imsim.stamp", false], [9, "module-euclidlike_imsim.stamp", false]], "euclidlike_imsim.utils": [[1, "module-euclidlike_imsim.utils", false], [9, "module-euclidlike_imsim.utils", false]], "euclidlike_imsim.wcs": [[1, "module-euclidlike_imsim.wcs", false], [9, "module-euclidlike_imsim.wcs", false]], "euclidlike_stamp (class in euclidlike_imsim.stamp)": [[1, "euclidlike_imsim.stamp.Euclidlike_stamp", false], [9, "euclidlike_imsim.stamp.Euclidlike_stamp", false]], "euclidlikebandpassbuilder (class in euclidlike_imsim.bandpass)": [[1, "euclidlike_imsim.bandpass.EuclidlikeBandpassBuilder", false], [9, "euclidlike_imsim.bandpass.EuclidlikeBandpassBuilder", false]], "euclidlikeccdimagebuilder (class in euclidlike_imsim.ccd)": [[1, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder", false], [9, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder", false]], "euclidlikepsf (class in euclidlike_imsim.psf)": [[1, "euclidlike_imsim.psf.EuclidlikePSF", false], [9, "euclidlike_imsim.psf.EuclidlikePSF", false]], "euclidlikewcs (class in euclidlike_imsim.wcs)": [[1, "euclidlike_imsim.wcs.EuclidlikeWCS", false], [9, "euclidlike_imsim.wcs.EuclidlikeWCS", false]], "findccd() (in module euclidlike)": [[0, "euclidlike.findCCD", false], [8, "euclidlike.findCCD", false]], "fix_seds() (euclidlike_imsim.stamp.euclidlike_stamp class method)": [[1, "euclidlike_imsim.stamp.Euclidlike_stamp.fix_seds", false], [9, "euclidlike_imsim.stamp.Euclidlike_stamp.fix_seds", false]], "get() (euclidlike_imsim.obseq.obseqdataloader method)": [[1, "euclidlike_imsim.obseq.ObSeqDataLoader.get", false], [9, "euclidlike_imsim.obseq.ObSeqDataLoader.get", false]], "get_ccd_center() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.get_ccd_center", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.get_ccd_center", false]], "get_input() (in module scripts.download_psf)": [[16, "scripts.download_psf.get_input", false]], "get_meta() (in module scripts.download_psf)": [[16, "scripts.download_psf.get_meta", false]], "get_names() (in module scripts.download_psf)": [[16, "scripts.download_psf.get_names", false]], "get_noise() (in module euclidlike_imsim.noise)": [[1, "euclidlike_imsim.noise.get_noise", false], [9, "euclidlike_imsim.noise.get_noise", false]], "getapproxnobjects() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.getApproxNObjects", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.getApproxNObjects", false]], "getbandpass() (euclidlike_imsim.utils.roman_utils method)": [[1, "euclidlike_imsim.utils.roman_utils.getBandpass", false], [9, "euclidlike_imsim.utils.roman_utils.getBandpass", false]], "getbandpasses() (in module euclidlike)": [[0, "euclidlike.getBandpasses", false], [8, "euclidlike.getBandpasses", false]], "getbrightpsf() (in module euclidlike)": [[0, "euclidlike.getBrightPSF", false], [8, "euclidlike.getBrightPSF", false]], "getdrawmethod() (euclidlike_imsim.stamp.euclidlike_stamp method)": [[1, "euclidlike_imsim.stamp.Euclidlike_stamp.getDrawMethod", false], [9, "euclidlike_imsim.stamp.Euclidlike_stamp.getDrawMethod", false]], "getflux() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.getFlux", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.getFlux", false]], "getkwargs() (euclidlike_imsim.psf.psfloader method)": [[1, "euclidlike_imsim.psf.PSFLoader.getKwargs", false], [9, "euclidlike_imsim.psf.PSFLoader.getKwargs", false]], "getkwargs() (euclidlike_imsim.skycat.skycatalogloader method)": [[1, "euclidlike_imsim.skycat.SkyCatalogLoader.getKwargs", false], [9, "euclidlike_imsim.skycat.SkyCatalogLoader.getKwargs", false]], "getlocalwcs() (euclidlike_imsim.utils.roman_utils method)": [[1, "euclidlike_imsim.utils.roman_utils.getLocalWCS", false], [9, "euclidlike_imsim.utils.roman_utils.getLocalWCS", false]], "getnobjects() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.getNObjects", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.getNObjects", false]], "getobj() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.getObj", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.getObj", false]], "getpsf() (euclidlike_imsim.psf.euclidlikepsf method)": [[1, "euclidlike_imsim.psf.EuclidlikePSF.getPSF", false], [9, "euclidlike_imsim.psf.EuclidlikePSF.getPSF", false]], "getpsf() (euclidlike_imsim.utils.roman_utils method)": [[1, "euclidlike_imsim.utils.roman_utils.getPSF", false], [9, "euclidlike_imsim.utils.roman_utils.getPSF", false]], "getpsf() (in module euclidlike)": [[0, "euclidlike.getPSF", false], [8, "euclidlike.getPSF", false]], "getpsf_image() (euclidlike_imsim.utils.roman_utils method)": [[1, "euclidlike_imsim.utils.roman_utils.getPSF_Image", false], [9, "euclidlike_imsim.utils.roman_utils.getPSF_Image", false]], "getskylevel() (in module euclidlike)": [[0, "euclidlike.getSkyLevel", false], [8, "euclidlike.getSkyLevel", false]], "getvalue() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.getValue", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.getValue", false]], "getwcs() (euclidlike_imsim.utils.roman_utils method)": [[1, "euclidlike_imsim.utils.roman_utils.getWCS", false], [9, "euclidlike_imsim.utils.roman_utils.getWCS", false]], "getwcs() (in module euclidlike)": [[0, "euclidlike.getWCS", false], [8, "euclidlike.getWCS", false]], "getworldpos() (euclidlike_imsim.skycat.skycataloginterface method)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.getWorldPos", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.getWorldPos", false]], "initialize() (euclidlike_imsim.noise.noiseimagebuilder method)": [[1, "euclidlike_imsim.noise.NoiseImageBuilder.initialize", false], [9, "euclidlike_imsim.noise.NoiseImageBuilder.initialize", false]], "main() (in module scripts.download_psf)": [[16, "scripts.download_psf.main", false]], "make_euclidlike_pupil_plane() (in module scripts.make_euclidlike_pupil_plane)": [[16, "scripts.make_euclidlike_pupil_plane.make_EuclidLike_pupil_plane", false]], "make_link() (in module scripts.download_psf)": [[16, "scripts.download_psf.make_link", false]], "module": [[1, "module-euclidlike_imsim.bandpass", false], [1, "module-euclidlike_imsim.ccd", false], [1, "module-euclidlike_imsim.noise", false], [1, "module-euclidlike_imsim.obseq", false], [1, "module-euclidlike_imsim.photonOps", false], [1, "module-euclidlike_imsim.psf", false], [1, "module-euclidlike_imsim.skycat", false], [1, "module-euclidlike_imsim.stamp", false], [1, "module-euclidlike_imsim.utils", false], [1, "module-euclidlike_imsim.wcs", false], [9, "module-euclidlike_imsim.bandpass", false], [9, "module-euclidlike_imsim.ccd", false], [9, "module-euclidlike_imsim.noise", false], [9, "module-euclidlike_imsim.obseq", false], [9, "module-euclidlike_imsim.photonOps", false], [9, "module-euclidlike_imsim.psf", false], [9, "module-euclidlike_imsim.skycat", false], [9, "module-euclidlike_imsim.stamp", false], [9, "module-euclidlike_imsim.utils", false], [9, "module-euclidlike_imsim.wcs", false], [16, "module-scripts", false], [16, "module-scripts.download_psf", false], [16, "module-scripts.make_euclidlike_pupil_plane", false]], "noiseimagebuilder (class in euclidlike_imsim.noise)": [[1, "euclidlike_imsim.noise.NoiseImageBuilder", false], [9, "euclidlike_imsim.noise.NoiseImageBuilder", false]], "objects (euclidlike_imsim.skycat.skycataloginterface property)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface.objects", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface.objects", false]], "obseqdata() (in module euclidlike_imsim.obseq)": [[1, "euclidlike_imsim.obseq.ObSeqData", false], [9, "euclidlike_imsim.obseq.ObSeqData", false]], "obseqdataloader (class in euclidlike_imsim.obseq)": [[1, "euclidlike_imsim.obseq.ObSeqDataLoader", false], [9, "euclidlike_imsim.obseq.ObSeqDataLoader", false]], "parse_args() (in module scripts.download_psf)": [[16, "scripts.download_psf.parse_args", false]], "parse_noise_config() (in module euclidlike_imsim.noise)": [[1, "euclidlike_imsim.noise.parse_noise_config", false], [9, "euclidlike_imsim.noise.parse_noise_config", false]], "processimage() (euclidlike_imsim.noise.noiseimagebuilder method)": [[1, "euclidlike_imsim.noise.NoiseImageBuilder.processImage", false], [9, "euclidlike_imsim.noise.NoiseImageBuilder.processImage", false]], "processimage() (euclidlike_imsim.noise.skyimagebuilder method)": [[1, "euclidlike_imsim.noise.SkyImageBuilder.processImage", false], [9, "euclidlike_imsim.noise.SkyImageBuilder.processImage", false]], "processimage() (euclidlike_imsim.noise.weightimagebuilder method)": [[1, "euclidlike_imsim.noise.WeightImageBuilder.processImage", false], [9, "euclidlike_imsim.noise.WeightImageBuilder.processImage", false]], "psfloader (class in euclidlike_imsim.psf)": [[1, "euclidlike_imsim.psf.PSFLoader", false], [9, "euclidlike_imsim.psf.PSFLoader", false]], "query_yes_no() (in module scripts.download_psf)": [[16, "scripts.download_psf.query_yes_no", false]], "read_obseq() (euclidlike_imsim.obseq.obseqdataloader method)": [[1, "euclidlike_imsim.obseq.ObSeqDataLoader.read_obseq", false], [9, "euclidlike_imsim.obseq.ObSeqDataLoader.read_obseq", false]], "remove_tarball() (in module scripts.download_psf)": [[16, "scripts.download_psf.remove_tarball", false]], "roman_utils (class in euclidlike_imsim.utils)": [[1, "euclidlike_imsim.utils.roman_utils", false], [9, "euclidlike_imsim.utils.roman_utils", false]], "run_main() (in module scripts.download_psf)": [[16, "scripts.download_psf.run_main", false]], "scripts": [[16, "module-scripts", false]], "scripts.download_psf": [[16, "module-scripts.download_psf", false]], "scripts.make_euclidlike_pupil_plane": [[16, "module-scripts.make_euclidlike_pupil_plane", false]], "setup() (euclidlike_imsim.ccd.euclidlikeccdimagebuilder method)": [[1, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder.setup", false], [9, "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder.setup", false]], "setup() (euclidlike_imsim.stamp.euclidlike_stamp method)": [[1, "euclidlike_imsim.stamp.Euclidlike_stamp.setup", false], [9, "euclidlike_imsim.stamp.Euclidlike_stamp.setup", false]], "skycataloginterface (class in euclidlike_imsim.skycat)": [[1, "euclidlike_imsim.skycat.SkyCatalogInterface", false], [9, "euclidlike_imsim.skycat.SkyCatalogInterface", false]], "skycatalogloader (class in euclidlike_imsim.skycat)": [[1, "euclidlike_imsim.skycat.SkyCatalogLoader", false], [9, "euclidlike_imsim.skycat.SkyCatalogLoader", false]], "skycatobj() (in module euclidlike_imsim.skycat)": [[1, "euclidlike_imsim.skycat.SkyCatObj", false], [9, "euclidlike_imsim.skycat.SkyCatObj", false]], "skycatvalue() (in module euclidlike_imsim.skycat)": [[1, "euclidlike_imsim.skycat.SkyCatValue", false], [9, "euclidlike_imsim.skycat.SkyCatValue", false]], "skycatworldpos() (in module euclidlike_imsim.skycat)": [[1, "euclidlike_imsim.skycat.SkyCatWorldPos", false], [9, "euclidlike_imsim.skycat.SkyCatWorldPos", false]], "skyimagebuilder (class in euclidlike_imsim.noise)": [[1, "euclidlike_imsim.noise.SkyImageBuilder", false], [9, "euclidlike_imsim.noise.SkyImageBuilder", false]], "unpack() (in module scripts.download_psf)": [[16, "scripts.download_psf.unpack", false]], "weightimagebuilder (class in euclidlike_imsim.noise)": [[1, "euclidlike_imsim.noise.WeightImageBuilder", false], [9, "euclidlike_imsim.noise.WeightImageBuilder", false]]}, "objects": {"": [[16, 1, 0, "-", "scripts"]], "euclidlike": [[8, 0, 1, "", "findCCD"], [8, 0, 1, "", "getBandpasses"], [8, 0, 1, "", "getBrightPSF"], [8, 0, 1, "", "getPSF"], [8, 0, 1, "", "getSkyLevel"], [8, 0, 1, "", "getWCS"]], "euclidlike_imsim": [[9, 1, 0, "-", "bandpass"], [9, 1, 0, "-", "ccd"], [9, 1, 0, "-", "noise"], [9, 1, 0, "-", "obseq"], [9, 1, 0, "-", "photonOps"], [9, 1, 0, "-", "psf"], [9, 1, 0, "-", "skycat"], [9, 1, 0, "-", "stamp"], [9, 1, 0, "-", "utils"], [9, 1, 0, "-", "wcs"]], "euclidlike_imsim.bandpass": [[9, 2, 1, "", "EuclidlikeBandpassBuilder"]], "euclidlike_imsim.bandpass.EuclidlikeBandpassBuilder": [[9, 3, 1, "", "buildBandpass"]], "euclidlike_imsim.ccd": [[9, 2, 1, "", "EuclidlikeCCDImageBuilder"]], "euclidlike_imsim.ccd.EuclidlikeCCDImageBuilder": [[9, 3, 1, "", "addNoise"], [9, 3, 1, "", "buildImage"], [9, 3, 1, "", "setup"]], "euclidlike_imsim.noise": [[9, 2, 1, "", "NoiseImageBuilder"], [9, 2, 1, "", "SkyImageBuilder"], [9, 2, 1, "", "WeightImageBuilder"], [9, 0, 1, "", "get_noise"], [9, 0, 1, "", "parse_noise_config"]], "euclidlike_imsim.noise.NoiseImageBuilder": [[9, 3, 1, "", "initialize"], [9, 3, 1, "", "processImage"]], "euclidlike_imsim.noise.SkyImageBuilder": [[9, 3, 1, "", "processImage"]], "euclidlike_imsim.noise.WeightImageBuilder": [[9, 3, 1, "", "processImage"]], "euclidlike_imsim.obseq": [[9, 0, 1, "", "ObSeqData"], [9, 2, 1, "", "ObSeqDataLoader"]], "euclidlike_imsim.obseq.ObSeqDataLoader": [[9, 3, 1, "", "get"], [9, 3, 1, "", "read_obseq"]], "euclidlike_imsim.photonOps": [[9, 2, 1, "", "ChargeDiff"], [9, 2, 1, "", "ChargeDiffBuilder"]], "euclidlike_imsim.photonOps.ChargeDiff": [[9, 3, 1, "", "applyTo"]], "euclidlike_imsim.photonOps.ChargeDiffBuilder": [[9, 3, 1, "", "buildPhotonOp"]], "euclidlike_imsim.psf": [[9, 2, 1, "", "EuclidlikePSF"], [9, 2, 1, "", "PSFLoader"]], "euclidlike_imsim.psf.EuclidlikePSF": [[9, 3, 1, "", "getPSF"]], "euclidlike_imsim.psf.PSFLoader": [[9, 3, 1, "", "getKwargs"]], "euclidlike_imsim.skycat": [[9, 0, 1, "", "SkyCatObj"], [9, 0, 1, "", "SkyCatValue"], [9, 0, 1, "", "SkyCatWorldPos"], [9, 2, 1, "", "SkyCatalogInterface"], [9, 2, 1, "", "SkyCatalogLoader"]], "euclidlike_imsim.skycat.SkyCatalogInterface": [[9, 3, 1, "", "getApproxNObjects"], [9, 3, 1, "", "getFlux"], [9, 3, 1, "", "getNObjects"], [9, 3, 1, "", "getObj"], [9, 3, 1, "", "getValue"], [9, 3, 1, "", "getWorldPos"], [9, 3, 1, "", "get_ccd_center"], [9, 4, 1, "", "objects"]], "euclidlike_imsim.skycat.SkyCatalogLoader": [[9, 3, 1, "", "getKwargs"]], "euclidlike_imsim.stamp": [[9, 2, 1, "", "Euclidlike_stamp"]], "euclidlike_imsim.stamp.Euclidlike_stamp": [[9, 3, 1, "", "buildPSF"], [9, 3, 1, "", "draw"], [9, 3, 1, "", "fix_seds"], [9, 3, 1, "", "getDrawMethod"], [9, 3, 1, "", "setup"]], "euclidlike_imsim.utils": [[9, 2, 1, "", "roman_utils"]], "euclidlike_imsim.utils.roman_utils": [[9, 3, 1, "", "check_input"], [9, 3, 1, "", "getBandpass"], [9, 3, 1, "", "getLocalWCS"], [9, 3, 1, "", "getPSF"], [9, 3, 1, "", "getPSF_Image"], [9, 3, 1, "", "getWCS"]], "euclidlike_imsim.wcs": [[9, 2, 1, "", "EuclidlikeWCS"]], "euclidlike_imsim.wcs.EuclidlikeWCS": [[9, 3, 1, "", "buildWCS"]], "scripts": [[16, 1, 0, "-", "download_psf"], [16, 1, 0, "-", "make_euclidlike_pupil_plane"]], "scripts.download_psf": [[16, 0, 1, "", "check_existing"], [16, 0, 1, "", "check_remove"], [16, 0, 1, "", "check_unpack"], [16, 0, 1, "", "download"], [16, 0, 1, "", "download_psf"], [16, 0, 1, "", "get_input"], [16, 0, 1, "", "get_meta"], [16, 0, 1, "", "get_names"], [16, 0, 1, "", "main"], [16, 0, 1, "", "make_link"], [16, 0, 1, "", "parse_args"], [16, 0, 1, "", "query_yes_no"], [16, 0, 1, "", "remove_tarball"], [16, 0, 1, "", "run_main"], [16, 0, 1, "", "unpack"]], "scripts.make_euclidlike_pupil_plane": [[16, 0, 1, "", "make_EuclidLike_pupil_plane"]]}, "objnames": {"0": ["py", "function", "Python function"], "1": ["py", "module", "Python module"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "property", "Python property"]}, "objtypes": {"0": "py:function", "1": "py:module", "2": "py:class", "3": "py:method", "4": "py:property"}, "terms": {"": [0, 8], "0": [0, 1, 8, 9, 12, 13], "1": [0, 1, 8, 9, 12, 13], "10": [0, 8, 13], "100": [1, 9], "1000000": [1, 9], "13": [2, 10], "17": [0, 8, 13], "180": [0, 8], "2": [0, 8, 9, 13, 16], "2023": [0, 8], "2025": [0, 8], "2048": 16, "2d": 16, "3": [13, 16], "30": [0, 1, 8, 9], "33688": 9, "33689": 9, "33690": 9, "35": [0, 8, 9], "3d": 16, "3x": [0, 8], "4": [0, 1, 8, 9], "5": [0, 8, 16], "6": 13, "8": [1, 9], "87e0c8e9770199cd276f5f0551054cb4902d53bb": 16, "90": [0, 8], "A": [0, 1, 8, 9, 16], "As": [0, 8], "But": [0, 8], "For": [0, 1, 8, 9, 13, 15], "If": [0, 1, 8, 9], "In": [0, 1, 8, 9], "It": [1, 9, 15, 16], "No": 16, "The": [2, 10, 12, 13, 14, 15, 16], "There": [0, 8], "These": [0, 8], "To": [9, 13, 15], "_opt_param": [1, 9], "_req_param": [1, 9], "_single_param": [1, 9], "_takes_rng": [1, 9], "ab": [0, 8], "ab_zeropoint": [0, 2, 8, 10], "aberr": [0, 8], "about": [0, 8, 15], "abov": 13, "access": [0, 1, 8, 9], "accord": [1, 9, 15], "account": [0, 8], "accross": [0, 8], "accuraci": [0, 8, 15], "achromat": [0, 8], "across": [1, 9, 16], "activ": [9, 13], "actual": [0, 1, 8, 9], "ad": [1, 9], "adapt": 16, "add": [1, 9], "addit": [0, 1, 8, 9], "addnois": [1, 9, 14], "adopt": [0, 8], "after": [0, 1, 8, 9, 15], "aim": 15, "aka": [1, 9], "al": 16, "alias": [0, 8], "all": [0, 8], "allow": [0, 1, 8, 9], "along": [2, 10, 15], "also": [0, 1, 8, 9, 15], "altern": [0, 8, 15], "alwai": [0, 8], "an": [0, 1, 8, 9, 15, 16], "analysi": 15, "angl": [0, 8, 16], "ani": [0, 1, 8, 9], "answer": 16, "apertur": [0, 8], "appear": [0, 8], "appli": [1, 9], "applic": [0, 8, 15], "applyto": [1, 9, 14], "appropi": [0, 8], "appropri": [1, 9], "approxim": [0, 1, 8, 9, 15], "ar": [0, 1, 8, 9, 15], "arbitrai": [0, 8], "arbitrari": [1, 9], "arcsec": [0, 8], "area": [0, 8], "arg": [0, 8, 16], "argpars": 16, "argument": [0, 8, 15, 16], "argv": 16, "around": [0, 1, 8, 9], "arrai": [0, 1, 8, 9], "articl": 15, "ask": [15, 16], "aspect": [0, 8], "associ": [1, 9], "assum": [0, 8], "astropi": 13, "asttyp": [0, 8], "atrribut": [0, 8], "attribut": [1, 9, 12, 14], "automodul": [0, 8], "avail": [0, 8, 15, 16], "awai": [0, 8], "axi": [0, 8], "b": [0, 8], "background": [0, 1, 2, 8, 9, 10], "baffl": [0, 8], "band": [0, 8], "bandpass": [0, 1, 2, 8, 9, 10], "base": [0, 1, 8, 9, 15], "bash": 9, "basic": [0, 1, 8, 9, 15], "been": [13, 16], "befor": [0, 8], "begin": [0, 8], "being": [1, 9], "below": [9, 16], "between": [0, 8], "bin": [1, 9], "blob": 16, "blue": [0, 8], "bool": [0, 1, 8, 9], "border": [0, 8], "both": [1, 9], "boxi": [0, 8], "bpass": [1, 9], "bright": [0, 8], "brighter": [0, 8], "brows": [0, 8], "bug": 15, "build": [1, 9], "buildbandpass": [1, 9, 14], "builder": [1, 9], "buildimag": [1, 9, 14], "buildphotonop": [1, 9, 14], "buildprofil": [1, 9], "buildpsf": [1, 9, 14], "buildwc": [1, 9, 14], "built": [1, 9], "bundl": [1, 9], "cab": [0, 8], "calcul": [0, 8], "call": [0, 1, 8, 9], "can": [0, 1, 2, 8, 9, 10, 15], "care": [0, 8], "carri": [0, 8], "case": [0, 1, 8, 9], "catalog": [1, 9], "ccd": [0, 1, 2, 8, 9, 10], "ccd2det": [0, 8], "ccd_id": 9, "ccd_po": [0, 8], "ccdid": [0, 8], "ccds_ccd": [2, 10], "cd": 13, "celestialcoord": [0, 1, 8, 9], "center": [0, 1, 2, 8, 9, 10], "certain": [0, 8], "cfg_imag": [1, 9], "cfg_nois": [1, 9], "chang": [0, 8, 9, 12], "charg": [0, 1, 8, 9], "chargediff": [1, 9, 14], "chargediffbuild": [1, 9, 14], "check": [0, 1, 8, 9], "check_exist": [14, 16], "check_input": [1, 9, 14], "check_remov": [14, 16], "check_unpack": [14, 16], "choos": [0, 8], "chosen": [0, 8], "chri": [0, 8], "chromat": [0, 1, 8, 9], "cite": 15, "class": [0, 8, 12, 14], "classmethod": [1, 9], "clone": 13, "close": [0, 8], "cm": [0, 8], "code": [1, 9, 13, 15, 16], "collect": [0, 8], "collecting_area": [0, 8], "column": [0, 8, 9], "com": [13, 16], "combin": [0, 1, 8, 9], "command": [0, 8, 9, 16], "command_arg": 16, "comment": 15, "commun": [1, 9, 12], "compromis": [0, 8], "comput": [0, 1, 8, 9], "conda": [9, 13], "config": [1, 12, 14], "config_fil": [1, 9], "configur": [0, 1, 8, 9, 15], "confus": [1, 9], "consid": [0, 8, 16], "consist": [0, 8], "consortium": 15, "construct": [0, 1, 8, 9, 15], "contain": [0, 1, 2, 8, 9, 10, 13, 15], "contrast": [0, 8], "contribut": [1, 9], "contributor": 15, "convent": [0, 2, 8, 10], "convers": [0, 8], "convert": [0, 8], "convolv": [1, 9], "coordin": [0, 1, 8, 9], "correct": [0, 8], "correspond": [0, 1, 8, 9], "cosmostat": 16, "cover": [0, 8], "creat": [0, 1, 8, 9, 13], "csic": [0, 8], "current": [1, 9, 13], "current_var": [1, 9], "curv": [0, 8], "data": [0, 1, 8, 9, 12], "date": [0, 1, 2, 8, 9, 10], "datetim": [0, 8], "deblend": 15, "debug": [1, 9], "decent": [0, 8], "decontamin": [0, 8], "default": [0, 1, 8, 9, 15, 16], "default_thin_trunc": [0, 8], "defin": [0, 1, 8, 9], "degrad": [0, 8], "degre": [0, 8], "demo": [0, 8, 12, 15], "depend": [0, 8, 9], "describ": [0, 8, 15], "descript": [0, 8], "det2ccd": [0, 8], "detail": [0, 8, 13, 15], "detect": 15, "detector": [0, 8], "determin": [0, 1, 8, 9], "detid": [0, 8], "develop": [12, 13, 16], "diamet": [0, 8], "dichroic": [0, 8], "dict": [0, 1, 8, 9], "dictionari": [0, 8], "differ": [0, 8], "diffus": [0, 1, 8, 9], "dir": [9, 15], "directli": [0, 8], "directori": [0, 2, 8, 9, 10, 15], "discret": [0, 8, 16], "displai": [2, 10], "distinct": 15, "dither": [0, 8], "divid": [0, 8], "do": [0, 1, 8, 9, 13], "do_download": 16, "do_filt": 16, "do_link": 16, "do_remov": 16, "do_unpack": 16, "docstr": [0, 8, 15], "document": 15, "doe": [0, 1, 8, 9], "doesn": [1, 9], "doi": 15, "done": [0, 8, 16], "download": [0, 8, 12, 14, 16], "download_cosmo": 16, "download_psf": 14, "draw": [0, 1, 8, 9, 14], "drawimag": [1, 9], "due": [0, 8], "duncan": [0, 8], "dure": [1, 9], "e": [0, 1, 8, 9], "each": [0, 1, 8, 9], "earli": [0, 8], "earth": [0, 8], "eclipt": [0, 8], "edge_pix": [1, 9], "effect": [0, 1, 8, 9], "either": [0, 8, 16], "els": [1, 9], "empti": [1, 9], "enabl": [0, 8, 15], "end": [0, 1, 8, 9, 12], "end_to_end_demo": [0, 2, 8, 10], "enough": [0, 8], "enter": 16, "entir": [0, 8], "entri": 9, "env_nam": 9, "environ": 9, "epoch": [0, 8], "equinox": [0, 8], "equival": [2, 10], "ero": [0, 8], "err": 9, "error": [0, 1, 8, 9], "esa": [0, 8], "esac": [0, 8], "especi": [0, 8], "estim": [0, 8], "et": 16, "etc": [0, 8], "euclid": [2, 10, 13, 14, 16], "euclid_lik": [0, 8], "euclid_obseq": 9, "euclidlik": [0, 1, 2, 8, 9, 10, 13, 15], "euclidlike_download_psf": [0, 8, 15], "euclidlike_imsim": [1, 9, 15], "euclidlike_stamp": [1, 9, 14], "euclidlikebandpassbuild": [1, 9, 14], "euclidlikeccdimagebuild": [1, 9, 14], "euclidlikepsf": [1, 9, 14], "euclidlikewc": [1, 9, 14], "even": [0, 8], "everyth": [0, 8], "exact": [0, 8], "exampl": [0, 1, 8, 9, 12, 15], "except": [0, 8], "exist": [1, 9], "expect": [0, 1, 8, 9], "explor": 15, "exposur": [0, 1, 8, 9], "express": [0, 8], "exptim": [0, 1, 8, 9], "extra_aberr": [1, 9], "factor": [1, 9], "fair": [0, 8], "fake": [0, 8], "fall": [0, 8], "fals": [0, 1, 8, 9], "fast": 15, "faster": [0, 8], "fatter": [0, 8], "featur": [2, 10], "feel": 15, "fidel": 15, "field": [0, 1, 8, 9], "figur": [0, 1, 8, 9], "file": [0, 1, 2, 8, 9, 10], "file_list": 9, "file_nam": [1, 9], "file_scop": [1, 9], "filebandpass": [1, 9], "filter": [0, 1, 8, 9], "filter_nam": [2, 10], "final": [1, 9], "find": [0, 8], "findccd": [0, 8, 14], "first": [1, 2, 9, 10], "fit": 9, "fix_s": [1, 9, 14], "flag": 15, "flat": [1, 9], "float": [0, 1, 8, 9], "flux": [0, 1, 8, 9], "focal": [0, 8, 12, 15, 16], "focu": [0, 8], "folding_threshold": [0, 8], "follow": [0, 1, 8, 9, 13], "form": 16, "format": [0, 1, 8, 9], "fov": [15, 16], "fpa": [0, 8], "fps3": [0, 8], "fraction": [0, 8], "free": 15, "from": [0, 1, 2, 8, 9, 10, 12, 13, 15, 16], "full": [0, 1, 8, 9, 15], "full_bandpass": [0, 8], "fulli": [0, 8], "function": [12, 14, 15, 16], "further": [13, 15], "futur": [0, 8], "gain": [0, 8], "galaxi": [1, 2, 9, 10], "galsim": [0, 1, 2, 8, 9, 10, 13, 16], "gap": [0, 8], "gener": [0, 1, 2, 8, 9, 10, 15], "generate_pupil_obscur": 16, "geometri": [0, 8], "get": [0, 1, 8, 9, 12, 14], "get_ccd_cent": [1, 9, 14], "get_input": [14, 16], "get_meta": [14, 16], "get_nam": [14, 16], "get_nois": [1, 9, 14], "getapproxnobject": [1, 9, 14], "getbandpass": [0, 1, 2, 8, 9, 10, 13, 14], "getbrightpsf": [0, 8, 14], "getdrawmethod": [1, 9, 14], "getflux": [1, 9, 14], "getkwarg": [1, 9, 14], "getlocalwc": [1, 9, 14], "getnobject": [1, 9, 14], "getobj": [1, 9, 14], "getpsf": [0, 1, 2, 8, 9, 10, 14, 15], "getpsf_imag": [1, 9, 14], "getskylevel": [0, 2, 8, 10, 14], "getvalu": [1, 9, 14], "getwc": [0, 1, 2, 8, 9, 10, 14], "getworldpo": [1, 9, 14], "getzodibackground": [0, 8], "git": 13, "github": [13, 15, 16], "give": [0, 8], "given": [0, 1, 8, 9, 13, 15, 16], "gname": [0, 8], "gname2": [0, 8], "goe": [1, 9], "good": [0, 8], "grab": 16, "grid": [0, 8, 15], "ground": 15, "gsobject": [1, 9], "gsparam": [0, 1, 8, 9], "guid": [0, 8], "ha": [0, 8, 13, 15, 16], "half": [0, 8], "handl": [0, 8, 16], "has_nobj": [1, 9], "have": [0, 8], "heavi": 13, "heavili": [1, 9, 15], "helper": [0, 1, 8, 9, 15], "here": [0, 1, 8, 9], "high": [0, 8, 15], "higher": 15, "highlight": 15, "histori": 12, "hit": 16, "how": [0, 2, 8, 10, 15], "howev": [0, 8], "http": [0, 8, 16], "i": [0, 1, 2, 8, 9, 10, 13, 15, 16], "ic": [0, 8], "id": [0, 2, 8, 10], "ignor": [0, 1, 8, 9], "illustr": 15, "imag": [0, 1, 8, 9, 15], "image_nam": [1, 9], "image_num": [1, 9], "image_po": [1, 9], "implement": [1, 9, 16], "import": [0, 8, 13], "imsim": [12, 14], "includ": [0, 1, 8, 9, 15], "include_bord": [0, 8], "include_photonop": [1, 9], "incorpor": [0, 8], "independ": [1, 9], "index": [0, 1, 4, 8, 9, 12], "indic": [0, 1, 8, 9, 15], "ineffici": [0, 8], "infer": [0, 8], "info": [1, 9], "inform": [0, 1, 8, 9, 15], "init_func": [1, 9], "initi": [1, 9, 14], "input": [0, 1, 8, 9, 16], "instal": 12, "instanc": [1, 9], "instruct": [12, 15], "instrument": [0, 8, 15], "instrument_param": [0, 8], "int": [0, 1, 8, 9], "inta": [0, 8], "integ": [0, 8], "interest": [0, 8, 15], "interfac": [1, 9], "intern": [0, 8], "interpol": [0, 8], "interpolatedchromaticobject": [0, 8], "interpolatedimag": [0, 8], "introduc": [2, 10], "ipac": [0, 8], "isn": [1, 9], "isr": [0, 8], "issu": 15, "item": [1, 9], "iter": [0, 8], "its": 15, "joint": 15, "journal": 15, "jupyt": [2, 10], "just": 16, "keep": [1, 9], "kei": [0, 8], "keyword": [0, 8], "kick": 16, "know": [0, 8], "knowledg": [0, 8], "known": [1, 9], "kwarg": [0, 1, 8, 9], "l233": 16, "label": [0, 8], "lack": [0, 8], "lanc": [0, 8], "larg": [1, 9, 15], "later": [0, 8], "latest": [0, 8], "latitud": [0, 8], "layout": 12, "lead": [0, 8], "leav": [0, 8], "length": [1, 9], "lens": [0, 8, 15], "level": [12, 14], "liaudat": 16, "librari": [13, 15], "licens": 15, "lie": [0, 8], "life": [0, 8], "light": [0, 8], "like": [2, 10, 13, 14, 16], "limit": [0, 1, 8, 9], "line": [9, 16], "linear": [0, 8], "link": [9, 15], "link_dir": 16, "linux": 13, "list": [0, 1, 8, 9], "load": [0, 1, 8, 9], "loader": [1, 9], "local": [1, 9], "local_wc": [1, 9], "localwc": [1, 9], "locat": [0, 1, 8, 9], "log": [1, 9], "logger": [0, 1, 8, 9, 16], "long_exptim": [0, 8], "longer": [0, 8], "longitud": [0, 8], "look": [0, 1, 8, 9], "lookup": [0, 8], "lookupt": [0, 8], "lower": [0, 8], "m": [0, 8], "mac": 13, "made": 11, "magnitud": [0, 8], "mai": [0, 1, 8, 9, 15], "main": [14, 16], "make": [0, 1, 8, 9, 13], "make_euclidlike_pupil_plan": 14, "make_link": [14, 16], "makeskyimag": [0, 8], "mani": [0, 8], "map": [0, 1, 8, 9], "max_flux": [1, 9], "max_sun_angl": [0, 8], "maximum": [0, 8], "mean": [0, 8, 16], "meant": [0, 8], "measur": [0, 8], "member": [0, 8], "meta": 16, "meter": [0, 8], "method": [1, 9, 15], "might": [0, 1, 8, 9], "miller": [0, 8], "min_sun_angl": [0, 8], "minimum": [0, 8], "mjd": [1, 9], "mm": [0, 8], "mode": [0, 8], "model": [0, 1, 8, 9], "modul": [2, 4, 10, 12, 14], "more": [0, 1, 8, 9, 15], "most": [0, 1, 8, 9], "msp": [0, 8], "much": [0, 8], "multipl": [1, 9], "multipli": [0, 8], "must": [0, 1, 8, 9, 15, 16], "n": 13, "n_ccd": [0, 8], "n_ccd_col": [0, 8], "n_ccd_row": [0, 8], "n_col": [0, 8], "n_dither": [0, 8], "n_filter": 16, "n_phot": [1, 9], "n_pix": 16, "n_pix_col": [0, 8], "n_pix_row": [0, 8], "n_row": [0, 8], "n_wave": [0, 1, 8, 9], "name": [1, 9], "nanomet": [0, 8], "nativ": [1, 9, 16], "necessari": [1, 9], "need": [0, 1, 8, 9, 15], "new": [1, 9, 15], "nimag": [1, 9], "nisp": [0, 8], "nisp_band": [0, 8], "nm": [0, 8], "nois": [0, 1, 2, 8, 9, 10], "noiseimagebuild": [1, 9, 14], "non": [0, 8, 16], "none": [0, 1, 8, 9, 16], "nonlinear": [0, 8], "normal": [0, 8], "note": [0, 1, 8, 9, 15, 16], "notebook": [2, 10], "np": [0, 8], "number": [0, 1, 8, 9], "numer": [0, 8], "numpi": [1, 9, 13], "obj_num": [1, 9], "obj_typ": [1, 9], "object": [0, 1, 8, 9, 14, 15], "object_index": [1, 9], "obliqu": [0, 8], "obs_kind": [1, 9], "obscur": [0, 8], "obseq": [1, 9], "obseq_data": 9, "obseqdata": [1, 9, 14], "obseqdataload": [1, 9, 14], "observ": [0, 1, 2, 8, 9, 10], "observatori": [0, 8, 15], "obtain": [0, 1, 8, 9], "off": 16, "offset": [1, 9], "old": [0, 8], "older": 12, "omit": [0, 8], "onc": 15, "one": [0, 1, 8, 9, 16], "onli": [0, 1, 8, 9, 13, 15, 16], "onto": [0, 1, 8, 9], "open": 15, "oper": [1, 9], "optic": [0, 8], "optim": [0, 8], "option": [0, 1, 8, 9], "optpars": 16, "orbit": [0, 8], "order": [0, 8], "orient": [0, 8], "osx": 13, "other": [0, 1, 8, 9], "otherwis": [0, 8], "out": [0, 1, 8, 9], "output": [0, 1, 2, 8, 9, 10], "outskirt": [0, 8], "over": [0, 8], "overrid": [1, 9], "oversampl": [0, 1, 8, 9, 15], "oversampling_factor": [1, 9], "overview": 12, "own": 15, "pa": [0, 8], "pa_is_fpa": [0, 8], "packag": [0, 1, 2, 8, 9, 10, 14, 15], "page": [4, 12], "panel": [0, 8], "paper": 15, "parallel": [0, 8], "param": [1, 9], "paramet": [0, 1, 8, 9, 16], "pars": [1, 9], "parse_arg": [14, 16], "parse_noise_config": [1, 9, 14], "part": [0, 1, 8, 9], "particular": [0, 8, 15], "particularli": 15, "pass": [0, 8], "passband": [0, 8], "path": 9, "pattern": [0, 8], "per": [0, 8], "perfectli": [0, 8], "perform": [1, 9], "photo": [0, 8], "photometri": 15, "photon": [0, 1, 8, 9], "photon_arrai": [1, 9], "photonarrai": [1, 9], "photonop": [1, 9], "php": [0, 8], "physic": [0, 8], "pi": [0, 8], "pip": 13, "pix": [0, 8], "pixel": [0, 8], "pixel_scal": [0, 1, 8, 9], "pixel_scale_mm": [0, 8], "pixelscal": [0, 8], "place": [1, 9, 15], "plan": [0, 8], "plane": [0, 8, 12, 15, 16], "plate": [0, 8], "plate_scal": [0, 8], "pleas": 15, "plot_vi": [2, 10], "po": [1, 9], "point": [0, 1, 8, 9], "polar": [0, 8], "posit": [0, 1, 8, 9, 15], "positiond": [0, 8], "possibl": [0, 8], "possibli": [0, 8], "post": [0, 8], "postag": [1, 9], "preced": [1, 9], "precis": [0, 8, 15], "precomput": [0, 8, 15], "preliminari": 15, "present": [1, 9, 16], "presum": 16, "probabl": [1, 9], "probablist": [1, 9], "procedur": 16, "process": [0, 1, 8, 9, 16], "processimag": [1, 9, 14], "produc": [0, 1, 2, 8, 9, 10, 15], "prof": [1, 9], "profil": [1, 9], "program": 16, "progress": [1, 9], "project": [0, 8, 16], "properli": [0, 8], "properti": [1, 9], "provid": [0, 1, 8, 9, 15], "psf": [0, 1, 2, 8, 9, 10, 15, 16], "psf_dir": [0, 8], "psfloader": [1, 9, 14], "public": 11, "publicli": [0, 8], "publish": 13, "pupil": [0, 1, 8, 9], "pupil_bin": [0, 1, 8, 9], "py": [0, 2, 8, 10, 16], "pypi": 13, "python": [0, 2, 8, 10, 13], "qe": [0, 8], "quadrant": [0, 1, 8, 9], "queri": [0, 8], "query_yes_no": [14, 16], "question": [15, 16], "quickskip": [1, 9], "rais": [0, 8], "random": [1, 9], "rang": [0, 8], "rather": [1, 9, 15], "reach": 15, "read": [0, 1, 8, 9], "read_nois": [0, 8], "read_obseq": [1, 9, 14], "readm": 15, "readout": [0, 8], "real": [0, 1, 8, 9], "realist": [0, 2, 8, 10], "rebuilt": [1, 9], "red": [0, 8], "refdata": [0, 8], "refer": [0, 8, 12], "reflect": [0, 8], "regular": [1, 9], "rel": [0, 8], "relat": [0, 8], "releas": [0, 8, 16], "relev": 12, "remov": [0, 8], "remove_tarbal": [14, 16], "render": [0, 1, 8, 9], "renorm": [0, 8], "repo": 11, "report": 15, "repositori": [13, 15], "repres": [0, 8], "represent": [0, 1, 8, 9, 15], "request": [0, 1, 8, 9], "requir": [0, 1, 8, 9, 13, 15, 16], "research": 15, "respect": [0, 8], "respons": [0, 8], "result": [0, 1, 8, 9, 15], "return": [0, 1, 8, 9, 16], "revis": 12, "rng": [1, 9], "roman": [0, 1, 8, 9], "roman_imsim": [1, 9, 15], "roman_util": [1, 9, 14], "roughli": [0, 8], "routin": [0, 1, 8, 9, 15], "row": [0, 8], "run": [0, 1, 2, 8, 9, 10, 13, 15], "run_list": 9, "run_main": [14, 16], "saa": [0, 8], "safe": [1, 9], "sai": [1, 9], "same": [0, 8], "sampl": [0, 1, 8, 9, 16], "satur": [0, 8], "save": [1, 9], "sbatch": 9, "sca": [1, 9], "scale": [0, 1, 8, 9, 15], "scatter": [1, 9], "scenario": [0, 8], "scene": [2, 10], "scratch": [1, 9], "script": [0, 1, 2, 8, 9, 10, 14, 15], "search": [4, 12], "sec": [0, 8], "second": [0, 8], "sed": [0, 1, 8, 9], "see": [0, 1, 8, 9, 13, 15], "select": [0, 8], "self": [1, 9], "sens": [1, 9], "sensibli": [0, 8], "sensor": [0, 8], "septemb": [0, 8], "sequenc": [0, 1, 8, 9], "set": [0, 1, 8, 9], "setup": [1, 9, 14], "setup_skycat": [1, 9], "sever": [0, 8], "sh": 9, "shape": [0, 8], "shear": [0, 8], "shell": 9, "short_exptime_nisp": [0, 8], "short_exptime_vi": [0, 8], "shorter": [0, 8], "should": [0, 8, 9, 15], "shouldn": [1, 9], "show": [0, 2, 8, 10], "signatur": [0, 8], "sim": 16, "simpl": 16, "simpli": [0, 8], "simplifi": [0, 8], "simpsftoolkit": 16, "simul": [0, 1, 8, 9, 15], "singl": [0, 1, 8, 9], "size": [0, 1, 8, 9], "sky": [0, 1, 8, 9], "sky_catalog": 9, "skycat": [1, 9], "skycatalog": [1, 9], "skycataloginterfac": [1, 9, 14], "skycatalogload": [1, 9, 14], "skycatobj": [1, 9, 14], "skycatvalu": [1, 9, 14], "skycatworldpo": [1, 9, 14], "skyimagebuild": [1, 9, 14], "slower": [0, 8], "slurm": [12, 14], "slurm_runn": 9, "small": [0, 8], "so": [0, 1, 8, 9], "softwar": 15, "solar": [0, 8], "some": [0, 1, 8, 9, 15], "sourc": [0, 1, 8, 9, 13, 15, 16], "space": [1, 9, 15], "spatial": [0, 8], "special": [1, 9], "specif": [0, 1, 8, 9], "specifi": [0, 1, 8, 9], "spider": [0, 8], "src": 16, "stamp": [1, 9], "stamp_siz": [1, 9], "star": [0, 2, 8, 10], "start": [1, 9, 12], "statement": [1, 9], "stderr": 9, "stdout": 9, "store": [0, 8], "str": [0, 1, 8, 9], "string": [0, 8, 16], "strut": [0, 8], "sub": [1, 9], "subcompon": [1, 9], "submodul": 14, "subroutin": [0, 8], "subset": [0, 8], "subtract": [1, 9], "success": 13, "suffici": 15, "sum": [0, 1, 8, 9], "sun": [0, 8], "suppli": [0, 8], "support": 13, "suppress": [0, 8], "sure": 13, "surfac": [0, 8], "survei": 15, "svo": [0, 8], "svo2": [0, 8], "switch": [0, 8], "sy": 16, "system": [0, 8, 13], "t": [1, 9], "tabl": [0, 8], "tabul": [0, 8], "take": [0, 1, 8, 9], "taken": [0, 8, 16], "takes_logg": [1, 9], "target": 16, "target_dir": 16, "task": [1, 9], "telescop": [0, 2, 8, 10, 15], "term": 15, "termin": [0, 8, 15], "test": [0, 8], "than": [0, 8, 15], "thei": [0, 8], "theori": [0, 8], "therefor": [0, 8], "thi": [0, 1, 2, 8, 9, 10, 15, 16], "thin": [0, 8], "thing": [1, 9], "those": [0, 8, 15], "thought": [0, 8], "three": [0, 8], "through": 15, "time": [0, 1, 8, 9], "tobia": 16, "total": [0, 8], "toward": [0, 8, 15], "transfer": [0, 8], "transmiss": [0, 8], "true": [0, 1, 8, 9, 16], "truncat": [0, 8], "truth": 9, "tupl": [1, 9], "two": [1, 9, 13, 15], "txt": 9, "type": [1, 9], "typic": [0, 8], "uncertain": [0, 8], "undoc": [0, 8], "unit": [0, 8], "unless": [0, 8], "unpack": [14, 16], "unpack_dir": 16, "up": [0, 1, 8, 9], "updat": [9, 15], "ur": [0, 8], "url": [15, 16], "us": [0, 2, 8, 10, 14, 15, 16], "use_ccd": [2, 10], "use_proxi": [1, 9], "user": [0, 8, 16], "util": [0, 1, 8, 9], "v0": 12, "v1": [0, 8], "valu": [0, 1, 8, 9, 16], "value_typ": [1, 9], "vari": [0, 8], "varianc": [1, 9], "variat": [0, 8], "varieti": [1, 9], "veri": [0, 8], "vernal": [0, 8], "version": [12, 13], "vi": [0, 8], "via": [1, 9, 16], "view": 15, "vignet": [0, 8], "vis_band": [0, 8], "vis_blue_limit": [0, 8], "vis_red_limit": [0, 8], "visit": [1, 9], "visual": [2, 10], "wa": [0, 8, 9, 16], "wai": [0, 8], "want": [0, 1, 8, 9], "wavefront": [0, 8], "wavelength": [0, 8, 15, 16], "wc": [0, 1, 2, 8, 9, 10], "wcs_dict": [0, 8], "we": [0, 1, 8, 9, 15], "weak": [0, 8, 15], "websit": 15, "weight": [1, 9], "weightimagebuild": [1, 9, 14], "welcom": 15, "were": [0, 1, 8, 9], "wf": 16, "wf_psf": 16, "what": [0, 1, 8, 9], "when": [0, 1, 8, 9, 15], "where": [0, 1, 8, 9, 15], "whether": [0, 1, 8, 9], "which": [0, 1, 8, 9], "who": [0, 8], "whole": 16, "wide": [0, 8], "wish": [0, 8], "within": [0, 8, 15], "without": [0, 8], "won": [1, 9], "work": [1, 9], "worker_init": [1, 9], "worker_initarg": [1, 9], "world": [0, 8], "world_po": [0, 1, 2, 8, 9, 10], "would": [0, 1, 8, 9], "wrt": 16, "x": [1, 9], "xsize": [1, 9], "y": [0, 1, 8, 9], "yaml": 9, "ye": 16, "yet": [1, 9], "you": [0, 1, 8, 9], "ysize": [1, 9], "zenodo": 15, "zeropoint": [0, 8], "zodiac": [0, 8], "zsh": 9}, "titles": ["The Euclid-like Module", "The Euclid-like ImSim Module", "Examples", "<no title>", "GalSim-Euclid-Like: Euclid-like images using GalSim", "Installation", "<no title>", "Overview", "The Euclid-like Module", "The Euclid-like ImSim Module", "Examples", "Revision History", "GalSim-Euclid-Like: Euclid-like images using GalSim", "Installation", "<no title>", "Overview", "scripts package"], "titleterms": {"0": 11, "1": 11, "The": [0, 1, 8, 9], "attribut": [0, 8, 15], "chang": 11, "class": [1, 9], "commun": 15, "config": 9, "data": 15, "demo": [2, 10], "depend": 13, "develop": 15, "download": 15, "download_psf": 16, "end": [2, 10], "euclid": [0, 1, 4, 8, 9, 12, 15], "exampl": [2, 10], "focal": [2, 10], "from": 11, "function": [0, 1, 8, 9], "galsim": [4, 12, 15], "get": 15, "histori": 11, "imag": [4, 12], "imsim": [1, 9], "indic": [4, 12], "instal": [5, 13, 15], "instruct": 13, "layout": [2, 10], "level": [0, 8], "like": [0, 1, 4, 8, 9, 12, 15], "make_euclidlike_pupil_plan": 16, "modul": [0, 1, 8, 9, 16], "older": 11, "overview": [7, 15], "packag": 16, "plane": [2, 10], "refer": 15, "relev": 15, "revis": 11, "script": 16, "slurm": 9, "start": 15, "submodul": 16, "tabl": [4, 12], "us": [1, 4, 9, 12], "v0": 11, "version": 11}}) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index d38c79e..3220f77 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,6 +10,9 @@ import sys sys.path.insert(0,os.path.abspath('.')) +import euclidlike +import euclidlike_imsim + project = 'GalSim-Euclid-Like' copyright = '2024, Rachel Mandelbaum, Axel Guinot, Federico Berlfein, Andy Park, Xiangchong Li, Michael Troxel, Tianqing Zhang' author = 'Rachel Mandelbaum, Axel Guinot, Federico Berlfein, Andy Park, Xiangchong Li, Michael Troxel, Tianqing Zhang' @@ -21,7 +24,7 @@ extensions = [] templates_path = ['_templates'] -exclude_patterns = [] +exclude_patterns = ['**/.ipynb_checkpoints'] diff --git a/docs/euclidlike.rst b/docs/euclidlike.rst index c09a526..d4f2d47 100644 --- a/docs/euclidlike.rst +++ b/docs/euclidlike.rst @@ -1,53 +1,153 @@ -euclidlike package -================== +The Euclid-like Module +################################ -Submodules ----------- +The ``euclidlike`` module contains telescope information and functionality needed for image simulations. +The demo script end_to_end_demo.py shows how to use many of the atrributes and functions described here. -euclidlike.backgrounds module ------------------------------ -.. automodule:: euclidlike.backgrounds - :members: - :undoc-members: - :show-inheritance: +Module-level Attributes +======================= -euclidlike.bandpass module --------------------------- +There are several of attributes of the ``euclidlike`` module which define some numerical +parameters related to a Euclid-like geometry. Some of these parameters relate to the entire +wide-field imager. Others, especially the return values of the functions to get the +PSF and WCS, are specific to each CCD and therefore are indexed based on the detector number. +All detector-related arrays are 0-indexed, which might differ from the CCD indices for Euclid, +which run 1-1 to n_row-n_col. -.. automodule:: euclidlike.bandpass - :members: - :undoc-members: - :show-inheritance: +gain + The gain for all CCDs is expected to be the roughly the same. -euclidlike.euclidlike\_psf module ---------------------------------- +pixel_scale + The pixel scale in units of arcsec/pixel. -.. automodule:: euclidlike.euclidlike_psf - :members: - :undoc-members: - :show-inheritance: +diameter + The telescope diameter in meters. -euclidlike.euclidlike\_wcs module ---------------------------------- +obscuration + The linear obscuration of the telescope, expressed as a fraction of the diameter. -.. automodule:: euclidlike.euclidlike_wcs - :members: - :undoc-members: - :show-inheritance: +collecting_area + The actual collecting area after accounting for obscuration, struts, etc. in + units of cm^2. -euclidlike.instrument\_params module ------------------------------------- +long_exptime + The typical exposure time for the longer exposures used for VIS images, in units of seconds. + The number that is stored is for a single dither. -.. automodule:: euclidlike.instrument_params - :members: - :undoc-members: - :show-inheritance: +short_exptime_nisp + The typical exposure time for the shorter NISP imaging exposures used for VIS images, in units of seconds. + The number that is stored is for a single dither. -Module contents ---------------- +short_exptime_vis + The typical exposure time for the shorter exposures with VIS taken in parallel with NISP imaging, in units of seconds. + The number that is stored is for a single dither. -.. automodule:: euclidlike - :members: - :undoc-members: - :show-inheritance: +n_dithers + The number of dithers per filter. + +n_ccd + The number of CCDs in the focal plane. + +n_ccd_row + The number of CCDs in the each focal plane row. + +n_ccd_col + The number of CCDs in the each focal plane column. + +n_pix_row + Each CCD has n_pix_row total pixels in each row. +n_pix_col + Each CCD has n_pix_col total pixels in each column. + +pixel_scale_mm + The physical pixel size, in units of mm. + +plate_scale + The plate scale, in units of arcsec / mm + +read_noise + Total readout noise, in units of e-. + +saturation + Pixel saturation, in units of e-. + +det2ccd + Mapping from DETID to CCDID. + +ccd2det + Mapping from CCDID to DETID. + +min_sun_angle + Minimum allowed angle from the telescope solar panels to the sun, in degrees. + +max_sun_angle + Maximum allowed angle from the telescope solar panels to the sun, in degrees. + +vis_bands + List of available VIS bands +nisp_bands + List of available NISP bands + +vis_blue_limit + Bandpass blue limit needed for consistency with the wavelength range covered by ur tabulated + PSF images, in nm. + +vis_red_limit + Bandpass red limit needed for consistency with the wavelength range covered by ur tabulated + PSF images, in nm. + +For example, to get the gain value, use euclidlike.gain. + +#.. automodule:: euclidlike.instrument_params +# :members: +# :undoc-members: + + +Euclid-like Functions +=============== + +This module also contains the following routines: + +`euclidlike.getBandpasses` + A utility to get a dictionary containing galsim.Bandpass objects for each of + the Euclid-like imaging bandpasses, which by default have AB zeropoints given using + the GalSim zeropoint convention (see `getBandpasses` docstring for more details). + +`euclidlike.getSkyLevel` + A utility to find the expected sky level due to zodiacal light at a given + position, in a given band. + +`euclidlike.getZodiBackground` + This helper routine is enables the calculation of the zodiacal light, in photons/m^2/arcsec^2/sec + +`euclidlike.getPSF` + A routine to get a chromatic representation of the PSF in a single CCD. + PSFs are based on precomputed, oversampled (by 3x) PSF images on a grid in wavelength and + focal plane position. + +`euclidlike.getBrightPSF` + Get a fake optical PSF for very bright objects. + +`euclidlike.getWCS` + This routine returns a dict containing a WCS for each of the Euclid CCDs. + +`euclidlike.findCCD` + This is a helper routine to calculate the minimum and maximum pixel values that should be + considered within a CCD. + + + +.. autofunction:: euclidlike.getBandpasses + +.. autofunction:: euclidlike.getSkyLevel + +.. autofunction:: euclidlike.getZodiBackground + +.. autofunction:: euclidlike.getPSF + +.. autofunction:: euclidlike.getBrightPSF + +.. autofunction:: euclidlike.getWCS + +.. autofunction:: euclidlike.findCCD diff --git a/docs/euclidlike_imsim.rst b/docs/euclidlike_imsim.rst index bc6626f..244a9b5 100644 --- a/docs/euclidlike_imsim.rst +++ b/docs/euclidlike_imsim.rst @@ -1,109 +1,64 @@ -euclidlike\_imsim package -========================= +The Euclid-like ImSim Module +################################ -Submodules ----------- +This module contains configuration scripts to produce large-scale Euclid-like simulation runs based on the information in ``euclidlike``. +It is based heavily on `roman_imsim `_. -euclidlike\_imsim.bandpass module ---------------------------------- +Classes and Functions +===================== .. automodule:: euclidlike_imsim.bandpass :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.ccd module ----------------------------- .. automodule:: euclidlike_imsim.ccd :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.detector\_physics module ------------------------------------------- .. automodule:: euclidlike_imsim.detector_physics :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.noise module ------------------------------- .. automodule:: euclidlike_imsim.noise :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.obseq module ------------------------------- .. automodule:: euclidlike_imsim.obseq :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.photonOps module ----------------------------------- .. automodule:: euclidlike_imsim.photonOps :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.psf module ----------------------------- .. automodule:: euclidlike_imsim.psf :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.scafile module --------------------------------- .. automodule:: euclidlike_imsim.scafile :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.skycat module -------------------------------- .. automodule:: euclidlike_imsim.skycat :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.stamp module ------------------------------- .. automodule:: euclidlike_imsim.stamp :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.utils module ------------------------------- .. automodule:: euclidlike_imsim.utils :members: :undoc-members: - :show-inheritance: - -euclidlike\_imsim.wcs module ----------------------------- .. automodule:: euclidlike_imsim.wcs :members: :undoc-members: - :show-inheritance: -Module contents ---------------- -.. automodule:: euclidlike_imsim - :members: - :undoc-members: - :show-inheritance: +Use +==== +Example files needed for large-scale Euclid-like simulation runs are included in ``GalSim-Euclid-Like/config``. + +.. include:: ../config/README.rst + diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 0000000..07f898e --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,29 @@ +Examples +========= + +The ``GalSim-Euclid-Like/examples`` directory contains example files for how use the euclidlike module. + +End-to-end demo +--------------- + +`end_to_end_demo.py.py <../examples/end_to_end_demo.py>`_ + +This first demo is the euclidlike-equivalent of `demo 13 `_ in ``GalSim``. This demo uses the Euclid-like PSF, WCS, and background noise to produce a realistic scene of galaxies and stars as observed from a Euclid-like Telescope. + +** Features introduced in the Python file**: + +- euclidlike.getBandpasses(AB_zeropoint) +- euclidlike.getWCS(world_pos, CCDs_CCD, date) +- euclidlike.getPSF(use_CCD, filter_name, wcs) +- euclidlike.getSkyLevel(bandpass, world_pos) + +The output generated from this file can be visualized by running the script `end_to_end_demo.py.py <../examples/end_to_end_demo.py>`_ + + +Focal Plane Layout +------------------ + +`plot_VIS.py <../examples/plot_VIS.py>`_ + +This Jupyter Notebook shows the display of the focal plane used in the euclidlike package, along with the CCD centers and ID convention. + diff --git a/docs/history.rst b/docs/history.rst new file mode 100644 index 0000000..d35e38d --- /dev/null +++ b/docs/history.rst @@ -0,0 +1,11 @@ +Revision History +################ + +.. include:: ../CHANGELOG.rst + + +Older Versions +============== + +.. toctree:: + older \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 55d881e..3f160f3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,63 +1,24 @@ -GalSim-Euclid-Like -================== - -Helper functions to generate simulations of Euclid-like images using GalSim. - -This repository contains information about the Euclid space telescope and survey that is needed to -produce simulations using `GalSim `_. Some of the -information provided is approximate, aimed towards fast simulations rather than full accuracy in -representation of Euclid images. Places where the information is only approximate are flagged and -described in the docstring, and we particularly highlight that the PSF is only approximate; -for details, see the docstring of the ``getPSF()`` method. This library should enable generation of -Euclid-like images of sufficient fidelity for preliminary exploration of object detection, -photometry, deblending, and joint analysis with ground-based observatories. For -applications requiring high precision such as weak lensing, the higher fidelity simulations -available within the Euclid Consortium should be used. - -This repository includes two distinct packages: - -* ``euclidlike``: has basic observatory, instrumentation, and survey information for Euclid. - This package can be used on its own along with GalSim to produce Euclid-like simulations. - -* ``euclidlike_imsim``: has configuration scripts to produce large-scale Euclid-like simulation runs - based on the information in ``euclidlike``. It is based heavily on `roman_imsim `_. - - -References -================== +.. GalSim-Euclid-Like documentation master file + -For more information about `GalSim `_, please see its README and documentation. +GalSim-Euclid-Like: Euclid-like images using GalSim +============================================== -For more information about Euclid, please see the `Euclid Consortium website `_ and papers linked from there. +.. toctree:: + :maxdepth: 2 -Attribution for software and data used by particular routines in this library is given in the docstring for the relevant routine. + overview + install + euclidlike + euclidlike_imsim + examples + history -Installation -================== - -Please view the `installation instructions `_ for details on how to install GalSim-Euclid-Like. - -Downloading relevant data -================== -The Euclid-like PSF is constructed from precomputed oversampled images on a grid in focal plane position and wavelength. To use the full FOV PSF within GalSim-Euclid-Like, the images must be downloaded by running:: - - $ euclidlike_download_psf - -in the terminal after installation of GalSim-Euclid-Like. To install in an alternative directory to the default, use the ``--dir`` argument. Refer to the ``getPSF`` documentation for further details about the PSF. -Getting started -================== -Please see the examples/ directory for demos illustrating the use of this code. - -Communicating with the developers +Indices and tables ================== -Feel free to `open a GitHub issue `_ to reach the developers with questions, comments, and bug reports. New contributors are also welcome and can indicate their interest in developing this code base through the Issues. - -Attribution -================== - -This software is open source and may be used according to the terms of its `license `_. - -When using this software, please provide the URL to the repository in the resulting paper or note. Once there is a Zenodo DOI or journal article, this README will be updated and we will ask those using the code in their research to cite the relevant journal article. +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 0000000..63b62ca --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,4 @@ +Installation +######## + +.. include:: ../INSTALL.rst \ No newline at end of file diff --git a/docs/modules.rst b/docs/modules.rst index 269fdea..dc909a1 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -1,9 +1,6 @@ -GalSim-Euclid-Like -================== - .. toctree:: :maxdepth: 4 euclidlike euclidlike_imsim - scripts + scripts \ No newline at end of file diff --git a/docs/overview.rst b/docs/overview.rst new file mode 100644 index 0000000..803a9ee --- /dev/null +++ b/docs/overview.rst @@ -0,0 +1,4 @@ +Overview +######## + +.. include:: ../README.rst \ No newline at end of file diff --git a/docs/scripts.rst b/docs/scripts.rst index 28a2437..11b271d 100644 --- a/docs/scripts.rst +++ b/docs/scripts.rst @@ -1,6 +1,11 @@ scripts package =============== +.. automodule:: scripts + :members: + :undoc-members: + :show-inheritance: + Submodules ---------- @@ -19,11 +24,3 @@ scripts.make\_euclidlike\_pupil\_plane module :members: :undoc-members: :show-inheritance: - -Module contents ---------------- - -.. automodule:: scripts - :members: - :undoc-members: - :show-inheritance: diff --git a/euclidlike/instrument_params.py b/euclidlike/instrument_params.py index a3fc12a..8371047 100644 --- a/euclidlike/instrument_params.py +++ b/euclidlike/instrument_params.py @@ -136,4 +136,4 @@ # this module. However, pointing errors / jitter are quantified in the VIS paper. # # The impact of the dichroic and of charge transfer inefficiency are not included. Same for -# saturation (200000 e-). +# saturation (200000 e-). \ No newline at end of file
     import galsim
     
     
    -[docs] +[docs] def getSkyLevel(bandpass, world_pos=None, exptime=None, epoch=2025, date=None): """ Get the expected sky level for a Euclid observation due to zodiacal light for this bandpass @@ -121,8 +121,6 @@

    Source code for euclidlike.backgrounds

         return sky_val  
    -
    -[docs] def getZodiBackground(ecl_lat, ecl_dlon, lambda_min, lambda_max, Tlambda, T): """ This helper routine is used with permission from Chris Hirata's Exposure Time Calculator and enables the @@ -258,8 +256,7 @@

    Source code for euclidlike.backgrounds

                 5.03411747e10*lambda_* np.interp(lambda_,Tlambda,T)
     
         # We now have the zodi level in photons/m^2/sr/sec. Convert to photons/m^2/arcsec^2/sec.
    -    return (zodi_tot / 4.2545170296152206e10)
    - + return (zodi_tot / 4.2545170296152206e10)