This notebook gives a brief overview of the practical aspects of SimCADO that you may find useful.
Topics include:
Installing SimCADO is easy:
$ pip3 install --user http://www.univie.ac.at/simcado/SimCADO.zip
Note: The --user
command is useful if you do not have write permissions for the normal python install folder. If you have full access, then it can be ignored.
Once in python, SimCADO can be imported like any other package
import simcado
SimCADO has several modules which contain the classes and functions that you will use. They will ont be described in detail here. This is just to make sure you know they exist.
from simcado import source, commands, utils, optics
If you want to know where simcado is installed, and where the data files that SimCADO uses are located, the utils
package contains the variable __pkg_dir__
. This is helpful when you want to view the data outside of a python session.
simcado.utils.__pkg_dir__
'C:\\Program Files\\Anaconda3\\lib\\site-packages\\simcado'
Quite often we will update the data files used by SimCADO. This doesn't require a full re-install of the package. SimCADO will download new files from the SimCADO website by calling get_extras()
.
Note this requires that the Python package wget
is installed on your system and that you have write permission for the folder where SimCADO is installed. If not, try reinstalling SimCADO with the --user
parameter.
simcado.get_extras()
100% [..................................................................................] 984 / 984 Downloading: default.config Version: 20170118a Size: 12KB 100% [..............................................................................] 11436 / 11436 PSF_POPPY.fits is already the latest version: 20161103a PSF_LTAO.fits is already the latest version: 20161108a PSF_MCAO.fits is already the latest version: 20161110a PSF_SCAO.fits is already the latest version: 20161115b FPA_nirspec_pca0.fits is already the latest version: 20161108a FPA_noise.fits is already the latest version: 20161108a TC_surface.dat is already the latest version: 20161122a TC_mirror_gold.dat is already the latest version: 20161122a TC_aluminium.dat is already the latest version: 20161215a TC_filter_J.dat is already the latest version: 20170105a TC_filter_H.dat is already the latest version: 20170105a TC_filter_Ks.dat is already the latest version: 20170105a TC_filter_Y.dat is already the latest version: 20170105a FPA_chip_layout.dat is already the latest version: 20170105a Downloading: TC_mirror_EELT.dat Version: 20170118a Size: 1KB 100% [..................................................................................] 469 / 469 Finished downloading data for SimCADO
Creating noise frames for the H4RG detectors is time consuming, so SimCADO randomly samples from a cube of noise frames. The default installation comes with a cube with 1 layer. Therefore it is recommended to generate more frames when first running SimCADO.
Note: the 3rd party python package for this only works on Python 3
simcado.install_noise_cube(n=9) # Generate n noise frames.
Run a simulation by calling simcado.run(src=)
. For this you will need a Source
object. These described in the other tutorial notebooks. You can create your own Source
object or use one of the helper functions in the module simcado.source
.
my_star = simcado.source.star(mag=20, filter_name="Ks", spec_type="G2V")
simcado.run(src=my_star)
Detector layout id x_cen y_cen x_len y_len gain --- ----- ----- ----- ----- ---- 0 0 0 1024 1024 1.7 Creating 1 layer(s) per chip 1 chip(s) will be simulated Reading out chip 0
[<astropy.io.fits.hdu.image.PrimaryHDU at 0x297a7f839e8>]
If no filename=
is given, the detector read-outs are returned to the console. If filename=
is set, SimCADO saves the read-out images to disk
simcado.run(src=the_sun, filename="test.fits")
The function simcado.run()
has some useful functionality built into it. Let take a look at the function definition:
simcado.run(src, filename=None,
mode="wide", detector_layout="small",
cmds=None, opt_train=None, fpa=None,
return_internals=False,
**kwargs)
Two important parameters here are mode
and detector_layout
: These two define the MICADO observing modes.
Currently mode
can be either ="wide"
(4mas/pixel) or ="zoom"
(1.5mas/pixel).
The detector_layout
can also be changed to speed up simulations of single objects. For example if the galaxy you're interested in is at z=5, you don't need to read out all 9 MICADO chips for each observation. In fact, a 1024x1024 window at the centre of the middle chip will probably be enough. Therefore SimCADO offers the following "layouts" for the detector - "small", "wide", "full". The default is "small".
small
- 1x 1k-detector centred in the FoVcentre
- 1x 4k-detector centred in the FoVfull
- 9x 4k-detector as described by the keyword FPA_CHIP_LAYOUTKwargs stands for keyword arguments, meaning any keyword-value pair from the list of SimCADO parameters. These will be discussed in the section Customising a simulation. Suffice to say, any keyword-value pair which controls an aspect of SimCADO can be passed as an extra parameter to simcado.run
.
For those who want more control over how a simulation is run. A simulation consists of three main steps:
UserCommands
list, an OpticalTrain
and a Detector
,Source
through the OpticalTrain
onto the Detector
, andDetector
For more information on each of these object, please see the online documentation.
The first step of a simulation chain looks like this: all the information needed for the simulation is held in the UserCommands
object. This is then use to set up the OpticalTrain
and the Detector
cmd = simcado.UserCommands()
opt = simcado.OpticalTrain(cmd)
fpa = simcado.Detector(cmd)
Safety switch is on - Detector(..., small_fov='True')
The second step involves calling the apply_optical_train()
method in the Source
object that we have already created. This propogates the light sources from the Source
object through the optical train and creates an image on the detector focal plane. Hence the method requires both objects as parameters:
my_star.apply_optical_train(opt_train=opt, detector=fpa)
After calling apply_optical_train()
the chips in the detector object are now full of photons. We can check this:
fpa.chips[0].array
array([[ 20.11373939, 20.11373939, 20.11373939, ..., 20.11373939, 20.11373939, 20.11373939], [ 20.11373939, 20.11375038, 20.11375067, ..., 20.11375138, 20.11375212, 20.11375045], [ 20.11373939, 20.11374998, 20.11375045, ..., 20.11375115, 20.11375148, 20.11375006], ..., [ 20.11373939, 20.11374998, 20.11374987, ..., 20.11374868, 20.11374851, 20.11374866], [ 20.11373939, 20.11374757, 20.1137475 , ..., 20.1137499 , 20.11374938, 20.1137492 ], [ 20.11373939, 20.11374791, 20.11374653, ..., 20.11375087, 20.11375036, 20.1137504 ]])
What we have here is the expected flux per pixel on the detector, i.e. total photons per second that will be arriving at each pixel. These values also include photons coming from non-astronomical sources, e.g. the thermal emission from the atmosphere and the mirror.
The final step is to read out the detector, either into a fits file or back to the user in the form of an astropy FITS object:
fpa.read_out(filename="test.fits")
Reading out chip 0
[<astropy.io.fits.hdu.image.PrimaryHDU at 0x297a7f83588>]
In Summary, the sequence of events behind a full simulation, i.e. what happens in simcado.run()
, looks like this
import simcado
# create a 1000 Msun cluster in the LMC
src = simcado.source.cluster(mass=1000, distance=50000, half_light_radius=4)
# create the simulation commands, optical train and detector
cmd = simcado.UserCommands()
opt = simcado.OpticalTrain(cmd)
fpa = simcado.Detector(cmd)
# observe the source - get the expected ph/s/pixel rate
my_star.apply_optical_train(opt_train=opt, detector=fpa)
# read the final image out to disk
fpa.read_out(filename="test.fits")