Skip to content

Commit 83ac83b

Browse files
author
Collin Capano
committed
update inference notebook 5
1 parent 3e796b8 commit 83ac83b

1 file changed

Lines changed: 87 additions & 54 deletions

File tree

tutorial/inference_5_results_io/IntroToPyCBCInference.ipynb

Lines changed: 87 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"\n",
3434
"# This is needed to access the executables on sciserver. On a personal machine this should be ignore.\n",
3535
"path = %env PATH\n",
36-
"%env PATH=$path:/home/idies/miniconda3/envs/py27/bin "
36+
"%env PATH=$path:/home/idies/miniconda3/envs/py37/bin "
3737
]
3838
},
3939
{
@@ -62,23 +62,9 @@
6262
"cell_type": "markdown",
6363
"metadata": {},
6464
"source": [
65-
"We will download a result file from a fully completed analysis, from [here](https://www.atlas.aei.uni-hannover.de/~cdcapano/projects/pycbc_inference/workshop-may2019/bbh_injection). In this analysis, we injected a binary black hole simulation into LIGO data (20 seconds after GW150914). The injection parameters are:\n",
66-
"```\n",
67-
"tc = 1126259482.420\n",
68-
"mass1 = 37\n",
69-
"mass2 = 32\n",
70-
"ra = 2.2\n",
71-
"dec = -1.25\n",
72-
"inclincation = 2.5\n",
73-
"coa_phase = 1.5\n",
74-
"polarization = 1.75\n",
75-
"distance = 100\n",
76-
"f_ref = 20\n",
77-
"f_lower = 18\n",
78-
"approximant = IMRPhenomPv2\n",
79-
"taper = start\n",
80-
"```\n",
81-
"These are similar to GW150914, although it is about a factor of 5 closer in distance. You can see the config file used and the run script in the [linked directory](https://www.atlas.aei.uni-hannover.de/~cdcapano/projects/pycbc_inference/workshop-may2019/bbh_injection)."
65+
"We will download a result file from a fully completed analysis, from [here](https://www.atlas.aei.uni-hannover.de/~work-cdcapano/pycbc_workshop_june_2020). This is the result of running `emcee_pt` on GW150914 using the standard prior provided in the online [PyCBC Inference documentation](http://pycbc.org/pycbc/latest/html/inference/examples/gw150914.html). You can see the complete configuration file [here](https://www.atlas.aei.uni-hannover.de/~work-cdcapano/pycbc_workshop_june_2020/inference-emcee_pt.ini).\n",
66+
"\n",
67+
"Note that there are two files in this directory. This is because this run was run twice with different starting seeds, to accumulate more samples. We'll download one of the files now."
8268
]
8369
},
8470
{
@@ -87,8 +73,8 @@
8773
"metadata": {},
8874
"outputs": [],
8975
"source": [
90-
"if not os.path.exists('bbh_results.hdf'):\n",
91-
" !wget https://www.atlas.aei.uni-hannover.de/~cdcapano/projects/pycbc_inference/bbh_injection/bbh_results.hdf"
76+
"if not os.path.exists('H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf'):\n",
77+
" !wget https://www.atlas.aei.uni-hannover.de/~work-cdcapano/pycbc_workshop_june_2020/H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf"
9278
]
9379
},
9480
{
@@ -102,7 +88,7 @@
10288
"cell_type": "markdown",
10389
"metadata": {},
10490
"source": [
105-
"The results file `bbh_results.hdf` is an HDF file. We could use the standard python module for reading HDF files [h5py](http://docs.h5py.org/en/stable/) to examine it. However, there are classes in [pycbc.inference.io](http://pycbc.org/pycbc/latest/html/pycbc.inference.io.html) that inherit from [h5py.File](http://docs.h5py.org/en/stable/high/file.html#file-objects) and add several convenience functions that make it easier to read samples from the file. There is one class for each type of sampler. So to load the file, we will use [pycbc.inference.io.loadfile](http://pycbc.org/pycbc/latest/html/pycbc.inference.io.html#pycbc.inference.io.loadfile). This function automatically determines which class to use to read the file, based on what is in the file."
91+
"The results file `H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf` is an HDF file. We could use the standard python module for reading HDF files [h5py](http://docs.h5py.org/en/stable/) to examine it. However, there are classes in [pycbc.inference.io](http://pycbc.org/pycbc/latest/html/pycbc.inference.io.html) that inherit from [h5py.File](http://docs.h5py.org/en/stable/high/file.html#file-objects) and add several convenience functions that make it easier to read samples from the file. There is one class for each type of sampler. To load the file, we will use [pycbc.inference.io.loadfile](http://pycbc.org/pycbc/latest/html/pycbc.inference.io.html#pycbc.inference.io.loadfile). This function automatically determines which class to use to read the file, based on what is in the file."
10692
]
10793
},
10894
{
@@ -120,7 +106,7 @@
120106
"metadata": {},
121107
"outputs": [],
122108
"source": [
123-
"fp = loadfile('bbh_results.hdf', 'r')"
109+
"fp = loadfile('H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf', 'r')"
124110
]
125111
},
126112
{
@@ -136,7 +122,7 @@
136122
"metadata": {},
137123
"outputs": [],
138124
"source": [
139-
"fp.keys()"
125+
"list(fp.keys())"
140126
]
141127
},
142128
{
@@ -152,7 +138,7 @@
152138
"metadata": {},
153139
"outputs": [],
154140
"source": [
155-
"fp.attrs.items()"
141+
"list(fp.attrs.items())"
156142
]
157143
},
158144
{
@@ -169,14 +155,14 @@
169155
"metadata": {},
170156
"outputs": [],
171157
"source": [
172-
"fp['sampler_info'].keys()"
158+
"list(fp['sampler_info'].keys())"
173159
]
174160
},
175161
{
176162
"cell_type": "markdown",
177163
"metadata": {},
178164
"source": [
179-
"Every group can have their own `.attrs`; let's look at the `sampler_info` group's `attrs`:"
165+
"We see that for `emcee_pt` (as well as any MCMC sampler), burn in information and the autocorrelation time (ACT) are stored in the sampler info. We could read these directly from the file. For example:"
180166
]
181167
},
182168
{
@@ -185,15 +171,14 @@
185171
"metadata": {},
186172
"outputs": [],
187173
"source": [
188-
"fp['sampler_info'].attrs.items()"
174+
"print(fp['sampler_info/burn_in_iteration'][()])"
189175
]
190176
},
191177
{
192178
"cell_type": "markdown",
193179
"metadata": {},
194180
"source": [
195-
"### Injection data\n",
196-
"If we are analyzing an injection, as in this case, an `injections` group is added to the file. This group contains all the information about the injection(s) that was (were) performed. Let's take a look:"
181+
"However, since the ACT and burn in itertion are such important information, they are promotted to attributes. We can get them by simply doing:"
197182
]
198183
},
199184
{
@@ -202,23 +187,23 @@
202187
"metadata": {},
203188
"outputs": [],
204189
"source": [
205-
"fp['injections'].keys()"
190+
"print(fp.act, fp.burn_in_iteration)"
206191
]
207192
},
208193
{
209-
"cell_type": "code",
210-
"execution_count": null,
194+
"cell_type": "markdown",
211195
"metadata": {},
212-
"outputs": [],
213196
"source": [
214-
"fp['injections'].attrs.items()"
197+
"Every group can have their own `.attrs`; let's look at the `sampler_info` group's `attrs`:"
215198
]
216199
},
217200
{
218-
"cell_type": "markdown",
201+
"cell_type": "code",
202+
"execution_count": null,
219203
"metadata": {},
204+
"outputs": [],
220205
"source": [
221-
"Note that there was no data sets stored in the `injections` group (`.keys()` returned an empty list). All of the injection info was in the `.attrs`. This was because a single injection was performed. If multiple injections had been done, the parameters that were varied would be stored as datasets."
206+
"list(fp['sampler_info'].attrs.items())"
222207
]
223208
},
224209
{
@@ -236,7 +221,7 @@
236221
"metadata": {},
237222
"outputs": [],
238223
"source": [
239-
"print(fp['samples'].keys())"
224+
"list(fp['samples'].keys())"
240225
]
241226
},
242227
{
@@ -252,7 +237,7 @@
252237
"metadata": {},
253238
"outputs": [],
254239
"source": [
255-
"fp['samples'].attrs.items()"
240+
"list(fp['samples'].attrs.items())"
256241
]
257242
},
258243
{
@@ -275,9 +260,9 @@
275260
"cell_type": "markdown",
276261
"metadata": {},
277262
"source": [
278-
"The shape of the dataset is `ntemps x nwalkers x n thinned iteration`. This run used 4 temperatures and 1000 walkers. Due to `max-samples-per-chain` being set to 1000, the data set has been thinned to include 750 samples from each walker and temperature.\n",
263+
"The shape of the dataset is `ntemps x nwalkers x n thinned iteration`. This run used 20 temperatures and 200 walkers. Due to `max-samples-per-chain` being set to 1024, the data set has been thinned to include 704 samples from each walker and temperature.\n",
279264
"\n",
280-
"If this had been an `emcee` run (which uses no temperatures), the samples datasets would have been two dimensional: `nwalkers x niterations`. If it had been a nested sampling run (with either CPNest or Multinest), the datasets would have been 1 dimensional. **The format of the samples data is sampler dependent.** This is why we have separate classes to read the results file."
265+
"If this had been an `emcee` run (which uses no temperatures), the samples datasets would have been two dimensional: `nwalkers x niterations`. If it had been a nested sampling run (e.g., with `dynesty`), the datasets would have been 1 dimensional. **The format of the samples data is sampler dependent.** This is why we have separate classes to read the results file."
281266
]
282267
},
283268
{
@@ -288,7 +273,7 @@
288273
"\n",
289274
"Now lets load the samples. We can use the `read_samples` function to do this. This takes as a the first argument a list of parameters to load. Here, we'll load all of the parameters. It also takes additional keyword arguments. These arguments are sampler-specific. For `emcee_pt` if we provide no additional keyword arguments, we'll get all temperatures. We just want the coldest temperature `temp=0`, as that is the posterior.\n",
290275
"\n",
291-
"If we provide no other arguments, `read_samples` will load all of the independent samples post burn-in. That is, it will get samples from all walkers, starting from the burn in iteration, and thinned by the ACL (it gets this information from the file's `.attrs`; specifically, the `thin_start` and `thin_interval` attributes). The samples are flattened into a 1D array."
276+
"If we provide no other arguments, `read_samples` will load all of the independent samples post burn-in. That is, it will get samples from all walkers, starting from the burn in iteration, and thinned by the autocorrelation time. The samples are flattened into a 1D array."
292277
]
293278
},
294279
{
@@ -313,7 +298,7 @@
313298
"cell_type": "markdown",
314299
"metadata": {},
315300
"source": [
316-
"So, we have 7000 independent samples. What sort of object is `samples`?"
301+
"So, we have 1600 independent samples. What sort of object is `samples`?"
317302
]
318303
},
319304
{
@@ -558,7 +543,7 @@
558543
"outputs": [],
559544
"source": [
560545
"!pycbc_inference_plot_posterior \\\n",
561-
" --input-file bbh_results.hdf \\\n",
546+
" --input-file H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf \\\n",
562547
" --output-file mass1_mass2.png \\\n",
563548
" --parameters 'primary_mass(mass1, mass2):mass1' 'secondary_mass(mass1, mass2):mass2' \\\n",
564549
" --plot-scatter \\\n",
@@ -613,7 +598,7 @@
613598
"metadata": {},
614599
"outputs": [],
615600
"source": [
616-
"!pycbc_inference_plot_posterior --input-file bbh_results.hdf --file-help"
601+
"!pycbc_inference_plot_posterior --input-file H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf --file-help"
617602
]
618603
},
619604
{
@@ -660,7 +645,7 @@
660645
"outputs": [],
661646
"source": [
662647
"!pycbc_inference_extract_samples --verbose \\\n",
663-
" --input-file bbh_results.hdf \\\n",
648+
" --input-file H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf \\\n",
664649
" --output-file mass_posterior.hdf \\\n",
665650
" --parameters \\\n",
666651
" 'primary_mass(mass1, mass2):mass1' \\\n",
@@ -693,7 +678,7 @@
693678
"metadata": {},
694679
"outputs": [],
695680
"source": [
696-
"fp.keys()"
681+
"list(fp.keys())"
697682
]
698683
},
699684
{
@@ -702,7 +687,7 @@
702687
"metadata": {},
703688
"outputs": [],
704689
"source": [
705-
"fp['samples'].keys()"
690+
"list(fp['samples'].keys())"
706691
]
707692
},
708693
{
@@ -720,7 +705,7 @@
720705
"metadata": {},
721706
"outputs": [],
722707
"source": [
723-
"fp.attrs.items()"
708+
"list(fp.attrs.items())"
724709
]
725710
},
726711
{
@@ -758,7 +743,7 @@
758743
"metadata": {},
759744
"outputs": [],
760745
"source": [
761-
"!ls -lh bbh_results.hdf mass_posterior.hdf"
746+
"!ls -lh H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf mass_posterior.hdf"
762747
]
763748
},
764749
{
@@ -797,16 +782,64 @@
797782
"cell_type": "markdown",
798783
"metadata": {},
799784
"source": [
800-
"### Challenge:\n",
801-
"Use the `--expected-parameters` option to put red lines at the injected values in the above plot. Read the output of `--help` to see the syntax that you need to provide."
785+
"### Extracting all parameters using `'*'`\n",
786+
"When we provided specific parameters to extract to `pycbc_inference_extract_samples`, only the parameters we specified were extracted. We can get all additionaly parameters by passing `'*'` to the `--parameters` option. Let's try it:"
787+
]
788+
},
789+
{
790+
"cell_type": "code",
791+
"execution_count": null,
792+
"metadata": {},
793+
"outputs": [],
794+
"source": [
795+
"!pycbc_inference_extract_samples --verbose \\\n",
796+
" --input-file H1L1-INFERENCE_EMCEE_PT_0-1126259200-400.hdf \\\n",
797+
" --output-file posterior.hdf \\\n",
798+
" --parameters \\\n",
799+
" 'primary_mass(mass1, mass2):mass1' \\\n",
800+
" 'secondary_mass(mass1, mass2):mass2' \\\n",
801+
" 'mchirp_from_mass1_mass2(mass1, mass2):mchirp' \\\n",
802+
" 'eta_from_mass1_mass2(mass1, mass2):eta' \\\n",
803+
" '*' \\\n",
804+
" --skip-groups data sampler_info --force"
805+
]
806+
},
807+
{
808+
"cell_type": "markdown",
809+
"metadata": {},
810+
"source": [
811+
"Let's load the file and check that we have all the parameters in the samples group:"
812+
]
813+
},
814+
{
815+
"cell_type": "code",
816+
"execution_count": null,
817+
"metadata": {},
818+
"outputs": [],
819+
"source": [
820+
"fp = loadfile('posterior.hdf', 'r')\n",
821+
"print(sorted(fp['samples'].keys()))"
822+
]
823+
},
824+
{
825+
"cell_type": "markdown",
826+
"metadata": {},
827+
"source": [
828+
"We do! But...\n",
829+
"\n",
830+
"**Careful:** When we created this posterior file, we applied the `primary_mass` and `secondary_mass` functions to ensure that `mass1 >= mass2`. But we did not do the same for the spin parameters. This means that `spin1_*` and `spin2_*` are no longer associated with their correct objects. To ensure that `spin1_*` is associated with the larger object and `spin2_*` the smaller, we can use the [primary_spin](http://pycbc.org/pycbc/latest/html/pycbc.html#pycbc.conversions.primary_spin) and [secondary_spin](http://pycbc.org/pycbc/latest/html/pycbc.html#pycbc.conversions.secondary_spin) functions.\n",
831+
"\n",
832+
"### Challenge\n",
833+
"\n",
834+
"Recreate the `posterior.hdf` file, but this time use the `primary_spin` and `secondary_spin` functions to ensure that all `spin1_*` and `spin2_*` parmaeters are associated with the larger and smaller masses, respectively. Then use the resulting posterior file to plot the z-components of the spin of each object. (*Hint*: to plot the z-components, you need to multiply the magnitude of each object's spin (`spin1_a` and `spin2_a`) with the cosine of its polar angle (`spin1_polar` and `spin2_polar`)."
802835
]
803836
}
804837
],
805838
"metadata": {
806839
"kernelspec": {
807-
"display_name": "Python 3",
840+
"display_name": "Python 3.7 (py37)",
808841
"language": "python",
809-
"name": "python3"
842+
"name": "py37"
810843
},
811844
"language_info": {
812845
"codemirror_mode": {
@@ -818,7 +851,7 @@
818851
"name": "python",
819852
"nbconvert_exporter": "python",
820853
"pygments_lexer": "ipython3",
821-
"version": "3.6.2"
854+
"version": "3.7.4"
822855
}
823856
},
824857
"nbformat": 4,

0 commit comments

Comments
 (0)