{ "cells": [ { "cell_type": "markdown", "id": "612ecdf2-d7da-4a1f-87da-ff42d5a7e222", "metadata": {}, "source": [ "# MOSAIC Demo\n", "\n", "This is a simple demo of the \"ETC\" mode for MOSAIC. To use this you need the `oc/mosaic` branch of Scopesim and the `oc/mosaic` branch of the irdb. The implementation creates one-dimensional spectra for the output (summed over the fibres in a bundle for the MOS modes). The first sections demonstrate how to use Scopesim for the MOS and mIFU modes. The final section provides a more detailed description of the implementation and instrument definition that is currently used." ] }, { "cell_type": "code", "execution_count": null, "id": "ade0fcb7-352f-4659-9cf6-abe22b49b8d6", "metadata": {}, "outputs": [], "source": [ "import scopesim as sim\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from astropy import units as u" ] }, { "cell_type": "markdown", "id": "bfda4486-6cf3-407d-b1fe-1f39e9f5ffd4", "metadata": {}, "source": [ "Change the path below to your local irdb copy." ] }, { "cell_type": "code", "execution_count": null, "id": "d273f5c3-bd10-4c54-ac2b-f5722cade6dd", "metadata": {}, "outputs": [], "source": [ "# Edit this path if you have a custom install directory, otherwise comment it out. (For ReadTheDocs only)\n", "sim.link_irdb(\"../../../\")" ] }, { "cell_type": "markdown", "id": "6e726529-9a90-45ac-9af1-0f23c1015743", "metadata": {}, "source": [ "To simulate observations with MOSAIC, the instrument packages for MOSAIC, the ELT, and Armazones are required. The packages are downloaded from the server and installed into sub-directory `inst_pkgs` in the current working directory. If you have not got the packages yet, uncomment the following cell." ] }, { "cell_type": "code", "execution_count": null, "id": "e3a2cc34-18fc-41c9-b1af-ba85bae7df24", "metadata": {}, "outputs": [], "source": [ "#sim.download_packages([\"MOSAIC\", \"ELT\", \"Armazones\"])" ] }, { "cell_type": "markdown", "id": "e288ac3a-4d10-4676-9bfe-76810824043a", "metadata": {}, "source": [ "The following command gives an overview of installed packages used by Scopesim. Please include the output in every bug report or question." ] }, { "cell_type": "code", "execution_count": null, "id": "ea2dfab3-9ada-4854-a387-cfe3dd0dbd3a", "metadata": {}, "outputs": [], "source": [ "sim.bug_report()" ] }, { "cell_type": "markdown", "id": "db5a8af4-1a32-431a-838f-cce1344fb3de", "metadata": {}, "source": [ "## Instrument modes" ] }, { "cell_type": "code", "execution_count": null, "id": "d482facd-efa0-41b5-9cff-5c897e3b1698", "metadata": {}, "outputs": [], "source": [ "cmd = sim.UserCommands(use_instrument=\"MOSAIC\")" ] }, { "cell_type": "code", "execution_count": null, "id": "d63b47ba-6a26-4f09-8ded-1bec7930d949", "metadata": {}, "outputs": [], "source": [ "cmd.modes" ] }, { "cell_type": "markdown", "id": "38063222-20bf-4668-aa31-3183d09a6b75", "metadata": {}, "source": [ "- The visual modes map spectra to a pseudo-detector of length 13000 pixels; the gap between the two 6k detectors in the real instrument is not simulated.\n", "- The near-infrared modes map spectra to a 4k x 4k detector.\n", "- As stated above, the MOS modes collapse the 7 (low-res modes) or 19 (high-res modes) fibres in a bundle to a single one-dimensional spectrum, the output is a FITS binary table with wavelength and flux (in ADU).\n", "- The mIFU modes return a 4k x 4k image with each of the 4xx fibre spectra mapped onto a detector row each. Rearrangement of the spectra into a cube has not been implemented." ] }, { "cell_type": "markdown", "id": "702ed374-0367-4cfe-be42-2305dfecc131", "metadata": {}, "source": [ "## MOS modes\n", "All the MOS modes work identically, and we will only demonstrate the low-resolution R band mode." ] }, { "cell_type": "code", "execution_count": null, "id": "3df6161a-01d3-459c-a148-48241ab340e1", "metadata": {}, "outputs": [], "source": [ "cmd = sim.UserCommands(use_instrument=\"MOSAIC\", set_modes=['MOS-LR-R'])" ] }, { "cell_type": "markdown", "id": "13f81b36-cba5-42c7-9c04-22387e7de69d", "metadata": {}, "source": [ "We shall use an exposure time of 10 seconds throughout. This could be set in the `Usercommands` object (`cmd[\"!OBS.exptime\"]`) but we prefer to set it explicitely in the `readout` commands." ] }, { "cell_type": "code", "execution_count": null, "id": "0aae4148-49e1-4f18-bb29-7f17ee6592dc", "metadata": {}, "outputs": [], "source": [ "t_exp = 10 # seconds" ] }, { "cell_type": "markdown", "id": "1406571f-e35a-4470-8e71-0edca5dda649", "metadata": {}, "source": [ "We can now build the instrument model as an instance of the `OpticalTrain` class." ] }, { "cell_type": "code", "execution_count": null, "id": "ff8a4137-cc1d-461c-b2e7-8d7cfca31d67", "metadata": {}, "outputs": [], "source": [ "mosaic = sim.OpticalTrain(cmd)" ] }, { "cell_type": "markdown", "id": "4a3dd85d-a417-4363-80c9-2061f5453637", "metadata": {}, "source": [ "The following gives an overview of the effects that are included in the optical train. " ] }, { "cell_type": "code", "execution_count": null, "id": "5e6c651b-1b52-4b40-b0c1-e3b36f35489e", "metadata": {}, "outputs": [], "source": [ "mosaic.effects" ] }, { "cell_type": "markdown", "id": "e630c9a8-8499-4c7a-a9ec-e7df735364b4", "metadata": {}, "source": [ "We start by observing blank sky; this will be useful for background subtraction when we observe a source later." ] }, { "cell_type": "code", "execution_count": null, "id": "0f0eae6d-646f-4233-8460-5490fb666f79", "metadata": {}, "outputs": [], "source": [ "mosaic.observe()" ] }, { "cell_type": "markdown", "id": "3c69954d-901f-444b-a3fa-1d4ccd89e927", "metadata": {}, "source": [ "This step creates an `ImagePlane` object, a noise-less image of the detector that records the expected number of electrons per second per pixel. In the current implementation for the visual branch of MOSAIC this is a pseudo-detector with 13000 pixels in the dispersion direction (x-axis), and just enough pixels in the y-direction to hold the 19 fibres of the HR modes (only 7 for LR modes, as in the example). Each fibre is mapped to a single row in the `ImagePlane`. Normally, the `ImagePlane` is not of interest to the user; we save it here for later when we will use to estimate signal-to-noise ratios." ] }, { "cell_type": "code", "execution_count": null, "id": "d0e152b2-10c0-4d08-aa94-2df9c6f274b4", "metadata": {}, "outputs": [], "source": [ "sky_implane = mosaic.image_planes[0].data\n", "print(f\"Size of imageplane: {sky_implane.shape}\")\n", "plt.imshow(sky_implane[:, 2000:3000], origin='lower', vmax=0.1);" ] }, { "cell_type": "markdown", "id": "6870b5cb-da6f-48ab-b841-d1b60400c79c", "metadata": {}, "source": [ "The actual detector \"image\" including dark current, shot noise and readout noise is created in the next step, where we have to specify the exposure time." ] }, { "cell_type": "code", "execution_count": null, "id": "533ee95c-cdac-4638-b600-6b1b2e6a7c80", "metadata": {}, "outputs": [], "source": [ "sky = mosaic.readout(exptime=t_exp)[0]" ] }, { "cell_type": "markdown", "id": "c3b11f15-2d69-460d-bef8-53418d7dfbb8", "metadata": {}, "source": [ "The result is a binary table with columns `wavelength` and `spectrum`:" ] }, { "cell_type": "code", "execution_count": null, "id": "68c08091-93af-4160-a144-9f3667c8589e", "metadata": {}, "outputs": [], "source": [ "sky[1].data" ] }, { "cell_type": "code", "execution_count": null, "id": "7a72913d-5d32-4939-ad1d-e38b431b678d", "metadata": {}, "outputs": [], "source": [ "plt.plot(sky[1].data['wavelength'], sky[1].data['spectrum'])" ] }, { "cell_type": "markdown", "id": "0dad3635-cfef-4150-8a52-ce3c6ee46220", "metadata": {}, "source": [ "As a source, we'll use a star of 15 mag:" ] }, { "cell_type": "code", "execution_count": null, "id": "9ea43e01-9371-491b-8c4e-a67735696f42", "metadata": {}, "outputs": [], "source": [ "src = sim.source.source_templates.star(flux=15 * u.mag)" ] }, { "cell_type": "code", "execution_count": null, "id": "e649ae17-ec87-4614-92d9-56a5c7191c02", "metadata": {}, "outputs": [], "source": [ "mosaic.observe(src)" ] }, { "cell_type": "markdown", "id": "b7fc01d7-1e79-434c-b428-802b2000b3b4", "metadata": {}, "source": [ "Again, we save the `ImagePlane` for later. Note that this contains the expected electron counts (per second) from both the source and the background. We then proceed to create the actual detector readout." ] }, { "cell_type": "code", "execution_count": null, "id": "4bb4d584-04b4-4059-9081-a514eb0ad1e1", "metadata": {}, "outputs": [], "source": [ "star_implane = mosaic.image_planes[0].data" ] }, { "cell_type": "code", "execution_count": null, "id": "8ed08e9a-e06b-4af5-910c-fb4468f117c3", "metadata": {}, "outputs": [], "source": [ "star = mosaic.readout(exptime=t_exp)[0] # same exposure time as for the background simulation" ] }, { "cell_type": "code", "execution_count": null, "id": "80ac5af9-cacb-4f69-9150-663c02df11f0", "metadata": {}, "outputs": [], "source": [ "plt.plot(star[1].data['wavelength'], star[1].data['spectrum'], label=\"raw spectrum\", lw=1)\n", "plt.plot(star[1].data['wavelength'], star[1].data['spectrum'] - sky[1].data['spectrum'], label=\"background subtracted\", lw=1)\n", "plt.plot(sky[1].data['wavelength'], sky[1].data['spectrum'], label=\"background spectrum\", lw=1)\n", "plt.legend()\n", "plt.text(0.656281, 1700, r\"H$\\alpha$\", horizontalalignment=\"center\")\n", "plt.text(0.686719, 1700, r\"O$_2$\", horizontalalignment=\"center\")\n", "plt.text(0.72, 2500, r\"H$_2$O\", horizontalalignment=\"center\")\n", "plt.text(0.759370, 450, r\"O$_2$\", horizontalalignment=\"center\")\n", "plt.text(0.822696, 1300, r\"O$_2$\", horizontalalignment=\"center\")\n", "plt.xlabel(\"Wavelength [um]\")\n", "plt.ylabel(\"Electrons\");" ] }, { "cell_type": "markdown", "id": "4fb502c1-81e5-4731-9ccf-9b0f57bf084f", "metadata": {}, "source": [ "Strictly speaking, the flux units is ADU, but the gain is currently set to 1, so that 1 ADU corresponds to 1 electron collected over the exposure time (60 s).\n", "The spectrum is the sum over the seven fibres (19 for the high-resolution modes), each covering a solid angle of 0.0118 arcsec$^2$. " ] }, { "cell_type": "markdown", "id": "33dbb6ff-c41d-4be5-bb20-a26a91fff215", "metadata": {}, "source": [ "Note that the `mosaic.readout()` method above has been set by the `exptime` keyword, and the exposure is a single readout of that integration time. This is appropriate for the visual modes. The near-infrared modes can also receive a simple `exptime`. In this case, the exposure time is automatically split into `ndit` subexposures of integration time `dit` each (cf. the readout of the mIFU example below). It is also possible to set `dit` and `ndit` directly. " ] }, { "cell_type": "markdown", "id": "94011e79-ad05-4f2c-a82b-66f9ea3b19c0", "metadata": {}, "source": [ "## Signal-to-noise estimation from the simulated data\n", "Scopesim does not have a built-in function to compute a signal-to-noise ratio for the simulation. Using the simulations for the background and star+background, it can be easily estimated. " ] }, { "cell_type": "markdown", "id": "dc80b6a1-4305-4f13-af36-d1da5073cfb9", "metadata": {}, "source": [ "To start with we have to convert the spectra from ADU to electrons by multiplying by the gain (in the visual mode, this is currently set to 1; in the near-infrared it is set to 2.5 from our previous experience with HxRG detectors)." ] }, { "cell_type": "code", "execution_count": null, "id": "8e366cb3-4e47-4a3e-b6be-dc0322cdd10e", "metadata": {}, "outputs": [], "source": [ "gain = mosaic.cmds[\"!DET.gain\"]\n", "print(f\"Gain: {gain}\")" ] }, { "cell_type": "code", "execution_count": null, "id": "103ef8f4-5a9d-48fd-8eac-7931a5cdbf6f", "metadata": {}, "outputs": [], "source": [ "noise = np.sqrt(star[1].data['spectrum'] / gain)\n", "signal = (star[1].data['spectrum'] - sky[1].data['spectrum'])/ gain\n", "SNR_emp = signal/noise" ] }, { "cell_type": "code", "execution_count": null, "id": "cbac25c6-11a5-4e7e-8953-5d9cfe586962", "metadata": {}, "outputs": [], "source": [ "plt.plot(star[1].data['wavelength'], SNR_emp)\n", "plt.ylim(0, 80)\n", "plt.xlabel(\"Wavelength [um]\")\n", "plt.ylabel(\"Signal-to-noise ration\")\n", "plt.title(\"Empirical signal-to-noise ratio\");" ] }, { "cell_type": "markdown", "id": "d9d180bd-a5ce-461f-bfc6-8ead334cd36d", "metadata": {}, "source": [ "## Signal-to-noise ration determination from expected values\n", "We can also break down the noise into its constituent components as they are currently implemented in Scopesim. For the signal and the Poisson noise due to source and background we go back to the expected values that are provided in the `ImagePlane` of the respective simulations. We use the following prescription for the SNR computation ([ELT Spectroscopy ETC document](https://www.eso.org/observing/etc/doc/elt/etc_spec_model.pdf)): \n", "$$\n", "\\frac{S}{N} = \\frac{\\sqrt{n_\\mathrm{exp}}\\cdot N_\\mathrm{obj}}{\\sqrt{N_\\mathrm{obj} + N_\\mathrm{sky} + n_\\mathrm{pix} R^2 + n_\\mathrm{pix} D t_\\mathrm{exp}}}\n", "$$\n", "For the electron numbers $N_\\mathrm{obj}$ and $N_\\mathrm{sky}$ from the source and the background, respectively, we recur to the `ImagePlane`s that we saved earlier. These give the expected number of electrons per second per pixels." ] }, { "cell_type": "code", "execution_count": null, "id": "bac4c598-434e-4ca6-ac01-55b771faba7f", "metadata": {}, "outputs": [], "source": [ "N_obj = (star_implane - sky_implane).sum(axis=0) * t_exp # sum over all fibres (non-fibre rows are zero, so summing over y-axis is fine)\n", "N_sky = sky_implane.sum(axis=0) * t_exp" ] }, { "cell_type": "markdown", "id": "edada196-0331-4dcb-bd12-5a0129356bd7", "metadata": {}, "source": [ "Scopesim uses $R=7$ electrons and $D=0.005$ electrons per second. These values were taken from E-MOS-SYS-ANR-0063-2_0, where they are given as $R\\approx 2.5$ electrons and $D=3$ electrons per hour, respectively. Our adopted values take into account that each row in the `ImagePlane` is the sum over a fibre, which we take to be around 6 pixels wide in a (real) detector image ($D$ scales linearly with that number, while $R$ scales with its square root). In the formula above $n_\\mathrm{pix}$ corresponds to the number of fibres that have been summed over, which is 7 in our case. The number of exposures is $n_\\mathrm{exp} = 1$ in the visual." ] }, { "cell_type": "code", "execution_count": null, "id": "cac86d14-b567-43ac-861e-52c126abbfc6", "metadata": {}, "outputs": [], "source": [ "rdnoise = mosaic.cmds[\"!DET.readout_noise\"]\n", "dark = mosaic.cmds[\"!DET.dark_current\"]\n", "print(f\"Readout noise: {rdnoise} electrons\")\n", "print(f\"Dark current: {dark} electrons/second\")" ] }, { "cell_type": "code", "execution_count": null, "id": "a1971fa9-d724-487a-b8b6-d673e3979c2c", "metadata": {}, "outputs": [], "source": [ "SNR_exp = N_obj / np.sqrt(N_obj + N_sky + 7 * rdnoise**2 + 7 * dark * t_exp)" ] }, { "cell_type": "code", "execution_count": null, "id": "a56d18b0-7b85-4ec0-ac75-13ef5a6c906d", "metadata": {}, "outputs": [], "source": [ "plt.plot(star[1].data['wavelength'], SNR_exp)\n", "plt.xlabel(\"Wavelength [um]\")\n", "plt.ylabel(\"Signal-to-noise ration\")\n", "plt.title(\"Expected signal-to-noise ratio\")\n", "plt.ylim(0, 80);" ] }, { "cell_type": "markdown", "id": "5edcad41-9ab7-4acb-a20a-d5c613f83064", "metadata": {}, "source": [ "## Using a galaxy as a source\n", "The `scopesim_templates` package includes models for a variety of astronomical source. We will use it to simulate an observation of an elliptical galaxy at some redshift." ] }, { "cell_type": "code", "execution_count": null, "id": "5d027a0b-2f2f-4386-876b-0a1e362472d4", "metadata": {}, "outputs": [], "source": [ "import scopesim_templates as sim_tp" ] }, { "cell_type": "code", "execution_count": null, "id": "02764a5e-ee9d-43e2-b0ad-e995e0698974", "metadata": {}, "outputs": [], "source": [ "gal = sim_tp.extragalactic.galaxy(\"kc96/elliptical\", z=0.1, amplitude=15, filter_curve=\"g\", pixel_scale=0.01, r_eff=0.3, \n", " n=4, ellip=0.5, theta=45, extend=3)" ] }, { "cell_type": "code", "execution_count": null, "id": "43dc0b6d-faef-499f-8d63-625bf29362bd", "metadata": {}, "outputs": [], "source": [ "plt.imshow(gal.fields[0].data, origin=\"lower\", norm=\"log\")" ] }, { "cell_type": "code", "execution_count": null, "id": "04eff4a6-e1f0-4b15-8e0d-bdd07b435b3a", "metadata": {}, "outputs": [], "source": [ "gal.fields[0].header" ] }, { "cell_type": "code", "execution_count": null, "id": "01565313-f413-4a5f-bc16-394fd7d83f50", "metadata": {}, "outputs": [], "source": [ "cmd_b = sim.UserCommands(use_instrument=\"MOSAIC\", set_modes=[\"MOS-LR-B\"])\n", "mosaic_b = sim.OpticalTrain(cmd_b)" ] }, { "cell_type": "code", "execution_count": null, "id": "7c6ed987-2d28-4408-82c5-cf93a7b7de87", "metadata": {}, "outputs": [], "source": [ "mosaic_b.observe(gal)" ] }, { "cell_type": "code", "execution_count": null, "id": "8662f382-f263-4717-8891-c1d9783f48fb", "metadata": {}, "outputs": [], "source": [ "galobs = mosaic_b.readout(exptime=t_exp)[0]" ] }, { "cell_type": "code", "execution_count": null, "id": "4f3b4a1e-9f30-4612-8dbb-e66bb7cc7288", "metadata": {}, "outputs": [], "source": [ "plt.plot(galobs[1].data['wavelength'], galobs[1].data['spectrum'], label=\"galaxy\")\n", "plt.plot(star[1].data['wavelength'], star[1].data['spectrum'] - sky[1].data['spectrum'], label=\"star\")\n", "plt.xlabel(\"Wavelength [um]\")\n", "plt.legend();" ] }, { "cell_type": "markdown", "id": "b612c2b2-ad88-445e-bd1f-f2bf93a251cc", "metadata": {}, "source": [ "## mIFU modes" ] }, { "cell_type": "code", "execution_count": null, "id": "59a4a82b-3fc0-47a3-90c2-345e21330902", "metadata": {}, "outputs": [], "source": [ "cmd = sim.UserCommands(use_instrument=\"MOSAIC\", set_modes=[\"mIFU-LR-J\"])" ] }, { "cell_type": "code", "execution_count": null, "id": "fc86a53d-1a51-4007-9990-fbf5d9c03729", "metadata": {}, "outputs": [], "source": [ "mosaic = sim.OpticalTrain(cmd)" ] }, { "cell_type": "code", "execution_count": null, "id": "31260e7f-d10c-47e3-8891-1cbaa2c4e867", "metadata": {}, "outputs": [], "source": [ "mosaic.observe()" ] }, { "cell_type": "code", "execution_count": null, "id": "be7b9f59-d8a6-4484-ac34-6ec28abee553", "metadata": {}, "outputs": [], "source": [ "hdul = mosaic.readout(exptime=3600)[0]" ] }, { "cell_type": "code", "execution_count": null, "id": "d4d3e953-795f-4c24-99d6-d5aa549a6bf2", "metadata": {}, "outputs": [], "source": [ "plt.imshow(hdul[1].data[900:1100, 1900:2100], norm='log', origin='lower')\n", "plt.colorbar();" ] }, { "cell_type": "code", "execution_count": null, "id": "4c5b7377-c23d-4056-8148-d039072f412e", "metadata": {}, "outputs": [], "source": [ "plt.plot(hdul[1].data[991, :])" ] }, { "cell_type": "markdown", "id": "f25addbb-0578-4ced-964d-f0560a41a963", "metadata": {}, "source": [ "The mIFU mode is incomplete - it is currently not possible to deduce the wavelength vector and the spatial arrangement of the fibres from the readout alone. A table format might be better suited for that purpose." ] }, { "attachments": {}, "cell_type": "markdown", "id": "12f2011d-11b2-4680-9f41-4686637e2472", "metadata": {}, "source": [ "## Instrument package\n", "In this section we describe how the instrument is defined for Scopesim and what data files and parameters are used. The instrument configuration is found in `irdb/MOSAIC` (a release package will be provided once the code and configuration has been validated). The main file is `default.yaml` where in particular the available instrument modes are defined (see above for a list of these modes). The `OpticalTrain`, i.e. the software representation of the entire system of atmosphere, telescope, instrument optics and detector, is built as a series of `Effect` objects, which are set along with relevant parameters in further `yaml` files, as appropriate for each instrument mode. \n", "All modes use the additional `Armazones` and `ELT` packages:\n", "- `irdb/Armazones/Armazones.yaml` sets a single effect, `skycalc_atmosphere`, which provides atmospheric transmission and emission spectra as taken from ESO's skycalc server. The two parameters `spectral_resolution` and `spectral_bin_width` have been carefully chosen for each mode and should not be changed (unless for experimental purposes).\n", "- `irdb/ELT/ELT.yaml` defines `telescope_reflection`, which provides reflectivity and thermal emission from the telescope mirrors. The parameter `!TEL.ter_curve.filename` is by default set to `TER_ELT_5_mirror.dat`. The irdb contains files for 5- and 6-mirror configurations (the latter including a flat mirror to deflect light to a side port), the latter with exposed (field-tracking) or hidden (pupil-tracking) telescope spiders, and for clean and not so clean mirror segments.\n", "\n", " \n", " \n", "\n", "The instrument is split into a visual and a near-infrared arm, described by `MOSAIC_VIS.yaml` and `MOSAIC_NIR.yaml`, respectively. \n", "- The transmission of the visual arm is given as a single combined `system transmission` effect, which uses the file named in the parameter \"!OBS.ter_file\" (TER = transmission, emission, reflection). For the near-infrared arm, the transmission is split into `fibre transmission` and `spectrograph transmission` (parameters `!OBS.fibre_ter_file` and `!OBS.spec_ter_file`). The fibre transmission files are named `TER_mos_*` to distinguish them from the IFU fibres, `TER_mIFU_*`. The available data are rather crude at present.\n", "\n", " \n", " \n", "\n", "- The point-spread function (effect `psf`) is currently taken to be a `SeeingPSF`, with FWHM settable via `!OBS.psf_fwhm`. This parameter is currently set to a default of 0.2 arcsec for all modes, probably not always a good value.\n", "- The line-spread function (effect `lsf`) is a convolution of a top-hat of width 4.5 spectral bins in the visual and 2.75 spectral bins in the near-infrared (the effect parameter `lsfwidth` is not currently user-settable, except by editing the yaml file; this should change in the future) with a Gaussian with standard deviation of 1 spectral bin. A spectral bin is given by the dispersion (um per pixel) on the detector.\n", "- The `fibre_bundle` effect determines the outline of the fibre bundle on the sky, and the `spectral_traces` effect is responsible for mapping the spectra into the two-dimensional `ImagePlane` (i.e. the detector focal plane). Both effects use the same trace file. Trace files are available for all instrument modes as multi-extension FITS files. The spatial arrangement of the fibres in a bundle is given as a table in the second extension of the file. Note that the fibre apertures are modelled as squares rather than hexagons (this makes it easier to sample the source cube); of course the squares cover the same solid angle on sky as the hexagons.\n", "\n", " \n", " \n", "\n", "The remaining traces map the spectra into the detector. This is done in a strictly linear manner, i.e. with constant dispersion (different for each mode). Each fibre is mapped as a one-dimensional spectrum onto a single row of the `ImagePlane`. \n", "\n", "The `ImagePlane` is produced by the `mosaic.observe()` command and is an image of the expected flux in photon/s in the detector plane, without noise. It is accessible by `mosaic.image_plane.hdu`.\n", "\n", "The `mosaic.readout()` command subsequently invokes the detector configuration to create a noisy detector readout from the `ImagePlane`. The detectors are defined in `MOSAIC_DET_VIS.yaml` and `MOSAIC_DET_NIR.yaml`, respectively. The geometric layout of the detectors is given by the effect `detector_array`, which reads `FPA_mosaic_VIS_layout.dat` and `FPA_mosaic_NIR_layout.dat`, respectively. The visual detector is currently described as a single 13000 x 160 array rather than the four 6k x 6k detectors foreseen for the actual instrument (hence the \"s(i)mpl(e)\" in the yaml file name) . This is because Scopesim only simulates a single fibre bundle, so a narrow effective detector is sufficient. Masking the gap between the two detectors is left to the user. The NIR detector is modeled as a single 4k x 4k detector (as in the actual instrument) to have enough room for the mIFU mode. \n", "\n", "The QE is handled by the effect `quantum_efficiency`, which uses the files `QE_VIS_ML2_depleted.dat` and `QE_detector_NIR.dat`, respectively.\n", "\n", " \n", "\n", "Finally, both detector yamls include the effect `collapse_1d`, which sums up the separate spectra from the fibres and produces a single output spectrum as described above. It is possible to switch this off with `mosaic['collapse_1d'].include=False` to see the \"detector image\". However, due to the way the spectra are currently formed, this is probably not of much interest." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.5" } }, "nbformat": 4, "nbformat_minor": 5 }