Commit 8430493b authored by Marc Arene's avatar Marc Arene
Browse files

Comments in main.py until line 215.

parent c32341cf
......@@ -51,21 +51,23 @@ if __name__ == '__main__':
To be written ..."""
parser=OptionParser(usage)
parser.add_option("--inj_file", default=None, action="store", type="string", help="""Injection file path leading to the `.ini` file specifying the parameters of the injection.""")
parser.add_option("--inj_file", default=None, action="store", type="string", help="""[!BROKEN!] Injection file path leading to the `.ini` file specifying the parameters of the injection.""")
parser.add_option("--event", default=None, action="store", type="string", help="""Event label part of the catalog GWTC-1""")
parser.add_option("--trigger_file", default=None, action="store", type="string", help="""File .ini describing the parameters where to start the chain. If left to None and --event used, a default file corresponding to the event will be used.""")
parser.add_option("--trigger_time", default=None, action="store", type="string", help="""Trigger GPS time.""")
parser.add_option("--config_file", default='../Codes/config_default.ini', action="store", type="string", help="""Configuration file path leading to the `.ini` file specifying some key options to run the HMC. The default file is '../Codes/config_default.ini'. Options set in the command line which are redundant with that of the config.ini will (should...) overwrite them.""")
parser.add_option("--outdir", default=None, action="store", type="string", help="""Output directory where results and plots will be stored. If not specified, it will be created automatically in the current working directory under ./outdir""")
parser.add_option("--trigger_file", default=None, action="store", type="string", help="""File .ini describing the parameter values where to start the chain. If left to None and --event used, a default file corresponding to the event will be used.""")
parser.add_option("--trigger_time", default=None, action="store", type="string", help="""[!BROKEN!] Trigger GPS time.""")
parser.add_option("--config_file", default='../Codes/config_default.ini', action="store", type="string", help="""Configuration file path leading to the `.ini` file specifying some key options to run the HMC. The default file is '../Codes/config_default.ini'. Options set in the command line which are redundant with that of the config.ini will (should...) overwrite them. Note that this config file must contain the path to a `prior_file` and to a `config_hmc_parameters_file.json`. The latter essentially defines the `search_parameter_keys` of the run.""")
parser.add_option("--outdir", default=None, action="store", type="string", help="""[!BROKEN!] Output directory where results and plots will be stored. If not specified, it will be created automatically in the current working directory under ./outdir""")
parser.add_option("-v", "--verbose", default=True, action="store_true", help="""Print out information of interest during the run.""",dest='verbose')
parser.add_option("-v", "--verbose", default=True, action="store_true", help="""[!BROKEN!] Print out information of interest during the run.""",dest='verbose')
parser.add_option("--plot_traj", default=False, action="store_true", help="""Will save positions, momentas, hamiltonian values etc of every point along every trajectory in phase to be able to plot them with `plot_trajectories.py` script.""")
parser.add_option("--sub_dir", default=None, action="store", type="string", help="""Optional sub-directory that will be appended at the endto the default output directory such that the final output directory is: '/default-output-dir/sub_dir/'""")
parser.add_option("--sub_dir", default=None, action="store", type="string", help="""Optional sub-directory that will be appended at the end to the default output directory such that the final output directory is: '/default-output-dir/sub_dir/'""")
parser.add_option("--fit_method", default='dnn', action="store", type="string", help="""Method used to fit the numerical gradients of the log likelihood accumulated in phase1. """)
parser.add_option("--no_seed", default=False, action="store_true", help="""New noise realisation from PSDs is generated""")
parser.add_option("--on_CIT", default=False, action="store_true", help="""Set this to True if running this script on Caltech's cluster. Will set the right path for the ROQ basis.""")
parser.add_option("--on_CIT", default=False, action="store_true", help="""[!BROKEN!] Set this to True if running this script on Caltech's cluster. Will set the right path for the ROQ basis.""")
# randGen = np.random.RandomState(seed=2)
##################################################################
# INITIALIZATION OF THE RUN
# PARSE INPUT ARGUMENTS
(opts, args) = parser.parse_args()
......@@ -79,16 +81,21 @@ if __name__ == '__main__':
config_dict_formatted = cut.dictionary_to_formatted_string(config_dict)
cut.logger.info(f'Options from the configuration file {opts.config_file} are: {config_dict_formatted}')
# This is not going to work on a generic CIT server...
if opts.on_CIT and config_dict['analysis']['roq']:
config_dict['analysis']['roq_b_matrix_directory'] = '/home/cbc/ROQ_data/IMRPhenomPv2/'
cut.logger.info('Setting the roq_b_matrix_directory to "/home/cbc/ROQ_data/IMRPhenomPv2/"')
# Set this boolean in RUN_CONST accordingly to the input option,
# then `RUN_CONST.plot_traj` can be called anywhere in the code.
RUN_CONST.plot_traj = opts.plot_traj
if not(opts.no_seed):
# Set up a random seed for result reproducibility. This is optional!
np.random.seed(88170235)
# Check whether the run is on an injection, an event from the catalog or a trigger time
# Check whether the run is done on an injection, an event from the catalog or a trigger time.
# WARNING: the only option really tested for the moment is `opts.event`,
# the other two require adaptation of the code.
if opts.event is not None:
data_name = opts.event + 'real'
elif opts.inj_file is not None:
......@@ -101,13 +108,13 @@ if __name__ == '__main__':
# Parse the inputs relative to the sampler and the search
# sampler_dict = init.get_sampler_dict(config_dict)
sampler_dict = pu.json_to_dict(config_dict['hmc']['config_hmc_parameters_file'])
sampler_dict = init.sampler_dict_update_geocent_time_by_duration(sampler_dict)
sampler_dict_formatted = cut.dictionary_to_formatted_string(sampler_dict)
cut.logger.info(f'Options for the sampler are: {sampler_dict_formatted}')
# SET THE OUTPUT DIRECTORY WHERE OUTPUT FILES WILL BE SAVED
# The typical the structure is set as `'../__output_data/[data_name]/[search_parameter_nbs]/[psd_option]/[config_options]/[approximant_name]/`; cf doc string of the function.
if opts.outdir is None:
outdir = init.get_output_dir(data_name, sampler_dict['search_parameter_keys'], config_dict, opts.sub_dir)
else:
......@@ -118,9 +125,7 @@ if __name__ == '__main__':
today_fmt = '{:%d/%m/%y at %Hh%M}'.format(today)
cut.logger.info(f'\n\n\n\n\nToday is the {today_fmt}.')
cut.logger.info(f'Output directory is: {outdir}')
# cut.logger.info(f'Run `$ tail -f {outdir}logger.log` to follow the run')
# import IPython; IPython.embed(); sys.exit()
# Save the config file dictionary
# Save the different input files in the output directory.
if opts.inj_file is not None:
subprocess.run('cp ' + opts.inj_file + ' ' + outdir + 'injection.ini', shell=True)
if opts.trigger_file is not None:
......@@ -150,11 +155,13 @@ if __name__ == '__main__':
start_time = ext_analysis_dict['start_time']
duration = ext_analysis_dict['duration']
# Retrieve the PSDs of the ifos from the psd_file given in the config_file.
# For GWTC1 events, PSDs are available on DCC and formated for each event as a `GWTC1_{opts.event}_PSDs.dat` file, hence the single_file possibility.
# [TO BE MODIFIED]: so I made a shortcut if they are stored correctly under f'../__input_data/{opts.event}/GWTC1_{opts.event}_PSDs.dat' but this should be simply removed and `gwtc1_psds_file` should not exist.
psds_single_file = config_dict['analysis'].get('psds_single_file', '/dir/not/filled')
gwtc1_psds_file = f'../__input_data/{opts.event}/GWTC1_{opts.event}_PSDs.dat'
psd_dict = cut.convert_string_to_dict(config_dict['analysis'].get('psd_dict', '{}'))
# import IPython; IPython.embed(); sys.exit()
if os.path.exists(psds_single_file):
set_psd_from_single_file = True
psds_file_path = psds_single_file
......@@ -169,7 +176,8 @@ if __name__ == '__main__':
cut.logger.info(f'No PSD path filled in options `psds_single_file` or `psd_dict` or could not be found. PSDs will therefore be computed from the strain files.')
# Retrieve the names of the .hdf5 files in the input directory of the event.
# [TO BE MODIFIED]: path of input strain files should be set in the configuration files and not half hard-coded as they are bellow...
hdf5_file_path_prefix = '../__input_data/' + opts.event
if not(os.path.exists(hdf5_file_path_prefix)):
cut.logger.error(f'The folder given to look for hdf5 strain files of the event: {hdf5_file_path_prefix}, does not exist.')
......@@ -181,16 +189,12 @@ if __name__ == '__main__':
interferometers = gwdn.InterferometerList(ext_analysis_dict['ifos'])
# The minimun frequency for each interferometer needs to be set if we want the strain derived from the psd to start being non zero at that frequency and not at the default one which is 20Hz
# if type(ext_analysis_dict['minimum_frequency']) == str:
# ifos_min_freqs_dict = cut.convert_string_to_dict(ext_analysis_dict['minimum_frequency'])
# else:
# ifos_min_freqs_dict = {ifo: ext_analysis_dict['minimum_frequency'] for ifo in ext_analysis_dict['ifos']}
for i, ifo in enumerate(interferometers):
ifo.minimum_frequency = ext_analysis_dict['minimum_frequency_ifos'][ifo.name]
ifo.maximum_frequency = ext_analysis_dict['maximum_frequency_ifo']
# Should look like: '../__input_data/GW170817/H-H1_GWOSC_4KHZ_R1-1187006835-4096.hdf5'
# [TO BE MODIFIED]: there should not be a hard-code for GW170817.
if opts.event == 'GW170817':
hdf5_file_path = f'{hdf5_file_path_prefix}/LOSC/{ifo.name[0]}-{ifo.name}_LOSC_CLN_4_V1-1187007040-2048.hdf5'
# hdf5_file_path = f'{hdf5_file_path_prefix}/{ifo.name[0]}-{ifo.name}_GWOSC_4KHZ_R1-1187006835-4096.hdf5'
......@@ -279,6 +283,7 @@ if __name__ == '__main__':
del hdf5_strain, desired_hdf5_strain
# WARNING: this `inj_file` branch is certainly broken
elif opts.inj_file is not None:
# SET THE INJECTION PARAMETERS AND THE ANALYSIS PARAMETERS
injection_parameters, ext_analysis_dict = set_inj.get_inj_parameters_and_analysis_dict(opts.inj_file, **config_dict['analysis'])
......
......@@ -106,6 +106,28 @@ def ini_file_to_dict(inj_file_path='../examples/injection_files/GW170817.ini'):
return injection_parameters
def compute_extended_analysis_dict(mass_1, mass_2, geocent_time, chirp_mass, **analysis_kwargs):
"""
First, this function is clearly messy and needs some non-negligible re-writing... The idea is essentially to retrieve from the input parameters the GPS start_time of the analysis and the duration of the segment. Then some checks are performed, such as on the sampling frequency; the interferometers names are put in a list etc...
Parameters
----------
mass_1: float
Mass, in solar mass units, of the first component of the binary.
mass_2: float
Mass, in solar mass units, of the second component of the binary.
geocent_time: float
GPS time, as measured at the center of the earth, of the merger.
chirp_mass: float
Chirp mass of the binary.
analysis_kwargs: dictionary
Additional options set in the '[analysis]' section of the config.ini file. The dictionary must contain the keys ['approximant', 'roq', 'minimum_frequency_ifos', 'ifos', 'reference_frequency', 'maximum_frequency',
Returns
-------
ext_analysis_dict: dictionary
Dictionary containing most importantly the duration of the segment analyzed and `tc_3p5PN` which is the duration to coalescence, and the GPS start_time.
"""
approximant = analysis_kwargs['approximant']
roq = analysis_kwargs['roq']
......@@ -113,7 +135,7 @@ def compute_extended_analysis_dict(mass_1, mass_2, geocent_time, chirp_mass, **a
if type(analysis_kwargs['minimum_frequency_ifos']) == str:
minimum_frequency_ifos = cut.convert_string_to_dict(analysis_kwargs['minimum_frequency_ifos'])
else:
minimum_frequency_ifos = {ifo: analysis_kwargs['minimum_frequency_ifos'] for ifo in analysis_kwargs['ifos']}
minimum_frequency_ifos = {ifo: analysis_kwargs['minimum_frequency'] for ifo in analysis_kwargs['ifos']}
minimum_frequency_all = min(minimum_frequency_ifos.values())
reference_frequency = analysis_kwargs['reference_frequency']
maximum_frequency = analysis_kwargs['maximum_frequency']
......
......@@ -16,6 +16,19 @@ def get_sampler_dict(config_dict):
return sampler_dict
def sampler_dict_update_geocent_time_by_duration(sampler_dict):
"""
Takes the dictionary containing the list of search parameter keys and updates the key `geocent_time` to `geocent_duration` since it will be the duration used by the HMC and not GPS time for numerical precision reasons when computing numerical gradients on that parameter.
Parameters
----------
sampler_dict: dictionary
Dictionary which must contain the keys `search_parameter_keys` (which is the array describing the parameters of the search), `trajectory_functions` (like 'log' for the keys `chirp_mass` and `reduced_mass` or `cosine` for `theta_jn`) and `parameters_offsets` (offsets used for each key when computing numerical gradients, typically 1e-7).
Returns
-------
sampler_dict: dictionary
Returns the input dictionary where the search_parameter_key `geocent_time` has been updated to `geocent_duration`.
"""
cut.logger.info('As usual, for numerical precision reasons for its gradients, the HMC samples in geocent_duration instead of the GPS geocent_time and converts back to it afterwards.')
idx_geocent_time = sampler_dict['search_parameter_keys'].index('geocent_time')
sampler_dict['search_parameter_keys'][idx_geocent_time] = 'geocent_duration'
......@@ -24,6 +37,31 @@ def sampler_dict_update_geocent_time_by_duration(sampler_dict):
return sampler_dict
def get_output_dir(inj_name, search_parameter_keys, config_dict, sub_dir=None):
"""
Parameters
----------
inj_name: string
Name of the injection, or the GW event.
search_parameter_keys: array like
List of the keys defining the parameters of the search.
config_dict: dictionary
Dict containing some key options for the run such as the total number of trajectories in phase 1
sub_dir: string, optional
Optional string which will be appended at the end of the output_dir string built from the previous inputs.
Returns
-------
outdir: string
The path of the directory where output files will be stored, note this string ends with a slash `/`.
Notes
-----
At the moment `outdir` is hard coded to start as `outdir = '../__output_data/[inj_name]/... `.
The end of the string is built to have the structure `'../__output_data/[inj_name]/[search_parameter_nbs]/[psd_option]/[config_options]/[approximant_name]/`.
- [search_parameter_nbs] is built from `search_parameter_keys` and assigns a predefined integer to each key to built a string.
- [psd_option]: should be removed, it was there to distinguish runs using fake PSDs vs PSDs estimated from the strain vs PSDs read from input files.
- [approximant_name]: eg `IMRPhenomD_NRTidal` etc...
"""
# Parse the inputs relative to the HMC algorithm
n_traj_hmc_tot = config_dict['hmc']['n_traj_hmc_tot']
......
......@@ -76,13 +76,19 @@ def dictionary_to_formatted_string(dictionary, indent=3, align_keys=True, decima
"""
Formats a dictionary such that the outputted string will be printed with the nested structure.
Parameters:
indent: int, default=3
number of spaces used to indent the nested dictionaries
align_keys: boolean, default=True
aligns vertically the printed values
decimal_format: int, default=None
number of decimals to print for numbers in the dictionary using the format {:.xf} where x is `decimal_format`. If left to None not format will be applied.
Parameters
----------
indent: int, default=3
Number of spaces used to indent the nested dictionaries
align_keys: boolean, default=True
Aligns vertically the printed values
decimal_format: int, default=None
Number of decimals to print for numbers in the dictionary using the format {:.xf} where x is `decimal_format`. If left to None not format will be applied.
Returns
-------
string_to_print: string
String to be printed with line breaks that follow the nested structure of the input dictionary.
"""
string_to_print = ''
indent_align_key_str = ''
......
[analysis]
# Interferometers to run the analysis on.
# Interferometers to run the analysis on; must be separated by a comma.
ifos = H1,L1,V1
approximant = IMRPhenomD_NRTidal
; minimum_frequency_ifos = {H1: 23.0, L1: 23.0, V1: 23.0}
# Names of the ifo in the dictionary here must match those defined above.
minimum_frequency_ifos = {H1: 30.0, L1: 30.0, V1: 30.0}
; minimum_frequency = 30
maximum_frequency = 2048.0
......@@ -12,6 +12,7 @@ roq_b_matrix_directory = /Users/marcarene/roq/ROQ_data/IMRPhenomPv2/
# 1: sets the PSDs from official GWTC-1 open PSD data; 2: computes PSDs using Welch methods from gwosc open strain data; 3: uses bilby's analytical pre-stored PSD files.
psd = 1
psds_single_file = ../__input_data/GWTC1_PSDs/GWTC1_GW170817_PSDs.dat
; psd_dict = {H1: /path/to/H1_PSD.dat, L1: /path/to/H1_PSD.dat, V1: /path/to/H1_PSD.dat}
phase_marginalization = True
......
# Setting DeepHMC for a run on a new event
- The bash line to launch will typically look like
```bash
python main.py --event=GW170817 --trigger_file=../examples/trigger_files/GW170817_IMRPhenomD_NRTidal.ini --config_file=../examples/config_files/config_GW170817_IMRPhenomD_NRTidal.ini --fit_method=dnn
```
- The `--event` option defines the name of the event and will be used to find input files in the directory `local_path_to/gwhmc/__input_data/GW170817/`, knowing that `main.py` is stored in `/gwhmc/main.py`.
## Configuration files
The current way config files work is unfortunately a bit complicated and confusing, it should be simplified in the long term.
### The `config.ini` file
- Path given in the `--config_file` option of the bash `python main.py` command line.
- Create a `config.ini` file, following the example of `gwhmc/examples/config_files/config_GW170817_IMRPhenomD_NRTidal.ini`: it must contain 3 sections named `[analysis]`, `[parameters]` and `[hmc]`:
```ini
[analysis]
# Interferometers to run the analysis on; must be separated by a comma.
ifos = H1,L1,V1
approximant = IMRPhenomD_NRTidal
# Names of the ifo in the dictionary here must match those defined above.
minimum_frequency_ifos = {H1: 30.0, L1: 30.0, V1: 30.0}
maximum_frequency = 2048.0
reference_frequency = 20
roq = False
roq_b_matrix_directory = /Users/marcarene/roq/ROQ_data/IMRPhenomPv2/
# 1: sets the PSDs from official GWTC-1 open PSD data; 2: computes PSDs using Welch methods from gwosc open strain data; 3: uses bilby's analytical pre-stored PSD files.
psd = 1
psds_single_file = ../__input_data/GWTC1_PSDs/GWTC1_GW170817_PSDs.dat
#psd_dict = {H1: /path/to/H1_PSD.dat, L1: /path/to/H1_PSD.dat, V1: /path/to/H1_PSD.dat}
phase_marginalization = True
[parameters]
prior_file=../gw/prior_files/GW170817_LALInf_IMRPhenomD_NRTidal.prior
[hmc]
# Total number of trajectories of HMC
n_traj_hmc_tot = 1000000
# Number of trajectories using numericalgradients in phase 1.
n_traj_fit = 1500
# Number of iterations if phase1 loop to go over for this run. This permits to split phase1 into several chunks. If set to 0, then the value will be set to that of n_traj_fit
n_traj_for_this_run = 300000
# Number of points used to sub-select points in Ordered Look-Up Tables for local fit bimodal parameters like (cos(inc), psi, logD)
n_fit_1 = 2000
# Number of points sub-selected from the above n1 ones to perform a linera fit
n_fit_2 = 200
# Length of numerical trajectories during phase1
length_num_traj = 200
# Stepsize between steps of trajectories used for phase1.
epsilon0 = 5e-3
# Python file to configure your search parameter space
config_hmc_parameters_file = ../examples/config_params/GW170817_IMRPhenomD_NRTidal.json
# Number of statistically independant samples desired.
n_sis = 5000
```
- PSDs can either be set from a single file containing the PSDs of each ifos. They are stored on DCC in such files for GWTC1 events. In that case use the `psds_single_file =` option.
- If each PSD is stored in one file then use the `psd_dict = ` option to define each path.
- If none of the above, then PSDs are estimated strom the strain data using the Welch method.
- The `psd = 1` (or 2 or 3) option was used in case of injections but it certainly broken now.
- `n_fit_1` and `n_fit_2` should be removed from the code since we use the DNN now and not OLUTs.
### The `prior.prior` file
- Its path is defined in the `[parameters]` section of the above `config.ini` file after the key `prior_file =`.
- At the moment some examples of prior files can be found in... ...`/gwhmc/gw/prior_files`.
- They are handled as Bilby does since they defines Bilby prior functions and look like:
```
# Example of priors for GW170817 using IMRPhenomD_NRTidal
theta_jn = Sine(name='theta_jn', boundary='reflective')
psi = Uniform(name='psi', minimum=0, maximum=np.pi, boundary='periodic')
luminosity_distance = PowerLaw(name='luminosity_distance', alpha=2, minimum=10, maximum=100, unit='Mpc', boundary=None)
mass_1 = Uniform(name='mass_1', minimum=0.5, maximum=7.7, unit='$M_{\odot}$')
mass_2 = Uniform(name='mass_2', minimum=0.5, maximum=7.7, unit='$M_{\odot}$')
chirp_mass = Constraint(name='chirp_mass', minimum=1.1838325, maximum=2.16847416667, unit='$M_{\odot}$')
# reduced_mass = Constraint(name='reduced_mass', minimum=0.5, maximum=1.3, unit='$M_{\odot}$')
dec = Cosine(name='dec', boundary='reflective')
ra = Uniform(name='ra', minimum=0, maximum=2 * np.pi, boundary='periodic')
geocent_time = Uniform(name='geocent_time', minimum=-np.inf, maximum=np.inf, boundary='reflective', latex_label='$t_c$', unit='$s$')
chi_1 = bilby.gw.prior.AlignedSpin(name='chi_1', a_prior=Uniform(minimum=0, maximum=0.05), boundary='reflective')
chi_2 = bilby.gw.prior.AlignedSpin(name='chi_2', a_prior=Uniform(minimum=0, maximum=0.05), boundary='reflective')
lambda_1 = Uniform(name='lambda_1', minimum=0, maximum=5000)
lambda_2 = Uniform(name='lambda_2', minimum=0, maximum=5000)
```
- Each line will be translated into the corresponding Bilby prior function, just as if we had written python code in this text file.
- The `boundary='reflective'` argument is not used in DeepHMC since we handle boundaries differently.
- Similar to what is done in Bilby, the prior on `geocent_time` is set internally by DeepHMC to be flat at `+/- 0.1` around the merger time.
### The `config_params.json` file
- Path defined in the `[hmc]` section of the `config.ini` file under the key `config_hmc_parameters_file = `.
- The information it contains could probably be directly defined in the `config.ini` file, which would be simpler, by writing some "string-dictionary" (just like for the `minimum_frequency_ifos = {H1: 20.0, L1: 30.0, V1: 20.0}`) which would then be converted into proper dictionaries using the `core.utils.convert_string_to_dict` method, but at the time I did not know about that handy bilby_pipe function so I used a json file to handle the nested structure of the information.
- So this json file typically looks like:
```json
{
"search_parameter_keys": [
"theta_jn",
"psi",
"luminosity_distance",
"chirp_mass",
"reduced_mass",
"dec",
"ra",
"geocent_time",
"chi_1",
"chi_2",
"lambda_1",
"lambda_2"
],
"trajectory_functions": {
"theta_jn": "cosine",
"psi": "None",
"luminosity_distance": "log",
"chirp_mass": "log",
"reduced_mass": "log",
"dec": "sine",
"ra": "None",
"geocent_time": "log",
"chi_1": "None",
"chi_2": "None",
"lambda_1": "None",
"lambda_2": "None"
},
"search_parameter_keys_local_fit": [
"theta_jn",
"psi",
"luminosity_distance"
],
"parameters_offsets": {
"theta_jn": 1e-7,
"phase": 1e-7,
"psi": 1e-7,
"luminosity_distance": 1e-7,
"chirp_mass": 1e-7,
"reduced_mass": 1e-7,
"dec": 1e-7,
"ra": 1e-7,
"geocent_time": 1e-7
}
}
```
- Most importantly it defines the search parameter space of the analysis, so here 12 dimensional and implicitely marginalizing over phase at coalescence (which option must therefore be set to `True` in the `config.ini` file).
- `geocent_time` will automatically be converted internally into `geocent_duration` because otherwise the HMC suffers from numerical precision issues when computing numerical gradients on a GPS time. But final results are then converted back to `geocent_time` by simply adding the `start_time` of the analysis.
- Each search parameter can have a "trajectory function" which defines the space in which trajectories are computed. Priors, defined for instance on `luminosity_distance` and not on `log(luminosity_distance)`, automatically adapt to the trajectory functions used. If set to `None` or not set in this file then the identity function is used.
- `search_parameter_keys_local_fit` made sense for the OLUTs but should be removed from the code now (removing the key directly in the file might break the code so careful...).
- `parameters_offsets` defines the offsets which will be used when computing numerical differenciation. If not specified for a parameter, the default value will be `1e-7`.
- Note that priors can be defined on component masses even though we sample in `log(chirp_mass)` and `log(reduced_mass)`.
- Note that if not marginalizing over the phase at coalescence, then the key `phase` refers to the *orbital* phase, to be consistent with Bilby, and not the phase at coalescence.
### The `trigger.ini` file
- Path given in the `--trigger_file` option of the bash `python main.py` command line.
- It defines the parameter values of the starting point of the analysis.
- For GW170817 using IMRPhenomD_NRTidal and marginalizing over the phase at coalescence, it can look like
```ini
[parameters]
mass_1=1.72592086595
mass_2=1.10730509114
luminosity_distance=21.1702759705
theta_jn=2.04318308535
psi=1.61012417485
geocent_time=1187008882.43
ra=3.44616
dec=-0.408084
chi_1=0.027842426346
chi_2=0.0278262466181
lambda_1=130.651548464
lambda_2=210.695175639
```
- `chirp_mas`, `total_mass`, `symmetric_mass_ratio`, `mass_ratio` and `reduced_mass` are automatically computed from the two component masses, but not the other way around, hence one must specify `mass_1` and `mass_2` in this file.
## Input `.hdf5` strain files
- The `--event` option of the bash `python main.py` command line defines the name of the event and will be used to find input files in the directory `local_path_to/gwhmc/__input_data/[event_name]/`, knowing that `main.py` is stored in `/gwhmc/main.py`. But note that at the moment is it hard-coded to look in the relative path `../__input_data/[event_name]`. This behavior should of course be modified...
- Since at the moment the path for each strain file is not specified in any configuration file, the code lists every `.hdf5` file present in the directory `../__input_data/[event_name]/` assuming they all refer to one strain file per interferometer (for some reason I hard-coded in `main.py` that for GW170817 it looks into `../__input_data/GW170817/LOSC/` ...).
- Then to differentiate between each ifo it is assumed that each file starts with a consistent prefix: `H-H1_[...].hdf5` or `L-L1_[...].hdf5` or `V-V1_[...].hdf5`.
- These files can be downloaded from the GWOSC website.
- If the sampling frequency defined in `config.ini` is higher than that used in the `.hdf5` file, an error is thrown, if smaller then the strain data is automatically down-sampled accordingly by keeping only 1 strain sample every `N` where `N = int(sampling_frequency_from_strain_file / sampling_frequency_from_config_file)`.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment