The functionality of PTS is fully available as a set of regular Python packages that can be imported into external Python code. This allows developing custom visualization scripts or even fully automated pipelines without having to start from scratch. This tutorial introduces the basic concepts of how to use PTS from Python by studying a simple example program. For more information on each of the subjects introduced, refer to the PTS Reference documentation.
This tutorial assumes that
This tutorial offers a ski file for download to serve as a template configuration. Download the file TutorialPythonGalaxy.ski
using the link provided in the table below and put it into your local working directory.
Initial SKIRT parameter file | TutorialPythonGalaxy.ski |
---|
This ski file describes a panchromatic simulation of a very basic spiral galaxy model including a single instrument and some specific types of probes.
We will introduce the Python program section by section. To work through the tutorial, you can copy each new code section into a regular Python script and run the partially complete program from the start. Alternatively, you can copy the code sections into a Python notebook (see Using PTS in interactive Python notebooks) so that you can run each section separately.
At the start of the script:
This section of the code reads the ski file you previously downloaded, modifies the number of photon packets being launched in each phase, and saves the updated file under a new name. The pts.simulation.skifile.SkiFile class offers many more functions to obtain information from and/or update the contents of SKIRT configuration files.
This section of the code employs the pts.simulation.skirt.Skirt class to actually perform the SKIRT simulation. The constructor of this class attempts to locate the SKIRT executable in some default location, which can be overridden using the path argument.
The pts.simulation.skirt.Skirt.execute() function offers various arguments (not used here) to specify the location of the SKIRT input/output files and to control parallelization. The console argument is given the value 'brief' to limit the number of SKIRT log messages written to the console to the most important ones; in any case all messages are still being written to the SKIRT log file as usual.
The execute() function returns an object of type pts.simulation.simulation.Simulation which can be used to access the results of the SKIRT simulation. Note that the actual results reside on disk; the simulation object merely remembers where they are.
While invoking SKIRT directly from Python is very useful in automated workflows, there are many situations where this might be impracticle or even impossible (e.g. because running the simulation and analyzing its results is not being done on the same computer). In cases where the simulation has already been performed, the line above creates a simulation object corresponding to its result. The pts.simulation.simulation.createSimulation() function takes an extra argument to specify the location if needed.
The built-in visualizations offered from the command line (see Visualizing SKIRT results with PTS) are obviously also available as regular functions, often offering more flexibility through extra arguments. The code section above calls on the pts.visual.plotcurves.plotSeds() function to plot the spectrum observed by the simulation. Note that all quantities in PTS have astropy units attached. In the above example, the wavelengths are specified im micron. See Units and Quantities for more information on the astropy.units package.
The plotSeds() function automatically plots the indvidual components contributing to the total flux because there is only a single instrument in the simulation. Here is the resulting plot:
For more information on other visualization options, refer to the reference documentation of the pts.visual package.
The first line in this code section obtains the absolute path of the total flux data cube generated by the first instrument in the simulation. In this particular case, we could easily have hardcoded the filename, but the generic method is more instructive. A simulation object can asked for a list of instrument objects, which in turn can be asked for a list of output file paths.
The second line loads the data cube, and the third line loads the three corresponding axes. Note that both the pts.simulation.fits.loadFits() and pts.simulation.fits.getFitsAxes() functions return astropy quantities with units attached. See Units and Quantities for more information on the astropy.units package.
This code section arbitrary picks the wavelength with index 20 in the wavelength grid established for the instrument in the ski file and outputs the maximum surface brightness at that wavelength:
Observed frame has 500 by 200 pixels Maximum surface brightness at 0.643 micron is 1.156 MJy / sr
Note that surface brightness units are automatically included by the astropy units machinery.
This code section assumes that the simulation configuration includes a SpatialCellPropertiesProbe and a TemperatureProbe configured with a PerCellForm. The for loop iterates over all probes and selects the appropriate ones.
The pts.simulation.text.loadColumns() function loads specific columns of a text column file, using the structured header information included by SKIRT. The columns to be loaded can be specified as a comma-separated list of header descriptions corresponding to those in the file header. Again, the function returns astropy quantities with appropriate units attached.
In the example above, the cell volumes and dust mass densities written by the SpatialCellPropertiesProbe are combined with the cell temperatures written by the TemperatureProbe to obtain the mass-weighted average dust temperature.
This code section simply outputs the calculated results, again automatically including units:
Maximum dust temperature is 21.08 K Maximum cell dust mass is 9002.1 solMass Mass-weighted average dust temperature is 17.19 K
Here is the complete Python program:
And here is the complete output generated by the program (replacing some irrelevant material by _):
_ 16:00:30.362 Saved galaxy.ski _ 16:00:30.363 Executing galaxy.ski _ 16:00:30.377 Welcome to SKIRT v9.0 (_) _ 16:00:30.378 Running on _ for _ _ 16:00:30.378 Constructing a simulation from ski file '/_/galaxy.ski'... _ 16:00:34.989 - Finished setup in 4.6 s. _ 16:00:35.072 - Finished setup output in 0.1 s. _ 16:00:55.859 - Finished primary emission in 20.8 s. _ 16:01:03.953 - Finished secondary emission in 8.1 s. _ 16:01:03.953 - Finished the run in 28.9 s. _ 16:01:06.188 - Finished final output in 2.2 s. _ 16:01:06.188 - Finished simulation galaxy using 16 threads and a single process in 35.8 s. _ 16:01:06.293 Available memory: 32 GB -- Peak memory usage: 1.08 GB (3.4%) _ 16:01:07.158 Created /_/galaxy_sed.pdf _ 16:01:07.275 Observed frame has 800 by 200 pixels _ 16:01:07.276 Maximum surface brightness at 0.643 micron is 1.156 MJy / sr _ 16:01:07.355 Maximum dust temperature is 21.08 K _ 16:01:07.356 Maximum cell dust mass is 9002.1 solMass _ 16:01:07.357 Mass-weighted average dust temperature is 17.19 K