Analyzing SAGE Output¶
The output from SAGE is analyzed using the respective parameter files used to run SAGE itself. Here, we will
assume the parameter file is located in /home/Desktop/sage-model/input/millennium.ini
.
On this page, we outline some of the basic features of sage-analysis that can be used to analyze and plot SAGE output.
Basic Analysis¶
Out of the box, sage-analysis will analyse the latest snapshot (i.e., the lowest redshift) and save the plots in
the ./plots
directory.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
galaxy_analysis = GalaxyAnalysis(par_fnames)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
The output path can be changed by adjusting the plot_output_path
variable passed to
generate_plots()
.
If you ran SAGE using sage-binary
output, you will need to specify the
first_file_to_analyze
, last_file_to_analyze
, and
num_sage_output_files
for each model. These will need to be specified for all
the following examples. For brevity, we will omit them in the following and assume that SAGE has been run using
sage-hdf5
output (recommended).
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
first_files_to_analyze = [0] # The first files that you wish to analyze + plot.
last_files_to_analyze = [0] # The last files that you wish to analyze + plot.
num_sage_output_files = [1] # The number of files that SAGE produced; usually the number of processors it ran on.
galaxy_analysis = GalaxyAnalysis(
par_fnames,
first_files_to_analyze=first_files_to_analyze,
last_files_to_analyze=last_files_to_analyze,
num_sage_output_files=num_sage_output_files
)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
Accessing Galaxy Properties¶
Galaxy properties can be accessed via the properties
attribute of an individual
Model
class. It can be useful to generate only the properties and not performing
plotting (e.g., if you wish to use the properties for your own purpose).
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
galaxy_analysis = GalaxyAnalysis(par_fnames)
galaxy_analysis.analyze_galaxies()
print(galaxy_analysis.models)
print(galaxy_analysis.models[0].bins["stellar_mass_bins"]) # The stellar mass bins (log10 Msun).
print(galaxy_analysis.models[0].properties["snapshot_63"]["SMF"]) # The number of galaxies in each bin.
>>> [========================
... Model Mini-Millennium
... SAGE File:/home/Desktop/sage-model/input/millennium.ini
... SAGE Output Format: sage_hdf5
... First file to read: 0
... Last file to read: 0
... ========================]
>>> [ 8. 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9. 9.1 9.2 9.3
... 9.4 9.5 9.6 9.7 9.8 9.9 10. 10.1 10.2 10.3 10.4 10.5 10.6 10.7
... 10.8 10.9 11. 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12. ]
>>> [1148. 1328. 1456. 1698. 1836. 1824. 1778. 1576. 1313. 1091. 955. 830.
... 791. 734. 656. 662. 659. 593. 550. 552. 496. 483. 475. 425.
... 401. 291. 293. 248. 229. 190. 124. 71. 47. 18. 3. 0.
... 0. 0. 0. 0.]
Analyze Only a Subset of Files¶
For extremely large simulations, it may be prudent to analyze only a subset of files. For example, if SAGE run in
parallel across 32 processors, we may only wish to analyze a quarter of these. This can be achieved by specifying the
first_file_to_analyze
and
last_file_to_analyze
for each model.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
first_files_to_analyze = [0]
last_files_to_analyze = [7]
galaxy_analysis = GalaxyAnalysis(
par_fnames,
first_files_to_analyze=first_files_to_analyze,
last_files_to_analyze=last_files_to_analyze,
)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
Turning On and Off Properties¶
Properties are analyzed and plotted according to the values in
plot_toggles
. The default values of this dictionary are set to
analyze all basic properties, with the exception of properties tracked over time.
from sage_analaysis.default_analysis_arguments import default_plot_toggles
print(default_plot_toggles)
>>> {
'SMF': True,
'BMF': True,
'GMF': True,
'BTF': True,
'sSFR': True,
'gas_fraction': True,
'metallicity': True,
'bh_bulge': True,
'quiescent': True,
'bulge_fraction': True,
'baryon_fraction': True,
'reservoirs': True,
'spatial': True,
'SMF_history': False,
'SFRD_history': False,
'SMD_history': False
}
By adjusting these properties, or specifying a custom set, you can control which properties you want to analyze.
from sage_analaysis.default_analysis_arguments import default_plot_toggles
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
# Plot only the stellar mass function and black hole-bulge relationship.
galaxy_analysis = GalaxyAnalysis(par_fnames, plot_toggles={"SMF": True, "bh_bulge": True})
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
# Plot all properties EXCEPT the mass-metallicity relationship.
plot_toggles = default_plot_toggles.copy() # Copy to ensure ``default_plot_toggles`` aren't overwritten.
plot_toggles["metallicity"] = False
galaxy_analysis = GalaxyAnalysis(par_fnames, plot_toggles=plot_toggles)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
Analyzing Basic Properties Over Redshift¶
It can also be very useful to investigate how properties evolve over many snapshots. By default, sage-analysis supports analyzing the stellar mass function, stellar mass density, and star formation rate density over redshift.
Note
Ensure that SAGE has outputs for multiple snapshots. Try setting NumOutputs
to -1
and re-running
SAGE.
These extra properties can be set by turning their respective entries in plot_toggles
.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
galaxy_analysis = GalaxyAnalysis(
par_fnames, plot_toggles={"SMF_history": True, "SMD_history": True, "SFRD_history": True},
)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
By default, these extra properties are analyzed and plotted for all available redshifts. You can also specify which redshifts you want to analyze, with sage-analysis selecting the snapshots that are closest to the desired redshifts specified. This is especially useful for the stellar mass function where we often want to investigate the evolution at specific redshifts.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
galaxy_analysis = GalaxyAnalysis(
par_fnames,
plot_toggles={"SMF_history": True},
history_redshifts={"SMF_history": [0.0, 0.5, 1.0, 2.0, 3.0]},
)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
To analyse and plot these properties in addition to the other properties (e.g., the baryon fraction, quiescent
fraction, etc), use and update the default_plot_toggles
value.
from sage_analysis.default_analysis_arguments import default_plot_toggles
plot_toggles = default_plot_toggles.copy() # Copy to ensure ``default_plot_toggles`` aren't overwritten.
plot_toggles["SMF_history"] = True
plot_toggles["SMD_history"] = True
plot_toggles["SFRD_history"] = True
galaxy_analysis = GalaxyAnalysis(par_fnames, plot_toggles=plot_toggles)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
Changing the Snapshot¶
By default, sage-analysis will analyze the lowest redshift snapshot for each model. This behaviour can be adjusted to analyze any arbitrary snapshot.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
snapshots = [[50]]
galaxy_analysis = GalaxyAnalysis(par_fnames)
galaxy_analysis.analyze_galaxies(snapshots=snapshots)
galaxy_analysis.generate_plots(snapshots=snapshots)
Changing the Redshift¶
Alternatively, rather than specifying the snapshot for each model, one can specify the redshift. sage-analysis will analyze the snapshot closest to these redshifts.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
redshifts = [[1.0]]
galaxy_analysis = GalaxyAnalysis(par_fnames)
galaxy_analysis.analyze_galaxies(redshifts=redshifts)
galaxy_analysis.generate_plots(redshifts=redshifts)
Note
The snapshots
and redshifts
parameters cannot both be specified, only one may be used.
Multiple Models¶
sage-analysis supports analyzing and plotting of multiple SAGE model outputs. For example, let’s say we want
to compare the stellar mass function for SAGE run with and without supernovae feedback. This model has been run
using a parameter file /home/Desktop/sage-model/input/millennium_no_SN.ini
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini", "/home/Desktop/sage-model/input/millennium_no_SN.ini"]
labels = ["Supernovae feedback on", "Supernovae feedback off"]
galaxy_analysis = GalaxyAnalysis(par_fnames, labels=labels)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
Multiple Simulations¶
In the above example, we ran SAGE on the same underlying N-body simulation. However, we may wish to analyze how SAGE performs on different simulations, at the same redshift; e.g., we may wish to compare the stellar mass function at z = 1 for Millennium and Bolshoi.
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini", "/home/Desktop/sage-model/input/bolshoi.ini"]
labels = ["Millennium", "Bolshoi"]
galaxy_analysis = GalaxyAnalysis(par_fnames, labels=labels)
redshifts = [[1.0], [1.0]] # Specify the redshift for each model; necessary because the snapshots are not aligned.
galaxy_analysis.analyze_galaxies(redshifts=redshifts)
galaxy_analysis.generate_plots(redshifts=redshifts)
Or perhaps we wish to see how the stellar mass density evolves for the different simulations…
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini", "/home/Desktop/sage-model/input/bolshoi.ini"]
labels = ["Millennium", "Bolshoi"]
plot_toggles = {"SFRD_history": True}
galaxy_analysis = GalaxyAnalysis(par_fnames, plot_toggles=plot_toggles)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()
Adding Extra Keywords for Analysis and Plotting¶
Some properties can be broken down into sub-populations and analyzed separately. For example, the stellar mass function
can be split into red and blue galaxies or the baryon fraction can be split into its constituent reservoirs. To access
these extra functionalities, the calculation_functions
and
plot_functions
dictionaries passed to the
GalaxyAnalysis
constructor need to be adjusted.
from sage_analysis.utils import generate_func_dict
from sage_analysis.galaxy_analysis import GalaxyAnalysis
par_fnames = ["/home/Desktop/sage-model/input/millennium.ini"]
plot_toggles = {"SMF": True, "baryon_fraction": True}
# For each toggle, specify the extra keyword arguments and their values.
# The calculation and plotting step can each have different keywords.
extra_keywords_calculations = {"SMF": {"calc_sub_populations": True}}
extra_keywords_plotting = {
"SMF": {"plot_sub_populations": True},
"baryon_fraction": {"plot_sub_populations": True}
}
# Now build a dictionary with these extra arguments.
calculation_functions = generate_func_dict(
plot_toggles, "sage_analysis.example_calcs", "calc_", extra_keywords_calculations
)
plot_functions = generate_func_dict(
plot_toggles, "sage_analysis.example_plots", "plot_", extra_keywords_plotting
)
# Then construct with these new dictionaries.
galaxy_analysis = GalaxyAnalysis(
par_fnames,
plot_toggles=plot_toggles,
calculation_functions=calculation_functions,
plot_functions=plot_functions
)
galaxy_analysis.analyze_galaxies()
galaxy_analysis.generate_plots()