Welcome to LIFEsim’s documentation!
LIFEsim is the simulator software for the Large Interferometer For Exoplanets (LIFE). It simulates the interferometric measurement of LIFE to demonstrate the capabilities of the observatory. Coupled with on-sky source simulations, LIFEsim will infer the amount and diversity of exoplanets observable with LIFE. Inputting spectral information of exoplanets allows for a description of the spectral measurement potential of LIFE.
For more information, please visit the LIFE Website.

Installation (Linux and Mac OS)
LIFEsim is available for installation from Github. It is compatible with Python 3.8.
Hint
Installation on Mac OS
We recommend the usage of a package manager for mac (e.g. Miniconda). Follow the installation instruction given by the respective package manager, making sure that you use the correct version of python (3.8).
Open a terminal window and activate conda by running
$ conda activate
Virtual Environment
It is highly recommended to install LIFEsim in a virtual environment. This ensures installed packages and changes made do not affect other projects on a system. The package dependencies of LIFEsim are best managed with a package manager like pip.
As a first step, virtualenv is installed with pip
$ pip install virtualenv
Then a virtual environment in the folder new_folder
is created in the current directory
$ virtualenv -p python3.8 new_folder
Hint
You might need to deactivate the conda base
$ conda deactivate
To activate and deactivate your new virtual environment use the following statement respectively
$ source path_to_new_folder/new_folder/bin/activate
Check that you are using the correct python version.
$ python --version
Python 3.8.X
$ deactivate
Download from PyPI (Recommended)
First, activate the virtual environment as shown above. LIFEsim can be installed from PyPI using the pip command.
$ pip install lifesim
LIFEsim need a modified version of the package SpectRes to run. It can also be installed using pip. Run
$ pip install git+https://github.com/fdannert/SpectRes.git
Download from Github
Navigate to the directory in which you desire to place the LIFEsim repository. Then clone the repository from Github by executing
$ git clone https://github.com/fdannert/LIFEsim.git
Hint
If git
is not installed on your system run
$ sudo apt install git
The dependencies required by LIFEsim can be installed with
$ pip install -r LIFEsim/requirements.txt
To upgrade already installed dependencies to LIFEsim requirements run
$ pip install --upgrade -r LIFEsim/requirements.txt
Important
LIFEsim need a modified version of the package SpectRes to run. Please install it via the following procedure.
First, make sure that you are in the directory where you want to install SpectRes. Then run
$ git clone https://github.com/fdannert/SpectRes.git
The last step is point the Python install of your virtual environment to LIFEsim and SpectRes. Please do so by running
$ echo "export PYTHONPATH='$PYTHONPATH:/path_to_LIFEsim/LIFEsim/:/path_to_SpectRes/SpectRes/'" >> path_to_new_folder/new_folder/bin/activate
Testing the Installation
To test the installation, open a new console and activate the virtual environment as above. Then open Python and import LIFEsim with
$ python
>>> import lifesim
If the import statement executes, the installation has been successful. As an extra test run
>>> lifesim.util.constants.c
299792000.0
This should return the speed of light in [m s \(^{-1}\) ].
Hint
If the import lifesim
command fails, the reason is likely that the the PYTHONPATH
is not set correctly. To check for this please run in Python (started with the virtual
environment active as above)
>>> import sys
>>> sys.path
If the path to LIFEsim '/path_to_LIFEsim/LIFEsim/'
is not returned in the results, please
open the file path_to_new_folder/new_folder/bin/activate
with a text editor of your choice.
Then make sure that the last line of the file reads
export PYTHONPATH=':/path_to_LIFEsim/LIFEsim/'
The same test can be performed if SpectRes does not import.
Installation (Windows)
Download Conda
Hint
This step can be skipped if a python distribution and package manager is already installed.
First, a python distribution and package manager is required. For windows, we suggest Miniconda, a lightweight variant of the popular Anaconda distribution. To install Miniconda, follow the installation instructions.
Virtual Environment
It is highly recommended to install LIFEsim in a virtual environment. This ensures installed packages and changes made do not affect other projects on a system. The steps of creating a virtual environment with conda are described in the following.
First, open the Conda Prompt, navigate to where you want to create the virtual environment and type
> conda create --name new_folder python=3.8
Note that we specify the required python version in this command. Some conda commands will ask for confirmation, which can be affirmed by typing.
Proceed ([y]/n)?
> y
A virtual environment in the folder new_folder
is created in the current directory
Hint
You might need to deactivate the conda base
> conda deactivate
To activate and deactivate your new virtual environment use the following commands respectively
> conda activate new_folder\
Check the python version with the following command
> python --version
> conda deactivate
Download from PyPI (Recommended)
Hint
You will likely need to install git first
> conda install git
With the new environment activated, install LIFEsim via pip.
> pip install LIFEsim
LIFEsim need a modified version of the package SpectRes to run. It can also be installed using pip. Run
> pip install git+https://github.com/fdannert/SpectRes.git
Download from Github
Navigate to the directory in which you desire to place the LIFEsim repository. Then clone the repository from Github by executing
> git clone https://github.com/fdannert/LIFEsim.git
Hint
If git
is not installed on your system run
> conda install git
The dependencies required by LIFEsim can be installed with
> conda install --file requirements.txt
Important
LIFEsim need a modified version of the package SpectRes to run. Please install it via the following procedure.
First, make sure that you are in the directory where you want to install SpectRes. Then run
> git clone https://github.com/fdannert/SpectRes.git
The last step is point the Python install of your virtual environment to LIFEsim and SpectRes.
To do so, please navigate to site-packages
folder of your virtual environment, most likely
located in `` C:Usersuser_nameminiconda3envsnew_folderLibsite-packages``. In this directory,
create the file lifesim.pth
containing the paths to LIFEsim and SpectRes separated by a new
line
C:\path_to_LIFEsim\LIFEsim\
C:\path_to_SpectRes\SpectRes\
Testing the Installation
To test the installation, open a new conda prompt and activate the virtual environment as above. Then open Python and import LIFEsim with
> python
>>> import lifesim
If the import statement executes, the installation has been successful. As an extra test run
>>> lifesim.util.constants.c
299792000.0
This should return the speed of light in [m s \(^{-1}\) ].
Hint
If the import lifesim
command fails, the reason is likely that the the PYTHONPATH
is not set correctly. To check for this please run in Python (started with the virtual
environment active as above)
>>> import sys
>>> sys.path
If the path to LIFEsim 'C:\path_to_LIFEsim\LIFEsim\'
is not returned this is likely the
source of the issue.
The same test can be performed if SpectRes does not import.
First Examples
The following examples will explore the current two main functionalities of LIFEsim: The simulation of single exoplanets with a given spectrum and the simulation of the LIFE search phase on a catalog of a simulated exoplanets populated.
Using the GUI
The following is a minimal working example of simulating a spectral observation of an exoplanet with the LIFEsim GUI.
As a first step, activate the virtual environment containing the LIFEsim install with
$ source path_to_new_folder/new_folder/bin/activate
Open python
$ python
Then, open the LIFEsim spectrum simulator GUI by running
>>> from lifesim import Gui
>>> Gui()
With executing this command, the following GUI will open

Notice the three tabs for setting the instrument options, importing and previewing the spectrum and displaying the results. In the Settings tab, the required parameters for the target star and planet can be set manually. The parameters for the instrument can either be set manually or by pressing on a scenario button on the left side (e.g. Optimistic). This then automatically sets the instruments parameters to correspond with what the LIFE team currently views as an optimistic, baseline or pessimistic scenario.
For importing a spectrum, navigate to the Preview tab.

Begin by choosing a spectrum to import (in .txt format) by clicking on Browse…. To complete this example, please download this file from the LIFEsim GitHub and open it in the pop-up dialog. Leave the option as absolute to only use the imported spectrum. Setting the option to additive will add the imported spectrum to the planets black body spectrum calculated according to given parameters.
Hint
A pure black body planet can be simulated by choosing the additive option and leaving the file dialog empty.

To specify the units of the spectrum you are importing, enter them in the fields x-axis units and
y-axis units. For this example, please set x-axis units to micron
and y-axis units to
photon micron-1 s-1 m-2 sr-1
.
In the Spectrum Parameter field the parameters used during the creation of the spectrum need to
be given. Again, for the example please set Distance to 10pc
, Planet Radius to 1 Earth
Radius
and leave Integration Time at 0.
Pressing Preview Spectrum will now show the spectrum in the units specified by the user. This can be used to check the correct import of the spectrum.

Changing the drop-down menu to converted units will show the spectrum in the units used in LIFEsim. This completes setting up the simulator for a run.
Change to the Results tab and press Run Simulation on the very left. This will run the simulation and the display the results as shown below.

Above the Run Simulation button you can change the Integration Time of the simulation and select or deselect the inclusion of specific noise sources in the simulation.
At the bottom of the Results tab you can choose a location to save the results at by clicking on Browse… and then save the results by clicking Save.
Simulating the Search Phase
LIFEsim is capable of taking an artificial exoplanet catalog input from P-Pop, calculate the signal-to-noise ratio for each planet and distribute the observation time available in the search phase to observe and detect an optimal number of exoplanets.
Hint
The following example mirrors the file LIFEsim/lifesim_demo.py
.
Set-Up
To run such a simulation, create a new python file. First, LIFEsim needs to imported
3import lifesim
LIFEsim is programmed such that all data and parameters are saved in a single location, which then
distributes those to the relevant modules. Create an instance of this so-called bus
8bus = lifesim.Bus()
The bus holds all parameters needed for the simulation (e.g. the collector aperture diameter, the duration of the search phase, etc.). They can all be set at the same time by using scenarios predefined by the LIFE team. These scenarios are the ‘baseline’ case, where the array configuration is as expected, as well as the ‘optimistic’ and ‘pessimistic’ case, where the array is set up in a more or less capable way. Set the parameters to the baseline case by running
11bus.data.options.set_scenario('baseline')
Note, that options can also be set manually. For example, the collector aperture diameter can be manually increased to four meters by
14bus.data.options.set_manual(diameter=4.)
A list of all available options and parameters can be found in the API Documentation for lifesim.util.options.
Downloading the Catalog
A example synthetic planet population based on statistics from the Kepler mission can be downloaded from the P-Pop github page with the following code. Make sure to replace the path with your local project folder.
18data = requests.get('https://raw.githubusercontent.com/kammerje/P-pop/main/TestPlanetPopulation.txt')
19
20with open('path/ppop_catalog.txt', 'wb') as file:
21 file.write(data.content)
Loading the Catalog
Now, the P-Pop catalog can be loaded in. An example catalog can be found in
LIFEsim/docs/_static
. Run
25bus.data.catalog_from_ppop(input_path='path/ppop_catalog.txt')
Important
The given P-Pop catalog populates known stars in the solar neighborhood of up to 20 pc with artificial planets based on the Kepler statistics. This population is done not only once, but in a Monte Carlo approach 500 different universes are simulated. This needs to be kept in mind when the results are interpreted.
With the catalog loaded into LIFEsim, some selections of stars can be removed. The following will remove all A-type stars and every M-type at a distance larger than 10 pc away from earth.
26bus.data.catalog_remove_distance(stype=0, mode='larger', dist=0.)
27bus.data.catalog_remove_distance(stype=4, mode='larger', dist=10.)
Hint
LIFEsim uses the following numeric integer keys for stellar types:
0 = A, 1 = F, 2 = G, 3 = K, 4 = M.
With this, the setup for the simulation is complete.
Creating the Instrument
Now, an instance of the LIFEsim instrument module needs to be created.
33instrument = lifesim.Instrument(name='inst')
To give any module access to the data and parameters used in a simulation, it needs to be connected to the bus.
34bus.add_module(instrument)
Next, all modules needed for the instrument module to run need to be created. A list of the required modules can be found in the API Documentation of lifesim.instrument.instrument. First, create the module responsible for simulating transmission maps of a four-arm nulling interferometer and add it to the bus.
36transm = lifesim.TransmissionMap(name='transm')
37bus.add_module(transm)
Next, create the modules for the simulation of the astrophysical noise sources and add them to the bus.
39exozodi = lifesim.PhotonNoiseExozodi(name='exo')
40bus.add_module(exozodi)
41localzodi = lifesim.PhotonNoiseLocalzodi(name='local')
42bus.add_module(localzodi)
43star_leak = lifesim.PhotonNoiseStar(name='star')
44bus.add_module(star_leak)
Now, the instrument needs to be told to which modules it should connect to. Do so by running
47bus.connect(('inst', 'transm'))
48bus.connect(('inst', 'exo'))
49bus.connect(('inst', 'local'))
50bus.connect(('inst', 'star'))
51
52bus.connect(('star', 'transm'))
Note, that not all noise sources need to be connected in order for the instrument simulation to run. If required, individual noise sources can be disconnected by running
>>> bus.disconnect(('inst', 'exo'))
Creating the Optimizer
The optimizer is responsible for distributing the available observing time onto the individual stars. Analogously to above, run
59opt = lifesim.Optimizer(name='opt')
60bus.add_module(opt)
61ahgs = lifesim.AhgsModule(name='ahgs')
62bus.add_module(ahgs)
63
64bus.connect(('transm', 'opt'))
65bus.connect(('inst', 'opt'))
66bus.connect(('opt', 'ahgs'))
Running the Simulation
First, the signal-to-noise ratio needs to be calculated for every planet in the catalog. To do so, run
73instrument.get_snr()
This function will assign every planet the SNR after one hour of observation. Since the simulation is entirely contained in the radom noise case, the SNR scales with square-root of the integration time. Therefore, the SNR for any integration time can be calculated by knowing the SNR of a specific integration time.
Note
It is not unusual for instrument.get_snr()
to take up to an hour to complete.
Knowing the SNR for each planet, the integration time can be optimally distributed by
75opt.ahgs()
In the baseline case, the observation time is distributed such that the number of planets in the habitable zone around their respective host stars is optimized. The optimization can be changed to respect all planets by setting
>>> bus.data.options.optimization['habitable'] = True
Check the API Documentation for lifesim.util.options to see all parameters used in the optimization process.
Saving the Results
After a simulation run, the results can be saved as a hdf5 file for later analysis by using
79bus.data.export_catalog(output_path='path/filename.hdf5')
Reading the Results
A previously saved simulation can be read into LIFEsim by running
84bus_read = lifesim.Bus()
85bus_read.data.options.set_scenario('baseline')
86bus_read.data.import_catalog(input_path='path/filename.hdf5')
Interpreting Results
All results are saved in the catalog located at bus.data.catalog
. This pandas data frame
contains rows representing the individual artificial exoplanets. The meaning of most columns can be
found in the file LIFEsim/lifesim/core/data.py
. The most important columns are listed in the
following:
'nuniverse'
: The index for the universe the planet is located in. See ‘Important’ box above for further explanation.
'nstar'
: The unique index for the star.
'habitable'
: IsTrue
if the planet resides in the habitable zone of its host star.
'snr_1h'
: The signal-to-noise ration the planet would have after one hour of integration time.
'detected'
: IsTrue
if the planet is observed long enough to have an SNR larger than bus.data.option.optimization[‘snr_target’]. In this case, the planet is counted towards the planets detected in the search phase.
'int_time'
: The amount of integration time spend on the system in [s].
Interpretation of this catalog is easily facilitated by the usage of selection masks. For example, the number of detected exoplanets in the habitable zone around M-type stars would be retrieved via
>>> import numpy as np
>>> mask_mtype = bus.data.catalog.stype == 4
>>> mask = np.logical_and.reduce((bus.data.catalog.detected, bus.data.catalog.habitable, mask_mtype))
>>> result_number = mask.sum()/500
Note the division by 500 to factor out the 500 simulated universes.
Architecture
Introduction
This section is meant to function as a starting point for anyone interested in contributing to LIFEsim or understanding the underlying programming ideas behind the package. First, the core of the package is described in some detail. This is then followed up by an example on how to program a new LIFEsim module.
General Structure
Apart from the functional goals, the core of LIFEsim is programmed to achieve two major goals:
LIFEsim must be easy to use for users unfamiliar with programming and for programmers unfamiliar with the code
LIFEsim must be easy to extend.
The implicit aim of goal (1.) is that all members of the LIFE team, largely independent from their background and level of knowledge, should be able to run a LIFEsim simulation. The implicit aim of goal (2.) is that a student can contribute to LIFEsim in the scope of an ETH semester project.

The diagram above outlines the general core architecture of LIFEsim.
The Bus
The Bus class is the main interface between the user and a LIFEsim simulation. Hence, it is considered to be part of the LIFEsim front-end. All modules taking part in the simulation are aggregated by the Bus. Via the Bus, the user is able to connect modules via their sockets. Furthermore, the Bus holds a single Data class by composition and forwards it to any modules connected to the bus. This makes sure that there are no conflicting instances of the Data class in a single simulation.
Modules
The underlying idea behind the Module class is that every physical, (partially) self-contained model is written into its own Module. This simplifies the program layout and makes it easier to understand on an abstract level. If a new physical model is to be added to LIFEsim, the programmer should create an abstract class inheriting from the Module class. Then, the programmer should identify all functions that the new module should fulfill. These functions are implemented as a stub abstract method, forcing any inheriting modules to implement the respective functionalities. Note here, that on this level the modules should not contain any functional code, but are rather filled with placeholder pass statements.
The Data Class
All data, parameters and options for LIFEsim are contained in the Data and Options classes. Located in the Data class is a catalog containing all target stars and exoplanets and additionally allocated space to save variables needed in the respectively used modules. The catalog can be directly imported from P-Pop.
The Options class saves parameters in dictionaries split after which part of the simulations the parameters concern. The parameters can be set according to existing baseline, optimistic and pessimistic scenarios for a future realization of the LIFE mission. A list of all options and the scenarios can be found in the tables at the bottom of the page. The Options class is connected to the Data class by composition, making sure that only a single instance of options can exist in any given simulation.
Sockets
The method of using sockets is implemented as a tool for interface management between the modules. This allows for independent implementation and re-implementation of modules. The the following is a description of the sockets functionality and how they should be used.
Each Module has an attributed dictionary called sockets. The elements of this dictionary is accessed by a string key, which doubles as the name of the socket. If Module P (see picture below) is to be connected to Module A, the following set-up needs to be done.

An entry in the sockets dictionary under a unique socket name s_name
is created (e.g.
s_name = 'connection_a'
). This element contains itself another dictionary specifying
the type of module the socket should accept.
the number of modules that can be connected to this socket.
a (currently empty) list tracking which modules are connected to the socket.
The set-up of the socket is now complete. Connecting the socket is done via the bus as follows
1bus = lifesim.Bus()
2
3mod_p = lifesim.Module_P(name='module_p')
4bus.add_module(mod_p)
5
6mod_a = lifesim.Module_A(name='module_a')
7bus.add_module(mod_a)
8
9bus.connect(('module_p', 'module_a'))
The command in Line 9 searches all sockets of the instance of Module P if they accept connection from an instance of Module A, and connects them if suitable socket is found. The same is done vice-versa, meaning that all Module A sockets are search for connections to Module P.
Now, module_a
is connected to the socket connection_a
of module_p
. It can therefore be
accessed in module_p
by calling self.sockets['connection_a']['modules'][0]
.
List of Parameters



Contributing to LIFEsim
LIFEsim is a community project lead by the LIFE Collaboration. Any contribution to LIFEsim is much encourage and highly appreciated.
We ask that contributions follow the PEP 8 python style guide.