lalsuite 7.26.2.dev20251210__cp312-cp312-macosx_12_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lal/.dylibs/Python +0 -0
- lal/.dylibs/libaec.0.dylib +0 -0
- lal/.dylibs/libbrotlicommon.1.2.0.dylib +0 -0
- lal/.dylibs/libbrotlidec.1.2.0.dylib +0 -0
- lal/.dylibs/libcfitsio.10.4.4.1.dylib +0 -0
- lal/.dylibs/libcrypto.3.dylib +0 -0
- lal/.dylibs/libcurl.4.dylib +0 -0
- lal/.dylibs/libfftw3.3.dylib +0 -0
- lal/.dylibs/libfftw3f.3.dylib +0 -0
- lal/.dylibs/libframel.8.48.4.dylib +0 -0
- lal/.dylibs/libgsl.28.dylib +0 -0
- lal/.dylibs/libgslcblas.0.dylib +0 -0
- lal/.dylibs/libhdf5.310.dylib +0 -0
- lal/.dylibs/libhdf5_hl.310.dylib +0 -0
- lal/.dylibs/libiconv.2.dylib +0 -0
- lal/.dylibs/libidn2.0.dylib +0 -0
- lal/.dylibs/libintl.8.dylib +0 -0
- lal/.dylibs/liblal.20.dylib +0 -0
- lal/.dylibs/liblalburst.8.dylib +0 -0
- lal/.dylibs/liblalframe.14.dylib +0 -0
- lal/.dylibs/liblalinference.23.dylib +0 -0
- lal/.dylibs/liblalinspiral.18.dylib +0 -0
- lal/.dylibs/liblalmetaio.11.dylib +0 -0
- lal/.dylibs/liblalpulsar.30.dylib +0 -0
- lal/.dylibs/liblalsimulation.37.dylib +0 -0
- lal/.dylibs/liblalsupport.14.dylib +0 -0
- lal/.dylibs/libmetaio.1.dylib +0 -0
- lal/.dylibs/libnghttp2.14.dylib +0 -0
- lal/.dylibs/libpsl.5.dylib +0 -0
- lal/.dylibs/libssl.3.dylib +0 -0
- lal/.dylibs/libsz.2.dylib +0 -0
- lal/.dylibs/libunistring.5.dylib +0 -0
- lal/.dylibs/libz.1.3.1.dylib +0 -0
- lal/.dylibs/libzstd.1.5.7.dylib +0 -0
- lal/__init__.py +145 -0
- lal/_lal.cpython-312-darwin.so +0 -0
- lal/_lal_swig.py +12 -0
- lal/antenna.py +1200 -0
- lal/git_version.py +64 -0
- lal/gpstime.py +233 -0
- lal/iterutils.py +408 -0
- lal/pipeline.py +3139 -0
- lal/rate.py +2455 -0
- lal/series.py +244 -0
- lal/utils/__init__.py +29 -0
- lal/utils/cache.py +379 -0
- lal/utils/series.py +277 -0
- lalapps/__init__.py +26 -0
- lalapps/bin/lal_cache +0 -0
- lalapps/bin/lal_fftw_wisdom +0 -0
- lalapps/bin/lal_fftwf_wisdom +0 -0
- lalapps/bin/lal_simd_detect +0 -0
- lalapps/bin/lal_tconvert +0 -0
- lalapps/bin/lal_version +0 -0
- lalapps/bin/lalapps_ComputeAntennaPattern +16 -0
- lalapps/bin/lalapps_ComputeFstatBenchmark +16 -0
- lalapps/bin/lalapps_ComputeFstatLatticeCount +16 -0
- lalapps/bin/lalapps_ComputeFstatMCUpperLimit +16 -0
- lalapps/bin/lalapps_ComputeFstatistic_v2 +16 -0
- lalapps/bin/lalapps_ComputePSD +16 -0
- lalapps/bin/lalapps_CopySFTs +16 -0
- lalapps/bin/lalapps_DistanceVsMass +0 -0
- lalapps/bin/lalapps_DriveHoughMulti +16 -0
- lalapps/bin/lalapps_FstatMetric_v2 +16 -0
- lalapps/bin/lalapps_HierarchSearchGCT +16 -0
- lalapps/bin/lalapps_HierarchicalSearch +16 -0
- lalapps/bin/lalapps_MakeSFTDAG +16 -0
- lalapps/bin/lalapps_MakeSFTs +16 -0
- lalapps/bin/lalapps_Makefakedata_v4 +16 -0
- lalapps/bin/lalapps_Makefakedata_v5 +16 -0
- lalapps/bin/lalapps_PredictFstat +16 -0
- lalapps/bin/lalapps_PrintDetectorState +16 -0
- lalapps/bin/lalapps_SFTclean +16 -0
- lalapps/bin/lalapps_SFTvalidate +16 -0
- lalapps/bin/lalapps_StringAddFrame +0 -0
- lalapps/bin/lalapps_StringSearch +0 -0
- lalapps/bin/lalapps_Weave +16 -0
- lalapps/bin/lalapps_WeaveCompare +16 -0
- lalapps/bin/lalapps_WeaveConcat +16 -0
- lalapps/bin/lalapps_WeaveSetup +16 -0
- lalapps/bin/lalapps_WriteSFTsfromSFDBs +16 -0
- lalapps/bin/lalapps_animate +0 -0
- lalapps/bin/lalapps_binj +0 -0
- lalapps/bin/lalapps_blindinj +0 -0
- lalapps/bin/lalapps_cache +16 -0
- lalapps/bin/lalapps_calfacs +0 -0
- lalapps/bin/lalapps_cbc_stochasticbank +0 -0
- lalapps/bin/lalapps_chirplen +0 -0
- lalapps/bin/lalapps_coh_PTF_inspiral +0 -0
- lalapps/bin/lalapps_coinj +0 -0
- lalapps/bin/lalapps_combine_crosscorr_toplists +16 -0
- lalapps/bin/lalapps_compareFstats +16 -0
- lalapps/bin/lalapps_compareSFTs +16 -0
- lalapps/bin/lalapps_create_time_correction_ephemeris +16 -0
- lalapps/bin/lalapps_dumpSFT +16 -0
- lalapps/bin/lalapps_effdist +0 -0
- lalapps/bin/lalapps_exc_resp +0 -0
- lalapps/bin/lalapps_fftw_wisdom +16 -0
- lalapps/bin/lalapps_fftwf_wisdom +16 -0
- lalapps/bin/lalapps_fits_header_getval +16 -0
- lalapps/bin/lalapps_fits_header_list +16 -0
- lalapps/bin/lalapps_fits_overview +16 -0
- lalapps/bin/lalapps_fits_table_list +16 -0
- lalapps/bin/lalapps_fr_ninja +0 -0
- lalapps/bin/lalapps_frextr +0 -0
- lalapps/bin/lalapps_frinfo +0 -0
- lalapps/bin/lalapps_frjoin +0 -0
- lalapps/bin/lalapps_frread +0 -0
- lalapps/bin/lalapps_frview +0 -0
- lalapps/bin/lalapps_gwf2xml +0 -0
- lalapps/bin/lalapps_heterodyne_pulsar +16 -0
- lalapps/bin/lalapps_inspawgfile +0 -0
- lalapps/bin/lalapps_inspfrinj +0 -0
- lalapps/bin/lalapps_inspinj +0 -0
- lalapps/bin/lalapps_inspiralDistance +0 -0
- lalapps/bin/lalapps_knope +16 -0
- lalapps/bin/lalapps_knope_automation_script +16 -0
- lalapps/bin/lalapps_knope_collate_results +16 -0
- lalapps/bin/lalapps_knope_result_page +16 -0
- lalapps/bin/lalapps_makeblindinj +85 -0
- lalapps/bin/lalapps_makeblindinj_himass +67 -0
- lalapps/bin/lalapps_ninja +0 -0
- lalapps/bin/lalapps_path2cache +16 -0
- lalapps/bin/lalapps_power +0 -0
- lalapps/bin/lalapps_pulsar_crosscorr_v2 +16 -0
- lalapps/bin/lalapps_pulsar_frequency_evolution +16 -0
- lalapps/bin/lalapps_pulsar_parameter_estimation_nested +16 -0
- lalapps/bin/lalapps_random_bank +0 -0
- lalapps/bin/lalapps_randombank +0 -0
- lalapps/bin/lalapps_run_pulsar_crosscorr_v2 +16 -0
- lalapps/bin/lalapps_searchsum2cache +16 -0
- lalapps/bin/lalapps_spec_avg +16 -0
- lalapps/bin/lalapps_spec_avg_long +16 -0
- lalapps/bin/lalapps_spec_coherence +16 -0
- lalapps/bin/lalapps_spininj +0 -0
- lalapps/bin/lalapps_splitSFTs +16 -0
- lalapps/bin/lalapps_splitbank +0 -0
- lalapps/bin/lalapps_ssbtodetector +16 -0
- lalapps/bin/lalapps_synthesizeBstatMC +16 -0
- lalapps/bin/lalapps_synthesizeLVStats +16 -0
- lalapps/bin/lalapps_synthesizeTransientStats +16 -0
- lalapps/bin/lalapps_tconvert +16 -0
- lalapps/bin/lalapps_tmpltbank +0 -0
- lalapps/bin/lalapps_version +0 -0
- lalapps/bin/lalapps_xtefitstoframe +0 -0
- lalapps/bin/lalburst_version +0 -0
- lalapps/bin/lalfr-cat +0 -0
- lalapps/bin/lalfr-cksum +0 -0
- lalapps/bin/lalfr-cut +0 -0
- lalapps/bin/lalfr-dump +0 -0
- lalapps/bin/lalfr-fmt +0 -0
- lalapps/bin/lalfr-paste +0 -0
- lalapps/bin/lalfr-print +0 -0
- lalapps/bin/lalfr-split +0 -0
- lalapps/bin/lalfr-stat +0 -0
- lalapps/bin/lalfr-stream +0 -0
- lalapps/bin/lalfr-vis +0 -0
- lalapps/bin/lalframe_version +0 -0
- lalapps/bin/lalinference_bench +0 -0
- lalapps/bin/lalinference_burst +0 -0
- lalapps/bin/lalinference_datadump +0 -0
- lalapps/bin/lalinference_injectedlike +0 -0
- lalapps/bin/lalinference_mpi_wrapper +59 -0
- lalapps/bin/lalinference_nest +0 -0
- lalapps/bin/lalinference_version +0 -0
- lalapps/bin/lalinspiral_version +0 -0
- lalapps/bin/lalmetaio_version +0 -0
- lalapps/bin/lalpulsar_ComputeAntennaPattern +0 -0
- lalapps/bin/lalpulsar_ComputeFstatBenchmark +0 -0
- lalapps/bin/lalpulsar_ComputeFstatLatticeCount +0 -0
- lalapps/bin/lalpulsar_ComputeFstatMCUpperLimit +0 -0
- lalapps/bin/lalpulsar_ComputeFstatistic_v2 +0 -0
- lalapps/bin/lalpulsar_ComputePSD +0 -0
- lalapps/bin/lalpulsar_DriveHoughMulti +0 -0
- lalapps/bin/lalpulsar_FstatMetric_v2 +0 -0
- lalapps/bin/lalpulsar_HierarchSearchGCT +0 -0
- lalapps/bin/lalpulsar_HierarchicalSearch +0 -0
- lalapps/bin/lalpulsar_MakeSFTs +0 -0
- lalapps/bin/lalpulsar_Makefakedata_v4 +0 -0
- lalapps/bin/lalpulsar_Makefakedata_v5 +0 -0
- lalapps/bin/lalpulsar_PredictFstat +0 -0
- lalapps/bin/lalpulsar_PrintDetectorState +0 -0
- lalapps/bin/lalpulsar_SFTclean +0 -0
- lalapps/bin/lalpulsar_SFTvalidate +0 -0
- lalapps/bin/lalpulsar_Weave +0 -0
- lalapps/bin/lalpulsar_WeaveCompare +0 -0
- lalapps/bin/lalpulsar_WeaveConcat +0 -0
- lalapps/bin/lalpulsar_WeaveSetup +0 -0
- lalapps/bin/lalpulsar_WriteSFTsfromSFDBs +0 -0
- lalapps/bin/lalpulsar_compareFstats +0 -0
- lalapps/bin/lalpulsar_compareSFTs +0 -0
- lalapps/bin/lalpulsar_create_time_correction_ephemeris +0 -0
- lalapps/bin/lalpulsar_crosscorr_v2 +0 -0
- lalapps/bin/lalpulsar_dumpSFT +0 -0
- lalapps/bin/lalpulsar_fits_header_getval +0 -0
- lalapps/bin/lalpulsar_fits_header_list +0 -0
- lalapps/bin/lalpulsar_fits_overview +0 -0
- lalapps/bin/lalpulsar_fits_table_list +0 -0
- lalapps/bin/lalpulsar_frequency_evolution +0 -0
- lalapps/bin/lalpulsar_heterodyne +0 -0
- lalapps/bin/lalpulsar_parameter_estimation_nested +0 -0
- lalapps/bin/lalpulsar_spec_avg +0 -0
- lalapps/bin/lalpulsar_spec_avg_long +0 -0
- lalapps/bin/lalpulsar_spec_coherence +0 -0
- lalapps/bin/lalpulsar_splitSFTs +0 -0
- lalapps/bin/lalpulsar_ssbtodetector +0 -0
- lalapps/bin/lalpulsar_synthesizeBstatMC +0 -0
- lalapps/bin/lalpulsar_synthesizeLVStats +0 -0
- lalapps/bin/lalpulsar_synthesizeTransientStats +0 -0
- lalapps/bin/lalpulsar_version +0 -0
- lalapps/bin/lalsim-bh-qnmode +0 -0
- lalapps/bin/lalsim-bh-ringdown +0 -0
- lalapps/bin/lalsim-bh-sphwf +0 -0
- lalapps/bin/lalsim-burst +0 -0
- lalapps/bin/lalsim-detector-noise +0 -0
- lalapps/bin/lalsim-detector-strain +0 -0
- lalapps/bin/lalsim-inject +0 -0
- lalapps/bin/lalsim-inspiral +0 -0
- lalapps/bin/lalsim-ns-eos-table +0 -0
- lalapps/bin/lalsim-ns-mass-radius +0 -0
- lalapps/bin/lalsim-ns-params +0 -0
- lalapps/bin/lalsim-sgwb +0 -0
- lalapps/bin/lalsim-unicorn +0 -0
- lalapps/bin/lalsimulation_version +0 -0
- lalapps/cosmicstring.py +691 -0
- lalapps/data/BNSMasses.dat +65022 -0
- lalapps/data/CorrelationMatrix.csv +15 -0
- lalapps/data/LALSimNeutronStarEOS_ABHT_QMC_RMF1_META.dat +1882 -0
- lalapps/data/LALSimNeutronStarEOS_ABHT_QMC_RMF2_META.dat +1939 -0
- lalapps/data/LALSimNeutronStarEOS_ABHT_QMC_RMF3_META.dat +1784 -0
- lalapps/data/LALSimNeutronStarEOS_ABHT_QMC_RMF4_META.dat +2074 -0
- lalapps/data/LALSimNeutronStarEOS_ALF1.dat +435 -0
- lalapps/data/LALSimNeutronStarEOS_ALF2.dat +453 -0
- lalapps/data/LALSimNeutronStarEOS_ALF3.dat +441 -0
- lalapps/data/LALSimNeutronStarEOS_ALF4.dat +441 -0
- lalapps/data/LALSimNeutronStarEOS_AP1.dat +212 -0
- lalapps/data/LALSimNeutronStarEOS_AP2.dat +212 -0
- lalapps/data/LALSimNeutronStarEOS_AP3.dat +212 -0
- lalapps/data/LALSimNeutronStarEOS_AP4.dat +210 -0
- lalapps/data/LALSimNeutronStarEOS_APR.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_APR4_EPP.dat +1447 -0
- lalapps/data/LALSimNeutronStarEOS_BBB2.dat +84 -0
- lalapps/data/LALSimNeutronStarEOS_BGN1H1.dat +123 -0
- lalapps/data/LALSimNeutronStarEOS_BHF_BBB2.dat +499 -0
- lalapps/data/LALSimNeutronStarEOS_BL_CHIRAL_META.dat +1534 -0
- lalapps/data/LALSimNeutronStarEOS_BPAL12.dat +61 -0
- lalapps/data/LALSimNeutronStarEOS_BSK19.dat +310 -0
- lalapps/data/LALSimNeutronStarEOS_BSK20.dat +310 -0
- lalapps/data/LALSimNeutronStarEOS_BSK21.dat +310 -0
- lalapps/data/LALSimNeutronStarEOS_ENG.dat +108 -0
- lalapps/data/LALSimNeutronStarEOS_FPS.dat +129 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_BSK14_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_DHSL59_BSK24.dat +1009 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_DHSL69_BSK24.dat +1009 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_F0_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_H1_BSK24.dat +1009 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_H2_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_H3_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_H4_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_H5_BSK24.dat +1009 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_LN55_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GMSR_SLY5_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GNH3.dat +71 -0
- lalapps/data/LALSimNeutronStarEOS_GPPVA_DD2_BSK24.dat +1009 -0
- lalapps/data/LALSimNeutronStarEOS_GPPVA_DDME2_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GPPVA_FSU2H_BSK24.dat +1009 -0
- lalapps/data/LALSimNeutronStarEOS_GPPVA_FSU2_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GPPVA_NL3WRL55_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_GS1.dat +136 -0
- lalapps/data/LALSimNeutronStarEOS_GS2.dat +100 -0
- lalapps/data/LALSimNeutronStarEOS_H1.dat +114 -0
- lalapps/data/LALSimNeutronStarEOS_H2.dat +114 -0
- lalapps/data/LALSimNeutronStarEOS_H3.dat +98 -0
- lalapps/data/LALSimNeutronStarEOS_H4.dat +664 -0
- lalapps/data/LALSimNeutronStarEOS_H5.dat +703 -0
- lalapps/data/LALSimNeutronStarEOS_H6.dat +509 -0
- lalapps/data/LALSimNeutronStarEOS_H7.dat +703 -0
- lalapps/data/LALSimNeutronStarEOS_HQC18.dat +388 -0
- lalapps/data/LALSimNeutronStarEOS_KDE0V.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_KDE0V1.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_KDE0V1_BSK24.dat +1388 -0
- lalapps/data/LALSimNeutronStarEOS_KDE0V_BSK24.dat +1398 -0
- lalapps/data/LALSimNeutronStarEOS_MPA1.dat +102 -0
- lalapps/data/LALSimNeutronStarEOS_MS1.dat +122 -0
- lalapps/data/LALSimNeutronStarEOS_MS1B.dat +126 -0
- lalapps/data/LALSimNeutronStarEOS_MS1B_PP.dat +1447 -0
- lalapps/data/LALSimNeutronStarEOS_MS1_PP.dat +1447 -0
- lalapps/data/LALSimNeutronStarEOS_MS2.dat +48 -0
- lalapps/data/LALSimNeutronStarEOS_PAL6.dat +148 -0
- lalapps/data/LALSimNeutronStarEOS_PCL2.dat +134 -0
- lalapps/data/LALSimNeutronStarEOS_PCP_BSK24_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_PS.dat +165 -0
- lalapps/data/LALSimNeutronStarEOS_QMC700.dat +117 -0
- lalapps/data/LALSimNeutronStarEOS_RG_SLY4_BSK24.dat +1010 -0
- lalapps/data/LALSimNeutronStarEOS_RS.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_RS_BSK24.dat +1356 -0
- lalapps/data/LALSimNeutronStarEOS_SK255.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SK255_BSK24.dat +1066 -0
- lalapps/data/LALSimNeutronStarEOS_SK272.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKA.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKA_BSK24.dat +1433 -0
- lalapps/data/LALSimNeutronStarEOS_SKB.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKB_BSK24.dat +1373 -0
- lalapps/data/LALSimNeutronStarEOS_SKI2.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKI2_BSK24.dat +1348 -0
- lalapps/data/LALSimNeutronStarEOS_SKI3.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKI3_BSK24.dat +1355 -0
- lalapps/data/LALSimNeutronStarEOS_SKI4.dat +497 -0
- lalapps/data/LALSimNeutronStarEOS_SKI4_BSK24.dat +1348 -0
- lalapps/data/LALSimNeutronStarEOS_SKI5.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKI6.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKI6_BSK24.dat +1358 -0
- lalapps/data/LALSimNeutronStarEOS_SKMP.dat +498 -0
- lalapps/data/LALSimNeutronStarEOS_SKOP.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SKOP_BSK24.dat +1373 -0
- lalapps/data/LALSimNeutronStarEOS_SLY.dat +99 -0
- lalapps/data/LALSimNeutronStarEOS_SLY2.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SLY230A.dat +500 -0
- lalapps/data/LALSimNeutronStarEOS_SLY230A_BSK24.dat +1116 -0
- lalapps/data/LALSimNeutronStarEOS_SLY2_BSK24.dat +1106 -0
- lalapps/data/LALSimNeutronStarEOS_SLY4.dat +100 -0
- lalapps/data/LALSimNeutronStarEOS_SLY9.dat +498 -0
- lalapps/data/LALSimNeutronStarEOS_SLY9_BSK24.dat +1083 -0
- lalapps/data/LALSimNeutronStarEOS_SQM1.dat +176 -0
- lalapps/data/LALSimNeutronStarEOS_SQM2.dat +180 -0
- lalapps/data/LALSimNeutronStarEOS_SQM3.dat +176 -0
- lalapps/data/LALSimNeutronStarEOS_WFF1.dat +109 -0
- lalapps/data/LALSimNeutronStarEOS_WFF2.dat +109 -0
- lalapps/data/LALSimNeutronStarEOS_WFF3.dat +107 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_DDLZ1_BSK24.dat +1227 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_DDME2_BSK24.dat +1272 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_DDMEX_BSK24.dat +1280 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_GM1_BSK24.dat +1288 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_MTVTC_BSK24.dat +1288 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_NL3_BSK24.dat +1230 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_PKDD_BSK24.dat +1288 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_TM1_BSK24.dat +1288 -0
- lalapps/data/LALSimNeutronStarEOS_XMLSLZ_TW99_BSK24.dat +1288 -0
- lalapps/data/LIGO-P1200087-v18-AdV_BNS_OPTIMIZED.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_DESIGN.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_EARLY_HIGH.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_EARLY_LOW.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_LATE_HIGH.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_LATE_LOW.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_MID_HIGH.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-AdV_MID_LOW.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_BNS_OPTIMIZED.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_DESIGN.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_EARLY_HIGH.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_EARLY_LOW.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_LATE_HIGH.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_LATE_LOW.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_MID_HIGH.txt +3000 -0
- lalapps/data/LIGO-P1200087-v18-aLIGO_MID_LOW.txt +3000 -0
- lalapps/data/LIGO-P1600143-v18-CE.txt +3000 -0
- lalapps/data/LIGO-P1600143-v18-CE_Pessimistic.txt +3000 -0
- lalapps/data/LIGO-P1600143-v18-CE_Wideband.txt +3000 -0
- lalapps/data/LIGO-P1600143-v18-ET_D.txt +3000 -0
- lalapps/data/LIGO-T0900288-v3-BHBH_20deg.txt +3000 -0
- lalapps/data/LIGO-T0900288-v3-High_Freq.txt +3000 -0
- lalapps/data/LIGO-T0900288-v3-NO_SRM.txt +3000 -0
- lalapps/data/LIGO-T0900288-v3-NSNS_Opt.txt +3000 -0
- lalapps/data/LIGO-T0900288-v3-ZERO_DET_high_P.txt +3000 -0
- lalapps/data/LIGO-T0900288-v3-ZERO_DET_low_P.txt +3000 -0
- lalapps/data/LIGO-T1600593-v1-KAGRA_Design.txt +4000 -0
- lalapps/data/LIGO-T1600593-v1-KAGRA_Early.txt +4000 -0
- lalapps/data/LIGO-T1600593-v1-KAGRA_Late.txt +4000 -0
- lalapps/data/LIGO-T1600593-v1-KAGRA_Mid.txt +4000 -0
- lalapps/data/LIGO-T1600593-v1-KAGRA_Opening.txt +4000 -0
- lalapps/data/LIGO-T1800042-v5-aLIGO_APLUS.txt +3000 -0
- lalapps/data/LIGO-T1800044-v5-aLIGO_DESIGN.txt +3000 -0
- lalapps/data/LIGO-T1800545-v1-AdV_O3low.txt +3000 -0
- lalapps/data/LIGO-T1800545-v1-AdV_O4.txt +3000 -0
- lalapps/data/LIGO-T1800545-v1-AdV_O4intermediate.txt +3000 -0
- lalapps/data/LIGO-T1800545-v1-KAGRA_128Mpc.txt +1000 -0
- lalapps/data/LIGO-T1800545-v1-KAGRA_25Mpc.txt +1000 -0
- lalapps/data/LIGO-T1800545-v1-KAGRA_80Mpc.txt +1000 -0
- lalapps/data/LIGO-T1800545-v1-aLIGO_140Mpc.txt +1000 -0
- lalapps/data/LIGO-T1800545-v1-aLIGO_175Mpc.txt +2792 -0
- lalapps/data/LIGO-T1800545-v1-aLIGO_O3low.txt +2792 -0
- lalapps/data/bimodalMeans.csv +3 -0
- lalapps/data/config_tiger_example.ini +150 -0
- lalapps/data/fiducialBBH.xml +67 -0
- lalapps/data/fiducialBNS.xml +67 -0
- lalapps/data/inspsrcs100Mpc.errors +38735 -0
- lalapps/data/lalinference_pipe_example.ini +573 -0
- lalapps/data/lib_pipe_example.ini +303 -0
- lalapps/data/power_pipe.ini +129 -0
- lalapps/data/unimodalMeans.csv +2 -0
- lalapps/git_version.py +64 -0
- lalburst/SimBurstUtils.py +324 -0
- lalburst/SnglBurstUtils.py +367 -0
- lalburst/__init__.py +7 -0
- lalburst/_lalburst.cpython-312-darwin.so +0 -0
- lalburst/_lalburst_swig.py +16 -0
- lalburst/binjfind.py +824 -0
- lalburst/bucluster.py +409 -0
- lalburst/burca.py +315 -0
- lalburst/burca_tailor.py +349 -0
- lalburst/cafe.py +579 -0
- lalburst/calc_likelihood.py +145 -0
- lalburst/cs_gamma.cpython-312-darwin.so +0 -0
- lalburst/date.py +118 -0
- lalburst/git_version.py +64 -0
- lalburst/offsetvector.py +278 -0
- lalburst/packing.py +170 -0
- lalburst/power.py +1457 -0
- lalburst/snglcluster.py +136 -0
- lalburst/snglcoinc.py +2637 -0
- lalburst/stringutils.py +607 -0
- lalburst/timeslides.py +236 -0
- lalframe/__init__.py +7 -0
- lalframe/_lalframe.cpython-312-darwin.so +0 -0
- lalframe/_lalframe_swig.py +14 -0
- lalframe/frread.py +324 -0
- lalframe/git_version.py +64 -0
- lalframe/utils/__init__.py +25 -0
- lalframe/utils/frtools.py +61 -0
- lalinference/__init__.py +7 -0
- lalinference/_bayespputils.cpython-312-darwin.so +0 -0
- lalinference/_lalinference.cpython-312-darwin.so +0 -0
- lalinference/_lalinference_swig.py +19 -0
- lalinference/bayespputils.py +7479 -0
- lalinference/bayestar/__init__.py +2 -0
- lalinference/bayestar/deprecation.py +72 -0
- lalinference/git_version.py +64 -0
- lalinference/imrtgr/__init__.py +0 -0
- lalinference/imrtgr/imrtgrutils.py +168 -0
- lalinference/imrtgr/nrutils.py +1366 -0
- lalinference/imrtgr/pneqns.py +250 -0
- lalinference/io/__init__.py +31 -0
- lalinference/io/hdf5.py +365 -0
- lalinference/lalinference_pipe_utils.py +3617 -0
- lalinference/nest2pos.py +151 -0
- lalinference/plot/__init__.py +34 -0
- lalinference/plot/spindisk.py +104 -0
- lalinference/tiger/__init__.py +0 -0
- lalinference/tiger/make_injtimes.py +634 -0
- lalinference/tiger/omegascans_dag.py +691 -0
- lalinference/tiger/postproc.py +1338 -0
- lalinference/wrapper.py +231 -0
- lalinspiral/__init__.py +7 -0
- lalinspiral/_lalinspiral.cpython-312-darwin.so +0 -0
- lalinspiral/_lalinspiral_swig.py +18 -0
- lalinspiral/_thinca.cpython-312-darwin.so +0 -0
- lalinspiral/git_version.py +64 -0
- lalinspiral/inspinjfind.py +485 -0
- lalinspiral/thinca.py +509 -0
- lalmetaio/__init__.py +7 -0
- lalmetaio/_lalmetaio.cpython-312-darwin.so +0 -0
- lalmetaio/_lalmetaio_swig.py +14 -0
- lalmetaio/git_version.py +64 -0
- lalpulsar/NstarTools.py +259 -0
- lalpulsar/PulsarParametersWrapper.py +938 -0
- lalpulsar/__init__.py +7 -0
- lalpulsar/_lalpulsar.cpython-312-darwin.so +0 -0
- lalpulsar/_lalpulsar_swig.py +17 -0
- lalpulsar/git_version.py +64 -0
- lalpulsar/knope_utils.py +6497 -0
- lalpulsar/lineFileParser.py +264 -0
- lalpulsar/metric_utils.py +78 -0
- lalpulsar/piecewise_model/__init__.py +7 -0
- lalpulsar/piecewise_model/basis_functions.py +156 -0
- lalpulsar/piecewise_model/class_definitions.py +323 -0
- lalpulsar/piecewise_model/errors.py +37 -0
- lalpulsar/piecewise_model/estimating_knots.py +833 -0
- lalpulsar/piecewise_model/gte_and_other_methods.py +189 -0
- lalpulsar/piecewise_model/mols_for_gte.py +269 -0
- lalpulsar/piecewise_model/pw_fstat.py +813 -0
- lalpulsar/piecewise_model/pw_model_simulations.py +156 -0
- lalpulsar/piecewise_model/sampling_methods.py +186 -0
- lalpulsar/piecewise_model/semicoherent_metric_methods.py +375 -0
- lalpulsar/piecewise_model/tbank_estimates.py +293 -0
- lalpulsar/public_sft_directory.py +82 -0
- lalpulsar/pulsarhtmlutils.py +1395 -0
- lalpulsar/pulsarpputils.py +3638 -0
- lalpulsar/simulateCW.py +602 -0
- lalpulsar/simulateHeterodynedCW.py +591 -0
- lalsimulation/__init__.py +7 -0
- lalsimulation/_lalsimulation.cpython-312-darwin.so +0 -0
- lalsimulation/_lalsimulation_swig.py +14 -0
- lalsimulation/git_version.py +64 -0
- lalsimulation/gwsignal/__init__.py +9 -0
- lalsimulation/gwsignal/core/__init__.py +2 -0
- lalsimulation/gwsignal/core/conditioning_subroutines.py +196 -0
- lalsimulation/gwsignal/core/errors.py +136 -0
- lalsimulation/gwsignal/core/gw.py +206 -0
- lalsimulation/gwsignal/core/parameter_conventions.py +122 -0
- lalsimulation/gwsignal/core/utils.py +329 -0
- lalsimulation/gwsignal/core/waveform.py +725 -0
- lalsimulation/gwsignal/core/waveform_conditioning.py +455 -0
- lalsimulation/gwsignal/models/__init__.py +29 -0
- lalsimulation/gwsignal/models/pyseobnr_model.py +452 -0
- lalsimulation/nrfits/NRSur3dq8Remnant.py +92 -0
- lalsimulation/nrfits/NRSur7dq4Remnant.py +469 -0
- lalsimulation/nrfits/__init__.py +1 -0
- lalsimulation/nrfits/eval_fits.py +364 -0
- lalsimulation/nrfits/nrfits.py +78 -0
- lalsimulation/nrfits/pn_spin_evolution_wrapper.py +92 -0
- lalsimulation/nrfits/quaternion_utils.py +74 -0
- lalsimulation/tilts_at_infinity/__init__.py +2 -0
- lalsimulation/tilts_at_infinity/calc_tilts_prec_avg_regularized.py +1424 -0
- lalsimulation/tilts_at_infinity/hybrid_spin_evolution.py +461 -0
- lalsimulation/tilts_at_infinity/tilts_at_infinity_utils.py +167 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesBurstPPAnalysis +305 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesBurstPostProc +1364 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesCombinePTMCMCh5s +100 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesCombinePosteriors +235 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesCompPos +1121 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesDIEvidence +68 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesGraceDBinfo +182 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesMCMC2pos +314 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesPPAnalysis +322 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesPlotSpinDisk +42 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesPosToSimBurst +227 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesPosToSimInspiral +307 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesPostProc +1345 -0
- lalsuite-7.26.2.dev20251210.data/scripts/cbcBayesThermoInt +107 -0
- lalsuite-7.26.2.dev20251210.data/scripts/imrtgr_imr_consistency_test +796 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_cache +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_fftw_wisdom +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_fftwf_wisdom +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_path2cache +148 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_searchsum2cache +172 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_simd_detect +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_tconvert +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lal_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ComputeAntennaPattern +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ComputeFstatBenchmark +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ComputeFstatLatticeCount +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ComputeFstatMCUpperLimit +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ComputeFstatistic_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ComputePSD +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_CopySFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_DistanceVsMass +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_DriveHoughMulti +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_FstatMetric_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_HierarchSearchGCT +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_HierarchicalSearch +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_MakeSFTDAG +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_MakeSFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_Makefakedata_v4 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_Makefakedata_v5 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_PredictFstat +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_PrintDetectorState +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_SFTclean +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_SFTvalidate +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_StringAddFrame +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_StringSearch +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_Weave +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_WeaveCompare +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_WeaveConcat +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_WeaveSetup +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_WriteSFTsfromSFDBs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_animate +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_binj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_blindinj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_cache +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_cafe +99 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_calfacs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_cbc_stochasticbank +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_chirplen +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_coh_PTF_inspiral +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_coinj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_combine_crosscorr_toplists +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_compareFstats +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_compareSFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_cosmicstring_pipe +525 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_create_time_correction_ephemeris +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_dumpSFT +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_effdist +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_exc_resp +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fftw_wisdom +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fftwf_wisdom +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fits_header_getval +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fits_header_list +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fits_overview +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fits_table_list +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_fr_ninja +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_frextr +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_frinfo +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_frjoin +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_frread +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_frview +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_gwf2xml +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_heterodyne_pulsar +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_inspawgfile +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_inspfrinj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_inspinj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_inspiralDistance +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_knope +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_knope_automation_script +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_knope_collate_results +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_knope_result_page +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_makeblindinj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_makeblindinj_himass +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ninja +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_path2cache +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_power +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_power_likelihood_pipe +219 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_power_pipe +417 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_pulsar_crosscorr_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_pulsar_frequency_evolution +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_pulsar_parameter_estimation_nested +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_random_bank +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_randombank +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_run_pulsar_crosscorr_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_searchsum2cache +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_spec_avg +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_spec_avg_long +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_spec_coherence +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_spininj +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_splitSFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_splitbank +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_ssbtodetector +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_apply_vetoes +171 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_calc_likelihood +172 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_contour_plotter +141 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_contour_plotter_largeloops +133 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_cs_gamma +110 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_cs_gamma_largeloops +119 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_final +1064 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_meas_likelihood +264 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_plot_binj +543 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_string_plot_likelihood +380 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_synthesizeBstatMC +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_synthesizeLVStats +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_synthesizeTransientStats +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_tconvert +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_tmpltbank +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalapps_xtefitstoframe +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_cluster +156 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_coinc +224 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_cut +425 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_gen_timeslides +254 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_inj_pic +254 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_injfind +170 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_plot_tisi +165 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_power_calc_likelihood +182 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_power_final +1369 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_power_meas_likelihood +206 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_power_plot_binj +934 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_power_plot_binjtf +302 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalburst_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-cat +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-cksum +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-cut +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-dump +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-fmt +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-paste +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-print +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-split +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-stat +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-stream +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalfr-vis +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalframe_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_bench +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_burst +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_burst_pp_pipe +220 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_coherence_test +139 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_compute_roq_weights +404 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_cpnest +58 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_datadump +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_evolve_spins_and_append_samples +202 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_injectedlike +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_merge_posteriors +57 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_mpi_wrapper +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_multi_pipe +144 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_nest +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_nest2pos +286 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_pipe +512 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_pp_pipe +229 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_review_test +362 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinference_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinspiral_injfind +206 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinspiral_thinca +240 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalinspiral_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalmetaio_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ComputeAntennaPattern +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ComputeFstatBenchmark +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ComputeFstatLatticeCount +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ComputeFstatMCUpperLimit +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ComputeFstatistic_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ComputePSD +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_CopyPublicSFTs +216 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_DriveHoughMulti +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_FstatMetric_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_HierarchSearchGCT +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_HierarchicalSearch +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_MakeSFTDAG +1142 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_MakeSFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_Makefakedata_v4 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_Makefakedata_v5 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_MoveSFTs +208 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_PiecewiseSearch +963 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_PredictFstat +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_PrintDetectorState +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_SFTclean +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_SFTvalidate +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_Weave +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_WeaveCompare +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_WeaveConcat +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_WeaveSetup +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_WriteSFTsfromSFDBs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_compareFstats +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_compareSFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_create_time_correction_ephemeris +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_crosscorr_v2 +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_dumpSFT +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_fits_header_getval +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_fits_header_list +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_fits_overview +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_fits_table_list +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_frequency_evolution +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_heterodyne +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_knope +145 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_knope_automation_script +731 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_knope_collate_results +675 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_knope_result_page +2977 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_parameter_estimation_nested +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_spec_avg +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_spec_avg_long +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_spec_coherence +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_splitSFTs +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_ssbtodetector +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_synthesizeBstatMC +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_synthesizeLVStats +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_synthesizeTransientStats +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalpulsar_version +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-bh-qnmode +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-bh-ringdown +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-bh-sphwf +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-burst +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-detector-noise +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-detector-strain +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-inject +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-inspiral +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-ns-eos-table +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-ns-mass-radius +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-ns-params +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-sgwb +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsim-unicorn +6 -0
- lalsuite-7.26.2.dev20251210.data/scripts/lalsimulation_version +6 -0
- lalsuite-7.26.2.dev20251210.dist-info/METADATA +90 -0
- lalsuite-7.26.2.dev20251210.dist-info/RECORD +749 -0
- lalsuite-7.26.2.dev20251210.dist-info/WHEEL +6 -0
- lalsuite-7.26.2.dev20251210.dist-info/licenses/COPYING +339 -0
- lalsuite-7.26.2.dev20251210.dist-info/top_level.txt +9 -0
|
@@ -0,0 +1,2977 @@
|
|
|
1
|
+
#!python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# lalpulsar_knope_result_page.py
|
|
5
|
+
#
|
|
6
|
+
# Copyright 2015
|
|
7
|
+
# Matthew Pitkin <matthew.pitkin@ligo.org>,
|
|
8
|
+
#
|
|
9
|
+
# This program is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# This program is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with this program; if not, write to the Free Software
|
|
21
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
22
|
+
# MA 02110-1301, USA.
|
|
23
|
+
|
|
24
|
+
## \file
|
|
25
|
+
## \ingroup lalpulsar_bin_HeterodyneSearch
|
|
26
|
+
"""
|
|
27
|
+
The KNOwn Pulsar pipelinE - lalpulsar_knope_result_page
|
|
28
|
+
|
|
29
|
+
Script from creating results pages for pulsars from the known pulsar search
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import print_function, division
|
|
33
|
+
|
|
34
|
+
import argparse
|
|
35
|
+
from configparser import ConfigParser
|
|
36
|
+
import sys
|
|
37
|
+
import ast
|
|
38
|
+
import numpy as np
|
|
39
|
+
import re
|
|
40
|
+
import copy
|
|
41
|
+
import os
|
|
42
|
+
import fnmatch
|
|
43
|
+
import ast
|
|
44
|
+
import datetime
|
|
45
|
+
import json
|
|
46
|
+
from scipy import stats
|
|
47
|
+
import h5py
|
|
48
|
+
import itertools
|
|
49
|
+
|
|
50
|
+
import matplotlib
|
|
51
|
+
|
|
52
|
+
matplotlib.use("Agg")
|
|
53
|
+
|
|
54
|
+
from lalpulsar.pulsarpputils import *
|
|
55
|
+
from lalpulsar.pulsarhtmlutils import *
|
|
56
|
+
from lalinference.bayespputils import Posterior, PosteriorOneDPDF
|
|
57
|
+
from lalinference import git_version
|
|
58
|
+
|
|
59
|
+
__author__ = "Matthew Pitkin <matthew.pitkin@ligo.org>"
|
|
60
|
+
__version__ = "git id %s" % git_version.id
|
|
61
|
+
__date__ = git_version.date
|
|
62
|
+
|
|
63
|
+
# try importing scotchcorner
|
|
64
|
+
try:
|
|
65
|
+
from scotchcorner import scotchcorner
|
|
66
|
+
except ImportError:
|
|
67
|
+
print(
|
|
68
|
+
"Could no import scotchcorner: make sure scotchcorner is installed (e.g. 'pip install scotchcorner') and in the PYTHONPATH",
|
|
69
|
+
file=sys.stderr,
|
|
70
|
+
)
|
|
71
|
+
sys.exit(1)
|
|
72
|
+
|
|
73
|
+
# create format for the output page
|
|
74
|
+
htmlpage = """
|
|
75
|
+
<!DOCTYPE html>
|
|
76
|
+
<html lang="en">
|
|
77
|
+
|
|
78
|
+
<head>
|
|
79
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
|
80
|
+
<meta name="description" content="PSR {psrname}"/>
|
|
81
|
+
<meta charset="UTF-8">
|
|
82
|
+
|
|
83
|
+
<title>{title}</title>
|
|
84
|
+
|
|
85
|
+
<link rel="stylesheet" type="text/css" href="{cssfile}"/>
|
|
86
|
+
|
|
87
|
+
</head>
|
|
88
|
+
|
|
89
|
+
<body>
|
|
90
|
+
|
|
91
|
+
<!- add in javascript to allow text toggling -->
|
|
92
|
+
<script language="javascript">
|
|
93
|
+
function toggle(id) {{
|
|
94
|
+
var ele = document.getElementById(id);
|
|
95
|
+
if(ele.style.display == "block"){{
|
|
96
|
+
ele.style.display = "none";
|
|
97
|
+
}}
|
|
98
|
+
else
|
|
99
|
+
ele.style.display = "block";
|
|
100
|
+
}}
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<!-- Page title -->
|
|
104
|
+
<h1>{h1title}</h1>
|
|
105
|
+
|
|
106
|
+
<!-- Links to the parts of the page -->
|
|
107
|
+
<div class="pagelinks">
|
|
108
|
+
{linkstable}
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<!-- table of pulsar parameters from EM data -->
|
|
112
|
+
<table>
|
|
113
|
+
<tr>
|
|
114
|
+
<td>
|
|
115
|
+
<div class="pulsartable" id="pulsartable">
|
|
116
|
+
{pulsartable}
|
|
117
|
+
</div>
|
|
118
|
+
</td>
|
|
119
|
+
|
|
120
|
+
<td>
|
|
121
|
+
<!-- table of derived gravitational wave upper limits, SNRs and evidence ratios -->
|
|
122
|
+
<div class="limitstable" id="limitstable">
|
|
123
|
+
{limitstable}
|
|
124
|
+
</div>
|
|
125
|
+
</td>
|
|
126
|
+
</tr>
|
|
127
|
+
</table>
|
|
128
|
+
|
|
129
|
+
<br />
|
|
130
|
+
|
|
131
|
+
<!-- plots of 1D and 2D marginalised posteriors for GW amplitude and phase parameters -->
|
|
132
|
+
<div class="selectedposteriors" id="selectedposteriors">
|
|
133
|
+
{selectedposteriors}
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<br />
|
|
137
|
+
|
|
138
|
+
<!-- corner plot of all parameters (hidden by default) -->
|
|
139
|
+
<div class="jointposteriors" id="jointposteriors">
|
|
140
|
+
{jointposteriors}
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<br />
|
|
144
|
+
|
|
145
|
+
<!-- (if background runs have been produced): if running a multi-detector analysis the plot
|
|
146
|
+
coherent vs. incoherent Bayes factors (with SNR giving colour of points) of background
|
|
147
|
+
and foreground, or if single detector plot signal vs. noise Bayes factor against SNR. -->
|
|
148
|
+
<div class="evidenceplots" id="evidenceplots">
|
|
149
|
+
{evidenceplots}
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<br />
|
|
153
|
+
|
|
154
|
+
<!-- plots of pre-processed data (heterodyned/spectrally interpolated time series) -->
|
|
155
|
+
<div class="dataplots" id="dataplots">
|
|
156
|
+
{dataplots}
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
<br />
|
|
160
|
+
|
|
161
|
+
<!-- plots of the posterior samples for all parameters -->
|
|
162
|
+
<div class="posteriorsamples" id="posteriorsamples">
|
|
163
|
+
{posteriorsamples}
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<br />
|
|
167
|
+
|
|
168
|
+
<!-- table of posterior statistics: means, max. likelihoods, confidence intervals -->
|
|
169
|
+
<div class="posteriorstats" id="posteriorstats">
|
|
170
|
+
{posteriorstats}
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<br />
|
|
174
|
+
|
|
175
|
+
<!-- a footer -->
|
|
176
|
+
<div id="footer">
|
|
177
|
+
{footer}
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
</body>
|
|
181
|
+
</html>
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def set_spin_down(p1_I, assoc, f0, f1, n=5.0):
|
|
186
|
+
"""
|
|
187
|
+
Set the spin-down of the source based on the intrinsic period derivative (p1_I) corrected for any proper motion/
|
|
188
|
+
globular cluster acceleration if available, or if not give AND the pulsar is in a globular cluster base the
|
|
189
|
+
spin-down on assuming an age of 10^9 years (defaulting to the source being a gravitar, with n=5).
|
|
190
|
+
Otherwise just return the unadjusted spin-down.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
if p1_I != None and p1_I > 0.0:
|
|
194
|
+
return -p1_I * f0**2 # convert period derivative into frequency derivative
|
|
195
|
+
elif assoc != None:
|
|
196
|
+
if "GC" in assoc: # check if a globular cluster pulsar
|
|
197
|
+
return -f0 / ((n - 1.0) * 1.0e9 * 365.25 * 86400.0)
|
|
198
|
+
else:
|
|
199
|
+
return f1
|
|
200
|
+
else:
|
|
201
|
+
return f1
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def create_psr_table(par):
|
|
205
|
+
"""
|
|
206
|
+
Create a html table of some information from the pulsar parameter file.
|
|
207
|
+
"""
|
|
208
|
+
table = htmltable() # create table class
|
|
209
|
+
|
|
210
|
+
# list of parameters to display (in this order)
|
|
211
|
+
paramdisplist = [
|
|
212
|
+
"RAJ",
|
|
213
|
+
"DECJ",
|
|
214
|
+
"F0",
|
|
215
|
+
"F1",
|
|
216
|
+
"F2",
|
|
217
|
+
"PEPOCH",
|
|
218
|
+
"A1",
|
|
219
|
+
"E",
|
|
220
|
+
"EPS1",
|
|
221
|
+
"EPS2",
|
|
222
|
+
"OM",
|
|
223
|
+
"T0",
|
|
224
|
+
"TASC",
|
|
225
|
+
"PB",
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
for param in paramdisplist:
|
|
229
|
+
pa = par[param]
|
|
230
|
+
if pa != None:
|
|
231
|
+
table.addrow()
|
|
232
|
+
dispfunc = paramhtmldispfunc.__dict__[param]
|
|
233
|
+
table.adddata(paramhtmldict[param])
|
|
234
|
+
table.adddata(dispfunc(str(pa)))
|
|
235
|
+
|
|
236
|
+
return table.tabletext
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class create_data_table:
|
|
240
|
+
def __init__(
|
|
241
|
+
self, datafiles, outputdir, figformats=["png"], asdtime=86400, harmonics=[2.0]
|
|
242
|
+
):
|
|
243
|
+
"""
|
|
244
|
+
Initialise with a dictionary keyed in detector names containing paths to the equivalent pre-processed
|
|
245
|
+
data file(s) for that detector (if harmonics contains more than one frequency harmonic this there should
|
|
246
|
+
be a list of files, with one for each harmonic and given in the same order as the harmonics lists).
|
|
247
|
+
figformats gives a list of the output figure formats (defaulting to .png), and asd time is the time to use
|
|
248
|
+
for each FFT when creating the spectrograms/ASDs, which defaults to 86400 seconds (1 day).
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
self._datatable = htmltag(
|
|
252
|
+
"h2", "Analysis statistics", newline=True
|
|
253
|
+
).text # the output html table
|
|
254
|
+
|
|
255
|
+
if not isinstance(harmonics, list):
|
|
256
|
+
self._harmonics = list(harmonics)
|
|
257
|
+
else:
|
|
258
|
+
self._harmonics = harmonics
|
|
259
|
+
self._nharmonics = len(self._harmonics)
|
|
260
|
+
self._ifos = list(datafiles.keys()) # get list of detectors
|
|
261
|
+
self._datafiles = (
|
|
262
|
+
{}
|
|
263
|
+
) # dictionary (keyed to harmonics) of dictionaries (keyed to detector) of data files
|
|
264
|
+
|
|
265
|
+
for i, ifo in enumerate(datafiles):
|
|
266
|
+
if isinstance(datafiles[ifo], list):
|
|
267
|
+
if len(datafiles[ifo]) != self._nharmonics:
|
|
268
|
+
print(
|
|
269
|
+
"Error... number of pre-processed data files is not the same as the number of harmonics.",
|
|
270
|
+
file=sys.stderr,
|
|
271
|
+
)
|
|
272
|
+
sys.exit(1)
|
|
273
|
+
else:
|
|
274
|
+
if i == 0:
|
|
275
|
+
for h in self._harmonics:
|
|
276
|
+
self._datafiles[h] = {}
|
|
277
|
+
|
|
278
|
+
for j, df in enumerate(datafiles[ifo]):
|
|
279
|
+
if not os.path.isfile(df):
|
|
280
|
+
print(
|
|
281
|
+
"Error... pre-processed data file '%s' for '%s' does not exist."
|
|
282
|
+
% (df, ifo),
|
|
283
|
+
file=sys.stderr,
|
|
284
|
+
)
|
|
285
|
+
sys.exit(1)
|
|
286
|
+
else:
|
|
287
|
+
self._datafiles[self._harmonics[j]][ifo] = df
|
|
288
|
+
else:
|
|
289
|
+
if self._nharmonics == 1:
|
|
290
|
+
self._datafiles[self._harmonics[0]] = datafiles
|
|
291
|
+
for df in list(self._datafiles[self._harmonics[0]].values()):
|
|
292
|
+
if not os.path.isfile(df):
|
|
293
|
+
print(
|
|
294
|
+
"Error... pre-processed data file '%s' for '%s' does not exist."
|
|
295
|
+
% (df, ifo),
|
|
296
|
+
file=sys.stderr,
|
|
297
|
+
)
|
|
298
|
+
sys.exit(1)
|
|
299
|
+
break
|
|
300
|
+
else:
|
|
301
|
+
print(
|
|
302
|
+
"Error... number of pre-processed data files is not the same as the number of harmonics.",
|
|
303
|
+
file=sys.stderr,
|
|
304
|
+
)
|
|
305
|
+
sys.exit(1)
|
|
306
|
+
|
|
307
|
+
self._outputdir = outputdir
|
|
308
|
+
if not os.path.isdir(self._outputdir):
|
|
309
|
+
print(
|
|
310
|
+
"Error... output path '%s' for data plots does not exist"
|
|
311
|
+
% self._outputdir,
|
|
312
|
+
file=sys.stderr,
|
|
313
|
+
)
|
|
314
|
+
sys.exit(1)
|
|
315
|
+
|
|
316
|
+
self._figformats = figformats # figure output formats
|
|
317
|
+
if "png" not in figformats:
|
|
318
|
+
print(
|
|
319
|
+
"Error... must include 'png' in the output figure formats",
|
|
320
|
+
file=sys.stderr,
|
|
321
|
+
)
|
|
322
|
+
sys.exit(1)
|
|
323
|
+
|
|
324
|
+
# get plots of absolute values, amplitude spectral density and spectrograms of the pre-processed data
|
|
325
|
+
self._asdtime = asdtime
|
|
326
|
+
self._asds = {}
|
|
327
|
+
self.create_plots()
|
|
328
|
+
|
|
329
|
+
self._starts = {} # start times of data files
|
|
330
|
+
self._ends = {} # end times of data files
|
|
331
|
+
self._length = {} # length (seconds) of data files
|
|
332
|
+
self._duty_factor = {} # duty factors of data
|
|
333
|
+
|
|
334
|
+
# get analysis data statistics (start time, end time, duty factor)
|
|
335
|
+
self.get_stats()
|
|
336
|
+
|
|
337
|
+
# create table of results for all detectors
|
|
338
|
+
self.create_table()
|
|
339
|
+
|
|
340
|
+
def create_plots(self):
|
|
341
|
+
# create the plots of the absolute values, amplitude spectral density and spectrograms of the
|
|
342
|
+
# pre-processed data.
|
|
343
|
+
self._Bkplots = {}
|
|
344
|
+
self._asdplots = {}
|
|
345
|
+
self._fscanplots = {}
|
|
346
|
+
|
|
347
|
+
for h in self._harmonics:
|
|
348
|
+
self._Bkplots[h] = {}
|
|
349
|
+
self._asdplots[h] = {}
|
|
350
|
+
self._fscanplots[h] = {}
|
|
351
|
+
self._asds[h] = {}
|
|
352
|
+
|
|
353
|
+
Bkfigs, asdfigs, fscanfigs, asdlist, _ = plot_Bks_ASDs(
|
|
354
|
+
self._datafiles[h],
|
|
355
|
+
delt=self._asdtime,
|
|
356
|
+
plotpsds=True,
|
|
357
|
+
plotfscan=True,
|
|
358
|
+
removeoutlier=5.0,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
if self._nharmonics == 1:
|
|
362
|
+
harmtext = "" # don't add any harmonics suffix to the file name
|
|
363
|
+
else:
|
|
364
|
+
harmtext = "_%d" % int(h)
|
|
365
|
+
|
|
366
|
+
# output the plots
|
|
367
|
+
for i, ifo in enumerate(self._ifos):
|
|
368
|
+
self._asds[h][ifo] = asdlist[
|
|
369
|
+
i
|
|
370
|
+
] # set the estimate of the amplitude spectral density for that IFO
|
|
371
|
+
|
|
372
|
+
for ftype in self._figformats:
|
|
373
|
+
for fig, fignameprefix in zip(
|
|
374
|
+
[Bkfigs[i], fscanfigs[i], asdfigs[i]], ["Bk", "fscan", "ASD"]
|
|
375
|
+
):
|
|
376
|
+
# try outputting figures
|
|
377
|
+
figname = os.path.join(
|
|
378
|
+
outdir, "%s_%s%s.%s" % (fignameprefix, ifo, harmtext, ftype)
|
|
379
|
+
)
|
|
380
|
+
try:
|
|
381
|
+
fig.savefig(figname)
|
|
382
|
+
except:
|
|
383
|
+
print(
|
|
384
|
+
"Error... problem creating figure '%s'." % figname,
|
|
385
|
+
file=sys.stderr,
|
|
386
|
+
)
|
|
387
|
+
sys.exit(1)
|
|
388
|
+
|
|
389
|
+
if ftype == "png": # add figure files
|
|
390
|
+
self._Bkplots[h][ifo] = os.path.join(
|
|
391
|
+
outdir, "Bk_%s%s.%s" % (ifo, harmtext, ftype)
|
|
392
|
+
)
|
|
393
|
+
self._asdplots[h][ifo] = os.path.join(
|
|
394
|
+
outdir, "ASD_%s%s.%s" % (ifo, harmtext, ftype)
|
|
395
|
+
)
|
|
396
|
+
self._fscanplots[h][ifo] = os.path.join(
|
|
397
|
+
outdir, "fscan_%s%s.%s" % (ifo, harmtext, ftype)
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
@property
|
|
401
|
+
def Bkplots(self):
|
|
402
|
+
# return dictionary of plots of absolute values of the pre-processed data for each detector
|
|
403
|
+
return self._Bkplots
|
|
404
|
+
|
|
405
|
+
@property
|
|
406
|
+
def asdplots(self):
|
|
407
|
+
# return dictionary of plot of the amplitude specatral densities for each detector
|
|
408
|
+
return self._asdplots
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def fscanplots(self):
|
|
412
|
+
# return dictionary of spectrogram plots of the pre-processed data for each detector
|
|
413
|
+
return self._fscanplots
|
|
414
|
+
|
|
415
|
+
@property
|
|
416
|
+
def asds(self):
|
|
417
|
+
# return dictionary of noise amplitude spectral density estimates for each detector
|
|
418
|
+
return self._asds
|
|
419
|
+
|
|
420
|
+
def get_stats(self):
|
|
421
|
+
# get analysis statistics (data start, end and duty cycle) for each detector
|
|
422
|
+
for i, ifo in enumerate(self._ifos):
|
|
423
|
+
# use np.loadtxt to open file and get start and end times
|
|
424
|
+
try:
|
|
425
|
+
bkd = np.loadtxt(
|
|
426
|
+
self._datafiles[self._harmonics[0]][ifo], comments=["#", "%"]
|
|
427
|
+
)
|
|
428
|
+
except:
|
|
429
|
+
print(
|
|
430
|
+
"Error... could not load file '%s'."
|
|
431
|
+
% self._datafiles[self._harmonics[0]][ifo],
|
|
432
|
+
file=sys.stderr,
|
|
433
|
+
)
|
|
434
|
+
sys.exit(1)
|
|
435
|
+
|
|
436
|
+
self._starts[ifo] = bkd[0, 0] # start time
|
|
437
|
+
self._ends[ifo] = bkd[-1, 0] # end time
|
|
438
|
+
dt = np.min(np.diff(bkd[:, 0])) # minimum time step in data
|
|
439
|
+
self._length[ifo] = float(len(bkd)) * dt
|
|
440
|
+
self._duty_factor[ifo] = (
|
|
441
|
+
100.0 * self._length[ifo] / (self._ends[ifo] - self._starts[ifo])
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
def analysis_stats_td(self, ifo):
|
|
445
|
+
# return the inside of the html <td> element giving the statistics for a particular detector
|
|
446
|
+
table = htmltable()
|
|
447
|
+
table.addrow()
|
|
448
|
+
table.adddata(" ")
|
|
449
|
+
table.adddata(ifo, dataclass=ifo)
|
|
450
|
+
tdvals = [
|
|
451
|
+
("Start (GPS)", str(int(self._starts[ifo]))),
|
|
452
|
+
("End (GPS)", str(int(self._ends[ifo]))),
|
|
453
|
+
("Length (sec)", str(int(self._length[ifo]))),
|
|
454
|
+
("Duty factor (%)", "%.lf" % self._duty_factor[ifo]),
|
|
455
|
+
]
|
|
456
|
+
for item in tdvals:
|
|
457
|
+
table.addrow()
|
|
458
|
+
table.adddata(item[0])
|
|
459
|
+
table.adddata(item[1])
|
|
460
|
+
|
|
461
|
+
return table.tabletext
|
|
462
|
+
|
|
463
|
+
def create_table(self):
|
|
464
|
+
table = htmltable()
|
|
465
|
+
|
|
466
|
+
for ifo in self._ifos:
|
|
467
|
+
for h in self._harmonics:
|
|
468
|
+
table.addrow()
|
|
469
|
+
if self._nharmonics != 1:
|
|
470
|
+
table.adddata("Data for %df" % int(h), colspan=2, header=True)
|
|
471
|
+
table.addrow()
|
|
472
|
+
|
|
473
|
+
table.adddata(
|
|
474
|
+
self.analysis_stats_td(ifo), datastyle="text-align: center;"
|
|
475
|
+
)
|
|
476
|
+
plotlink = atag(
|
|
477
|
+
os.path.basename(self._Bkplots[h][ifo]),
|
|
478
|
+
'<img class="dataplot" src="{}"/>'.format(
|
|
479
|
+
os.path.basename(self._Bkplots[h][ifo])
|
|
480
|
+
),
|
|
481
|
+
).text
|
|
482
|
+
table.adddata(plotlink)
|
|
483
|
+
table.addrow()
|
|
484
|
+
plotlink = atag(
|
|
485
|
+
os.path.basename(self._asdplots[h][ifo]),
|
|
486
|
+
'<img class="asdplot" src="{}"/>'.format(
|
|
487
|
+
os.path.basename(self._asdplots[h][ifo])
|
|
488
|
+
),
|
|
489
|
+
).text
|
|
490
|
+
table.adddata(plotlink)
|
|
491
|
+
plotlink = atag(
|
|
492
|
+
os.path.basename(self._fscanplots[h][ifo]),
|
|
493
|
+
'<img class="dataplot" src="{}"/>'.format(
|
|
494
|
+
os.path.basename(self._fscanplots[h][ifo])
|
|
495
|
+
),
|
|
496
|
+
).text
|
|
497
|
+
table.adddata(plotlink)
|
|
498
|
+
|
|
499
|
+
self._datatable += table.tabletext
|
|
500
|
+
|
|
501
|
+
def __str__(self): # string method
|
|
502
|
+
return self._datatable
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
class posteriors:
|
|
506
|
+
"""
|
|
507
|
+
Get sample posteriors and created a set of functions for outputting tables, plots and posterior statistics
|
|
508
|
+
"""
|
|
509
|
+
|
|
510
|
+
def __init__(
|
|
511
|
+
self,
|
|
512
|
+
postfiles,
|
|
513
|
+
outputdir,
|
|
514
|
+
ifos=None,
|
|
515
|
+
harmonics=[2],
|
|
516
|
+
modeltype="waveform",
|
|
517
|
+
biaxial=False,
|
|
518
|
+
usegwphase=False,
|
|
519
|
+
parfile=None,
|
|
520
|
+
priorfile=None,
|
|
521
|
+
subtracttruths=False,
|
|
522
|
+
showcontours=False,
|
|
523
|
+
):
|
|
524
|
+
"""
|
|
525
|
+
Initialise with a dictionary keyed in detector names containing paths to the equivalent posterior samples
|
|
526
|
+
file for that detector.
|
|
527
|
+
"""
|
|
528
|
+
self._outputdir = outputdir
|
|
529
|
+
if not os.path.isdir(self._outputdir):
|
|
530
|
+
print(
|
|
531
|
+
"Error... output path '%s' for data plots does not exist"
|
|
532
|
+
% self._outputdir,
|
|
533
|
+
file=sys.stderr,
|
|
534
|
+
)
|
|
535
|
+
sys.exit(1)
|
|
536
|
+
|
|
537
|
+
if ifos is None: # get list of detectors from postfiles dictionary
|
|
538
|
+
self._ifos = list(postfiles.keys()) # get list of detectors
|
|
539
|
+
else:
|
|
540
|
+
if isinstance(ifos, list):
|
|
541
|
+
self._ifos = ifos
|
|
542
|
+
else:
|
|
543
|
+
self._ifos = [ifos]
|
|
544
|
+
# check ifos are in postfiles dictionary
|
|
545
|
+
for ifo in self._ifos:
|
|
546
|
+
if ifo not in postfiles:
|
|
547
|
+
print(
|
|
548
|
+
"Error... posterior files for detector '%s' not given" % ifo,
|
|
549
|
+
file=sys.stderr,
|
|
550
|
+
)
|
|
551
|
+
sys.exit(1)
|
|
552
|
+
|
|
553
|
+
self._postfiles = postfiles
|
|
554
|
+
self._posteriors = {} # dictionary of posterior objects
|
|
555
|
+
self._posterior_stats = {} # dictionary if posteriors statistics
|
|
556
|
+
self._signal_evidence = {} # dictionary of signal evidence values
|
|
557
|
+
self._noise_evidence = {} # dictionary of noise evidence values
|
|
558
|
+
self._maxL = {} # dictionary of maximum log likelihood values
|
|
559
|
+
self._Bsn = {} # dictionary of signal vs noise Bayes factors
|
|
560
|
+
self._signal_evidence = {} # dictionary of signal evidences
|
|
561
|
+
self._noise_evidence = {} # dictionary of noise evidences
|
|
562
|
+
self._Bci = None # coherent versus incoherent Bayes factor
|
|
563
|
+
self._Bcin = None # coherent versus incoherent or noise Bayes factor
|
|
564
|
+
self._optimal_snrs = {} # dictionary of optimal matched filter SNRs
|
|
565
|
+
self._parameters = [] # list of the source parameters in the posterior files
|
|
566
|
+
self._parfile = parfile # set the TEMPO(2) parameter file used
|
|
567
|
+
self._injection_parameters = None # injection/heterodyne parameters
|
|
568
|
+
self._priorfile = priorfile # the prior file used for the analysis
|
|
569
|
+
self._prior_parameters = {} # the prior parameters
|
|
570
|
+
self._injection_credible_regions = (
|
|
571
|
+
{}
|
|
572
|
+
) # dictionary of minimal credible regions within which an injected parameter is found
|
|
573
|
+
self._harmonics = harmonics # list of frequency harmonics
|
|
574
|
+
self._modeltype = modeltype # the model type ('waveform' or 'source')
|
|
575
|
+
self._biaxial = (
|
|
576
|
+
biaxial # whether the source is a biaxial star (rather than triaxial)
|
|
577
|
+
)
|
|
578
|
+
self._usegwphase = (
|
|
579
|
+
usegwphase # whether to use GW phase rather than rotational phase
|
|
580
|
+
)
|
|
581
|
+
self._subtract_truths = subtracttruths # set whether to subtract true/heterodyned values of phase parameters from the distributions (so true/heterodyned value is at zero)
|
|
582
|
+
self._showcontours = showcontours # set whether to show probability contours on 2d posterior plots
|
|
583
|
+
|
|
584
|
+
# check if parameter file has been given
|
|
585
|
+
if self._parfile is not None:
|
|
586
|
+
# try and read it
|
|
587
|
+
try:
|
|
588
|
+
self._injection_parameters = psr_par(self._parfile)
|
|
589
|
+
except:
|
|
590
|
+
print(
|
|
591
|
+
"Error... cannot read injection parameter file '%s'."
|
|
592
|
+
% self._parfile,
|
|
593
|
+
file=sys.stderr,
|
|
594
|
+
)
|
|
595
|
+
sys.exit(1)
|
|
596
|
+
|
|
597
|
+
if self._usegwphase: # change initial phase if required
|
|
598
|
+
if hasattr(self._injection_parameters, "PHI0"):
|
|
599
|
+
phi0val = 2.0 * self._injection_parameters["PHI0"]
|
|
600
|
+
setattr(self._injection_parameters, "PHI0", phi0val)
|
|
601
|
+
|
|
602
|
+
# if RA_RAD and DEC_RAD are set then copy them into RA and DEC attributes
|
|
603
|
+
if hasattr(self._injection_parameters, "RA_RAD"):
|
|
604
|
+
setattr(
|
|
605
|
+
self._injection_parameters,
|
|
606
|
+
"RA",
|
|
607
|
+
self._injection_parameters["RA_RAD"],
|
|
608
|
+
)
|
|
609
|
+
if hasattr(self._injection_parameters, "DEC_RAD"):
|
|
610
|
+
setattr(
|
|
611
|
+
self._injection_parameters,
|
|
612
|
+
"DEC",
|
|
613
|
+
self._injection_parameters["DEC_RAD"],
|
|
614
|
+
)
|
|
615
|
+
|
|
616
|
+
# if DIST is set, then use the original value in KPC as the posterior samples will be in KPC
|
|
617
|
+
if hasattr(self._injection_parameters, "DIST"):
|
|
618
|
+
setattr(
|
|
619
|
+
self._injection_parameters,
|
|
620
|
+
"DIST",
|
|
621
|
+
self._injection_parameters["DIST_ORIGINAL"],
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
if "Joint" in self._ifos: # put 'Joint' at the end
|
|
625
|
+
j = self._ifos.pop(self._ifos.index("Joint"))
|
|
626
|
+
self._ifos.append(j)
|
|
627
|
+
|
|
628
|
+
# check if prior file has been given
|
|
629
|
+
if self._priorfile is not None:
|
|
630
|
+
# try and read it
|
|
631
|
+
try:
|
|
632
|
+
pf = open(self._priorfile, "r")
|
|
633
|
+
except:
|
|
634
|
+
print(
|
|
635
|
+
"Error... cannot read prior file '%s'." % self._priorfile,
|
|
636
|
+
file=sys.stderr,
|
|
637
|
+
)
|
|
638
|
+
sys.exit(1)
|
|
639
|
+
|
|
640
|
+
for line in pf.readlines(): # read in priors
|
|
641
|
+
priorlinevals = line.split()
|
|
642
|
+
if len(priorlinevals) < 4:
|
|
643
|
+
print(
|
|
644
|
+
"Error... there must be at least four values on each line of the prior file '%s'."
|
|
645
|
+
% self._priorfile,
|
|
646
|
+
file=sys.stderr,
|
|
647
|
+
)
|
|
648
|
+
sys.exit(1)
|
|
649
|
+
|
|
650
|
+
if priorlinevals[1] not in [
|
|
651
|
+
"uniform",
|
|
652
|
+
"fermidirac",
|
|
653
|
+
"gaussian",
|
|
654
|
+
"gmm",
|
|
655
|
+
"loguniform",
|
|
656
|
+
]:
|
|
657
|
+
print(
|
|
658
|
+
"Error... the prior for '%s' must be either 'uniform', 'loguniform', 'gmm', 'fermidirac', or 'gaussian'."
|
|
659
|
+
% priorlinevals[0],
|
|
660
|
+
file=sys.stderr,
|
|
661
|
+
)
|
|
662
|
+
sys.exit(1)
|
|
663
|
+
|
|
664
|
+
if priorlinevals[1] in [
|
|
665
|
+
"uniform",
|
|
666
|
+
"fermidirac",
|
|
667
|
+
"gaussian",
|
|
668
|
+
"loguniform",
|
|
669
|
+
]:
|
|
670
|
+
if len(priorlinevals) != 4:
|
|
671
|
+
print(
|
|
672
|
+
"Error... there must be four values on each line of the prior file '%s'."
|
|
673
|
+
% self._priorfile,
|
|
674
|
+
file=sys.stderr,
|
|
675
|
+
)
|
|
676
|
+
sys.exit(1)
|
|
677
|
+
ranges = np.array(
|
|
678
|
+
[float(priorlinevals[2]), float(priorlinevals[3])]
|
|
679
|
+
) # set ranges
|
|
680
|
+
|
|
681
|
+
if (
|
|
682
|
+
self._usegwphase and priorlinevals[0].lower() == "phi0"
|
|
683
|
+
): # adjust phi0 priors if using GW phase
|
|
684
|
+
ranges = 2.0 * ranges
|
|
685
|
+
elif priorlinevals[1] == "gmm":
|
|
686
|
+
try:
|
|
687
|
+
ranges = {}
|
|
688
|
+
ranges["nmodes"] = priorlinevals[2]
|
|
689
|
+
ranges["means"] = ast.literal_eval(priorlinevals[3]) # means
|
|
690
|
+
ranges["covs"] = ast.literal_eval(
|
|
691
|
+
priorlinevals[4]
|
|
692
|
+
) # covariance matrices
|
|
693
|
+
ranges["weights"] = ast.literal_eval(
|
|
694
|
+
priorlinevals[5]
|
|
695
|
+
) # weights
|
|
696
|
+
plims = []
|
|
697
|
+
splitpars = [
|
|
698
|
+
p.lower() for p in priorlinevals[0].split(":")
|
|
699
|
+
] # split GMM parameter names
|
|
700
|
+
npars = len(splitpars)
|
|
701
|
+
for lims in priorlinevals[6:-1]: # limits for each parameter
|
|
702
|
+
plims.append(np.array(ast.literal_eval(lims)))
|
|
703
|
+
ranges["limits"] = plims
|
|
704
|
+
ranges["npars"] = npars
|
|
705
|
+
if self._usegwphase and "phi0" in splitpars:
|
|
706
|
+
phi0idx = splitpars.index("phi0")
|
|
707
|
+
# adjust phi0 priors (multiply limits, means and covariances by 2.) if using GW phase
|
|
708
|
+
for ci in range(ranges["nmodes"]):
|
|
709
|
+
ranges["means"][ci][phi0idx] = (
|
|
710
|
+
2.0 * ranges["means"][ci][phi0idx]
|
|
711
|
+
)
|
|
712
|
+
for ck in range(
|
|
713
|
+
npars
|
|
714
|
+
): # this will correctly multiply the variances by 4 when ck == phi0idx
|
|
715
|
+
ranges["covs"][ci][phi0idx][ck] = (
|
|
716
|
+
2.0 * ranges["covs"][ci][phi0idx][ck]
|
|
717
|
+
)
|
|
718
|
+
ranges["covs"][ci][ck][phi0idx] = (
|
|
719
|
+
2.0 * ranges["covs"][ci][ck][phi0idx]
|
|
720
|
+
)
|
|
721
|
+
ranges["limits"][phi0idx] = 2.0 * ranges["limits"][phi0idx]
|
|
722
|
+
for sidx, spar in enumerate(splitpars):
|
|
723
|
+
ranges["pindex"] = sidx
|
|
724
|
+
self._prior_parameters[spar] = {"gmm": ranges}
|
|
725
|
+
continue
|
|
726
|
+
except:
|
|
727
|
+
# if can't read in GMM prior correctly then just continue
|
|
728
|
+
continue
|
|
729
|
+
|
|
730
|
+
self._prior_parameters[priorlinevals[0]] = {priorlinevals[1]: ranges}
|
|
731
|
+
|
|
732
|
+
# check posterior files exist
|
|
733
|
+
for ifo in postfiles:
|
|
734
|
+
if not os.path.isfile(postfiles[ifo]):
|
|
735
|
+
print(
|
|
736
|
+
"Error... posterior samples file '%s' for '%s' does not exist."
|
|
737
|
+
% (postfiles[ifo], ifo),
|
|
738
|
+
file=sys.stderr,
|
|
739
|
+
)
|
|
740
|
+
sys.exit(1)
|
|
741
|
+
else: # convert into posterior class
|
|
742
|
+
pos, sigev, noiseev = pulsar_nest_to_posterior(postfiles[ifo])
|
|
743
|
+
self._posteriors[ifo] = pos
|
|
744
|
+
self._signal_evidence[ifo] = sigev
|
|
745
|
+
self._noise_evidence[ifo] = noiseev
|
|
746
|
+
self._Bsn[ifo] = sigev - noiseev
|
|
747
|
+
|
|
748
|
+
theseparams = []
|
|
749
|
+
for param in pos.names:
|
|
750
|
+
thispar = True
|
|
751
|
+
# remove parameters with 'logl', 'logw' or 'logprior' in the name
|
|
752
|
+
for testpar in ["logl", "logw", "logprior"]:
|
|
753
|
+
if testpar in param.lower():
|
|
754
|
+
thispar = False
|
|
755
|
+
break
|
|
756
|
+
if thispar:
|
|
757
|
+
theseparams.append(param)
|
|
758
|
+
|
|
759
|
+
if len(self._parameters) == 0:
|
|
760
|
+
self._parameters = copy.copy(theseparams)
|
|
761
|
+
else: # make sure different detectors do not have different sets of parameters
|
|
762
|
+
for param in theseparams:
|
|
763
|
+
if param not in self._parameters:
|
|
764
|
+
print(
|
|
765
|
+
"Error... parameter '%s' is not defined in posteriors samples for '%s'."
|
|
766
|
+
% (param, ifo),
|
|
767
|
+
file=sys.stderr,
|
|
768
|
+
)
|
|
769
|
+
sys.exit(1)
|
|
770
|
+
|
|
771
|
+
# rotate phi0 and psi into the 0->pi and 0->pi/2 ranges respectively if required (see Eqn. 45 of http://arxiv.org/abs/1501.05832)
|
|
772
|
+
if modeltype == "source":
|
|
773
|
+
phi0samples = None
|
|
774
|
+
psisamples = None
|
|
775
|
+
if "phi0" in pos.names:
|
|
776
|
+
phi0samples = pos["phi0"].samples
|
|
777
|
+
if "psi" in pos.names:
|
|
778
|
+
psisamples = pos["psi"].samples
|
|
779
|
+
|
|
780
|
+
# rotate psi values by pi/2 increments into the 0->pi/2 range
|
|
781
|
+
if psisamples is not None:
|
|
782
|
+
for i in range(len(psisamples)):
|
|
783
|
+
nrots = np.abs(
|
|
784
|
+
np.floor(psisamples[i] / (np.pi / 2.0))
|
|
785
|
+
) # number of rotations to return to range
|
|
786
|
+
psisamples[i] = np.mod(psisamples[i], np.pi / 2.0)
|
|
787
|
+
if phi0samples is not None: # rotate phi0 appropriately
|
|
788
|
+
phi0samples[i] += nrots * (np.pi / 2.0)
|
|
789
|
+
psisnew = PosteriorOneDPDF("psi", psisamples)
|
|
790
|
+
pos.pop("psi")
|
|
791
|
+
pos.append(psisnew)
|
|
792
|
+
|
|
793
|
+
# make sure phi0 values are between 0->pi
|
|
794
|
+
if phi0samples is not None:
|
|
795
|
+
phi0samples = np.mod(phi0samples, np.pi)
|
|
796
|
+
phi0new = PosteriorOneDPDF("phi0", phi0samples)
|
|
797
|
+
pos.pop("phi0")
|
|
798
|
+
pos.append(phi0new)
|
|
799
|
+
|
|
800
|
+
if (
|
|
801
|
+
self._usegwphase
|
|
802
|
+
): # try switching phi0 to 2*phi0 if working with l=m=2 gravitational wave initial phase (e.g. for hardware injections)
|
|
803
|
+
if "phi0" in pos.names:
|
|
804
|
+
phi0new = PosteriorOneDPDF("phi0", 2.0 * pos["phi0"].samples)
|
|
805
|
+
pos.pop("phi0")
|
|
806
|
+
pos.append(phi0new)
|
|
807
|
+
|
|
808
|
+
# if just working with results at 2f, but C22 and phi22 parameters have been used, convert back to h0 and phi0
|
|
809
|
+
if len(self._harmonics) == 1:
|
|
810
|
+
if self._harmonics[0] == 2.0:
|
|
811
|
+
if "c22" in pos.names and self._modeltype == "waveform":
|
|
812
|
+
h0new = PosteriorOneDPDF("h0", 2.0 * pos["c22"].samples)
|
|
813
|
+
pos.pop("c22")
|
|
814
|
+
pos.append(h0new)
|
|
815
|
+
ih0 = self._parameters.index("h0")
|
|
816
|
+
self._parameters.pop(ih0)
|
|
817
|
+
self._parameters.insert(ih0, "C22")
|
|
818
|
+
if self._parfile is not None:
|
|
819
|
+
if not hasattr(self._injection_parameters, "H0"):
|
|
820
|
+
setattr(
|
|
821
|
+
self._injection_parameters,
|
|
822
|
+
"H0",
|
|
823
|
+
2.0 * self._injection_parameters["C22"],
|
|
824
|
+
)
|
|
825
|
+
|
|
826
|
+
if "phi22" in pos.names and modeltype == "waveform":
|
|
827
|
+
phi0new = PosteriorOneDPDF(
|
|
828
|
+
"phi0", 0.5 * pos["phi22"].samples
|
|
829
|
+
)
|
|
830
|
+
pos.pop("phi0")
|
|
831
|
+
pos.append(phi0new)
|
|
832
|
+
iphi0 = self._parameters.index("phi0")
|
|
833
|
+
self._parameters.pop(iphi0)
|
|
834
|
+
self._parameters.insert(iphi0, "PHI0")
|
|
835
|
+
if self._parfile is not None:
|
|
836
|
+
if not hasattr(self._injection_parameters, "PHI0"):
|
|
837
|
+
setattr(
|
|
838
|
+
self._injection_parameters,
|
|
839
|
+
"PHI0",
|
|
840
|
+
0.5 * self._injection_parameters["PHI22"],
|
|
841
|
+
)
|
|
842
|
+
|
|
843
|
+
# for a biaxial star (and if using the waveform model) set phi22 = 2*phi21
|
|
844
|
+
if len(self._harmonics) == 2:
|
|
845
|
+
if (
|
|
846
|
+
1.0 in self._harmonics
|
|
847
|
+
and 2.0 in self._harmonics
|
|
848
|
+
and self._biaxial
|
|
849
|
+
and self._modeltype == "waveform"
|
|
850
|
+
):
|
|
851
|
+
if "phi21" in pos.names:
|
|
852
|
+
phi22 = PosteriorOneDPDF(
|
|
853
|
+
"phi22", 2.0 * pos["phi21"].samples
|
|
854
|
+
)
|
|
855
|
+
pos.append(phi22)
|
|
856
|
+
if self._parfile is not None:
|
|
857
|
+
if hasattr(self._injection_parameters, "PHI21"):
|
|
858
|
+
setattr(
|
|
859
|
+
self._injection_parameters,
|
|
860
|
+
"PHI22",
|
|
861
|
+
2.0 * self._injection_parameters["PHI21"],
|
|
862
|
+
)
|
|
863
|
+
|
|
864
|
+
self._posteriors[ifo] = pos
|
|
865
|
+
|
|
866
|
+
self._get_snrs() # get the optimal SNR of the signal
|
|
867
|
+
|
|
868
|
+
self._get_bayes_factors() # get the Bayes factors
|
|
869
|
+
|
|
870
|
+
@property
|
|
871
|
+
def parameters(self):
|
|
872
|
+
# return a list of the source parameter names
|
|
873
|
+
return self._parameters
|
|
874
|
+
|
|
875
|
+
@property
|
|
876
|
+
def bsn(self):
|
|
877
|
+
# return a dictionary of the signal vs noise log Bayes factors
|
|
878
|
+
return self._Bsn
|
|
879
|
+
|
|
880
|
+
@property
|
|
881
|
+
def snrs(self):
|
|
882
|
+
# return dictionary of snrs
|
|
883
|
+
return self._optimal_snrs
|
|
884
|
+
|
|
885
|
+
@property
|
|
886
|
+
def bci(self):
|
|
887
|
+
# return coherent vs incoherent Bayes factor
|
|
888
|
+
return self._Bci
|
|
889
|
+
|
|
890
|
+
@property
|
|
891
|
+
def bcin(self):
|
|
892
|
+
# return coherent vs incoherent or noise Bayes factor
|
|
893
|
+
return self._Bcin
|
|
894
|
+
|
|
895
|
+
def h0_ul(self, ifo):
|
|
896
|
+
# return the h0 upper limit for a given detector
|
|
897
|
+
if ifo in self._h0ul:
|
|
898
|
+
return self._h0ul[ifo]
|
|
899
|
+
else:
|
|
900
|
+
return None
|
|
901
|
+
|
|
902
|
+
def ellipticity_ul(self, ifo):
|
|
903
|
+
# return the ellipticity upper limit
|
|
904
|
+
if ifo in self._ellipticity:
|
|
905
|
+
return self._ellipticity[ifo]
|
|
906
|
+
else:
|
|
907
|
+
return None
|
|
908
|
+
|
|
909
|
+
def q22_ul(self, ifo):
|
|
910
|
+
# return the Q22 quadrupole moment upper limit
|
|
911
|
+
if ifo in self._q22:
|
|
912
|
+
return self._q22[ifo]
|
|
913
|
+
else:
|
|
914
|
+
return None
|
|
915
|
+
|
|
916
|
+
def C21_ul(self, ifo):
|
|
917
|
+
# return the C21 upper limit
|
|
918
|
+
if ifo in self._C21:
|
|
919
|
+
return self._C21[ifo]
|
|
920
|
+
else:
|
|
921
|
+
return None
|
|
922
|
+
|
|
923
|
+
def C22_ul(self, ifo):
|
|
924
|
+
# return the C22 upper limit
|
|
925
|
+
if ifo in self._C22:
|
|
926
|
+
return self._C22[ifo]
|
|
927
|
+
else:
|
|
928
|
+
return None
|
|
929
|
+
|
|
930
|
+
def I21_ul(self, ifo):
|
|
931
|
+
# return the I21 upper limit
|
|
932
|
+
if ifo in self._I21:
|
|
933
|
+
return self._I21[ifo]
|
|
934
|
+
else:
|
|
935
|
+
return None
|
|
936
|
+
|
|
937
|
+
def I31_ul(self, ifo):
|
|
938
|
+
# return the I31 upper limit
|
|
939
|
+
if ifo in self._I31:
|
|
940
|
+
return self._I31[ifo]
|
|
941
|
+
else:
|
|
942
|
+
return None
|
|
943
|
+
|
|
944
|
+
def sdlim_ratio(self, ifo):
|
|
945
|
+
# return the spin-down limit ratio
|
|
946
|
+
if ifo in self._sdratio:
|
|
947
|
+
return self._sdratio[ifo]
|
|
948
|
+
else:
|
|
949
|
+
return None
|
|
950
|
+
|
|
951
|
+
def _get_snrs(self):
|
|
952
|
+
# get the returned match filter SNRs
|
|
953
|
+
for ifo in self._ifos:
|
|
954
|
+
self._optimal_snrs[ifo] = self.get_snr(
|
|
955
|
+
os.path.dirname(self._postfiles[ifo])
|
|
956
|
+
)
|
|
957
|
+
|
|
958
|
+
def get_snr(self, pdir):
|
|
959
|
+
# get SNR from files in pdir
|
|
960
|
+
snr = 0.0
|
|
961
|
+
# get files with SNR in the name in the posterior file directory
|
|
962
|
+
snrfiles = [sf for sf in os.listdir(pdir) if "SNR" in sf]
|
|
963
|
+
if len(snrfiles) < 1:
|
|
964
|
+
print("Error... no SNR files are given for '%s'" % ifo, file=sys.stderr)
|
|
965
|
+
sys.exit(1)
|
|
966
|
+
|
|
967
|
+
for (
|
|
968
|
+
snrfile
|
|
969
|
+
) in (
|
|
970
|
+
snrfiles
|
|
971
|
+
): # average SNR values from mulitple files (e.g. if nested sampling has been run multiple times for the same signal)
|
|
972
|
+
fp = open(os.path.join(pdir, snrfile), "r")
|
|
973
|
+
lines = [line.strip() for line in fp.readlines()]
|
|
974
|
+
|
|
975
|
+
if "# Recovered SNR" not in lines:
|
|
976
|
+
print(
|
|
977
|
+
"Error... no recovered SNRs are given in the SNR file '%s'."
|
|
978
|
+
% snrfile,
|
|
979
|
+
file=sys.stderr,
|
|
980
|
+
)
|
|
981
|
+
sys.exit(1)
|
|
982
|
+
|
|
983
|
+
# just return the final (either coherent or single detector-single frequency value of the SNR)
|
|
984
|
+
linevals = lines[-1].split()
|
|
985
|
+
snr += float(linevals[-1])
|
|
986
|
+
return snr / len(snrfiles)
|
|
987
|
+
|
|
988
|
+
def _get_bayes_factors(self):
|
|
989
|
+
# get the Bayes factors (actually odds ratios with equal priors for all hypotheses) for the signal
|
|
990
|
+
nifos = 0
|
|
991
|
+
ifosn = [] # list of signal and noise evidences for each detector
|
|
992
|
+
for ifo in self._ifos:
|
|
993
|
+
(
|
|
994
|
+
self._Bsn[ifo],
|
|
995
|
+
self._signal_evidence[ifo],
|
|
996
|
+
self._noise_evidence[ifo],
|
|
997
|
+
self._maxL[ifo],
|
|
998
|
+
) = self.get_bayes_factor(self._postfiles[ifo])
|
|
999
|
+
|
|
1000
|
+
if ifo != "Joint":
|
|
1001
|
+
nifos += 1
|
|
1002
|
+
ifosn.append(
|
|
1003
|
+
{"s": self._signal_evidence[ifo], "n": self._noise_evidence[ifo]}
|
|
1004
|
+
)
|
|
1005
|
+
|
|
1006
|
+
# get all combinations of (incoherent) noise and signal hypotheses
|
|
1007
|
+
combs = [
|
|
1008
|
+
list(i) for i in itertools.product(["s", "n"], repeat=nifos)
|
|
1009
|
+
] # see e.g. http://stackoverflow.com/q/14931769/1862861
|
|
1010
|
+
incoherentcombs = -np.inf
|
|
1011
|
+
incoherentsig = 0.0 # incoherent signal in all detectors
|
|
1012
|
+
for comb in combs:
|
|
1013
|
+
# don't include the all noise hypotheses (as we have that already as self._noise_evidence['Joint'])
|
|
1014
|
+
if comb.count("n") != len(
|
|
1015
|
+
comb
|
|
1016
|
+
): # see e.g. http://stackoverflow.com/a/3844948/1862861
|
|
1017
|
+
combsum = 0.0
|
|
1018
|
+
for i, cval in enumerate(comb):
|
|
1019
|
+
combsum += ifosn[i][cval]
|
|
1020
|
+
incoherentcombs = np.logaddexp(incoherentcombs, combsum)
|
|
1021
|
+
if comb.count("s") == len(comb):
|
|
1022
|
+
incoherentsig = combsum
|
|
1023
|
+
|
|
1024
|
+
# get the coherent vs incoherent noise odds ratio (assuming all hypotheses have equal priors)
|
|
1025
|
+
if len(self._ifos) > 2 and "Joint" in self._ifos:
|
|
1026
|
+
self._Bci = self._signal_evidence["Joint"] - incoherentsig
|
|
1027
|
+
self._Bcin = self._signal_evidence["Joint"] - np.logaddexp(
|
|
1028
|
+
incoherentcombs, self._noise_evidence["Joint"]
|
|
1029
|
+
)
|
|
1030
|
+
|
|
1031
|
+
def get_bayes_factor(self, postfile):
|
|
1032
|
+
# return the Bayes factor extracted from a posterior file
|
|
1033
|
+
try:
|
|
1034
|
+
fe = os.path.splitext(postfile)[-1].lower() # file extension
|
|
1035
|
+
if fe == ".h5" or fe == ".hdf": # HDF5 file
|
|
1036
|
+
# open hdf5 file
|
|
1037
|
+
f = h5py.File(postfile, "r")
|
|
1038
|
+
a = f["lalinference"]["lalinference_nest"]
|
|
1039
|
+
evdata = (
|
|
1040
|
+
a.attrs["log_bayes_factor"],
|
|
1041
|
+
a.attrs["log_evidence"],
|
|
1042
|
+
a.attrs["log_noise_evidence"],
|
|
1043
|
+
a.attrs["log_max_likelihood"],
|
|
1044
|
+
)
|
|
1045
|
+
f.close()
|
|
1046
|
+
else: # try old/legacy file format
|
|
1047
|
+
B = np.loadtxt(postfile.replace(".gz", "") + "_B.txt")
|
|
1048
|
+
evdata = tuple(B.tolist())
|
|
1049
|
+
except:
|
|
1050
|
+
print(
|
|
1051
|
+
"Error... could not extract evidences from '%s'." % postfile,
|
|
1052
|
+
file=sys.stderr,
|
|
1053
|
+
)
|
|
1054
|
+
sys.exit(1)
|
|
1055
|
+
|
|
1056
|
+
return (
|
|
1057
|
+
evdata # line contains Bsn, signal evidence, noise evidence, max likelihood
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1060
|
+
def snr(self, ifo):
|
|
1061
|
+
# return the SNR for a given detector
|
|
1062
|
+
if ifo in self._optimal_snrs:
|
|
1063
|
+
return self._optimal_snrs[ifo]
|
|
1064
|
+
else:
|
|
1065
|
+
return None
|
|
1066
|
+
|
|
1067
|
+
def create_joint_posterior_plot(
|
|
1068
|
+
self,
|
|
1069
|
+
parameters,
|
|
1070
|
+
bins=20,
|
|
1071
|
+
ifo=None,
|
|
1072
|
+
truths=None,
|
|
1073
|
+
credintervals=[0.9],
|
|
1074
|
+
filename=None,
|
|
1075
|
+
figformats=["png"],
|
|
1076
|
+
ratio=3,
|
|
1077
|
+
figlimits=None,
|
|
1078
|
+
contourlimits=None,
|
|
1079
|
+
jointsamples=True,
|
|
1080
|
+
whichtruth=None,
|
|
1081
|
+
scatter_kwargs={},
|
|
1082
|
+
):
|
|
1083
|
+
# create a plot with the 1D and 2D joint posteriors (if ifo is None then use all ifos in class)
|
|
1084
|
+
if ifo != None and ifo in self._ifos:
|
|
1085
|
+
plotifos = [ifo]
|
|
1086
|
+
else:
|
|
1087
|
+
plotifos = self._ifos
|
|
1088
|
+
|
|
1089
|
+
# if a joint detector posterior is present, make that first so other data is plotted on top
|
|
1090
|
+
if "Joint" in plotifos:
|
|
1091
|
+
j = plotifos.pop(plotifos.index("Joint"))
|
|
1092
|
+
plotifos.insert(0, j)
|
|
1093
|
+
|
|
1094
|
+
coldict = {
|
|
1095
|
+
"H1": "red",
|
|
1096
|
+
"H2": "cyan",
|
|
1097
|
+
"L1": "green",
|
|
1098
|
+
"V1": "blue",
|
|
1099
|
+
"G1": "magenta",
|
|
1100
|
+
"Joint": "black",
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
if len(parameters) < 2 or len(parameters) > len(self._parameters):
|
|
1104
|
+
print(
|
|
1105
|
+
"Error... can only plot posterior distributions for more than one parameters",
|
|
1106
|
+
file=sys.stderr,
|
|
1107
|
+
)
|
|
1108
|
+
sys.exit(1)
|
|
1109
|
+
|
|
1110
|
+
thistruth = []
|
|
1111
|
+
for param in parameters:
|
|
1112
|
+
if param not in self._parameters:
|
|
1113
|
+
print(
|
|
1114
|
+
"Error... the requested parameter '%s' is not recognised" % param,
|
|
1115
|
+
file=sys.stderr,
|
|
1116
|
+
)
|
|
1117
|
+
sys.exit(1)
|
|
1118
|
+
|
|
1119
|
+
if (
|
|
1120
|
+
self._injection_parameters is not None and truths is None
|
|
1121
|
+
): # we have injection values
|
|
1122
|
+
thistruth.append(self._injection_parameters[param.upper()])
|
|
1123
|
+
|
|
1124
|
+
if self._injection_parameters is not None and truths is None:
|
|
1125
|
+
truths = thistruth
|
|
1126
|
+
|
|
1127
|
+
if truths is not None:
|
|
1128
|
+
if isinstance(truths, list): # just a list of the true parameter values
|
|
1129
|
+
newtruths = {}
|
|
1130
|
+
if len(truths) != len(parameters):
|
|
1131
|
+
print(
|
|
1132
|
+
"Error... number of true values must be the same as number of parameters.",
|
|
1133
|
+
file=sys.stderr,
|
|
1134
|
+
)
|
|
1135
|
+
sys.exit(1)
|
|
1136
|
+
else:
|
|
1137
|
+
# convert to dictionary
|
|
1138
|
+
for ifo in plotifos:
|
|
1139
|
+
newtruths[ifo] = truths
|
|
1140
|
+
truths = newtruths
|
|
1141
|
+
if isinstance(
|
|
1142
|
+
truths, dict
|
|
1143
|
+
): # dictionary keyed to IFO with lists of true parameters for each IFO (this is really designed for the SNR vs Bayes factor plots)
|
|
1144
|
+
for ifo in plotifos:
|
|
1145
|
+
if ifo not in truths:
|
|
1146
|
+
print(
|
|
1147
|
+
"Error... problem in truths values. Detector '%s' not recognised."
|
|
1148
|
+
% ifo,
|
|
1149
|
+
file=sys.stderr,
|
|
1150
|
+
)
|
|
1151
|
+
sys.exit(1)
|
|
1152
|
+
else:
|
|
1153
|
+
if len(truths[ifo]) != len(parameters):
|
|
1154
|
+
print(
|
|
1155
|
+
"Error... number of true values must be the same as number of parameters.",
|
|
1156
|
+
file=sys.stderr,
|
|
1157
|
+
)
|
|
1158
|
+
sys.exit(1)
|
|
1159
|
+
else:
|
|
1160
|
+
truths = {}
|
|
1161
|
+
for ifo in plotifos:
|
|
1162
|
+
truths[ifo] = None # set all to be None
|
|
1163
|
+
|
|
1164
|
+
# list of truth values to subtract
|
|
1165
|
+
subtract_truths = []
|
|
1166
|
+
amppars = [
|
|
1167
|
+
"h0",
|
|
1168
|
+
"c21",
|
|
1169
|
+
"c22",
|
|
1170
|
+
"i21",
|
|
1171
|
+
"i31",
|
|
1172
|
+
"cosiota",
|
|
1173
|
+
"iota",
|
|
1174
|
+
"phi0",
|
|
1175
|
+
"phi21",
|
|
1176
|
+
"phi22",
|
|
1177
|
+
"lambda",
|
|
1178
|
+
"costheta",
|
|
1179
|
+
"theta",
|
|
1180
|
+
"psi",
|
|
1181
|
+
] # a list of "amplitude" parameters for which subtract truths won't be applied
|
|
1182
|
+
if truths is not None and self._subtract_truths is not None:
|
|
1183
|
+
if parameters[0] not in amppars:
|
|
1184
|
+
subtract_truths.append(0) # add the true/heterodyned parameter
|
|
1185
|
+
|
|
1186
|
+
# use first ifo and get the required posterior samples
|
|
1187
|
+
x = self._posteriors[plotifos[0]][parameters[0]].samples
|
|
1188
|
+
labels = []
|
|
1189
|
+
if parameters[0].upper() in paramlatexdict:
|
|
1190
|
+
labels.append(paramlatexdict[parameters[0].upper()])
|
|
1191
|
+
else:
|
|
1192
|
+
labels.append(parameters[0])
|
|
1193
|
+
for param in parameters[1:]:
|
|
1194
|
+
x = np.hstack((x, self._posteriors[plotifos[0]][param].samples))
|
|
1195
|
+
if param.upper() in paramlatexdict:
|
|
1196
|
+
labels.append(paramlatexdict[param.upper()])
|
|
1197
|
+
else:
|
|
1198
|
+
labels.append(param)
|
|
1199
|
+
if truths is not None and self._subtract_truths is not None:
|
|
1200
|
+
if param not in amppars:
|
|
1201
|
+
subtract_truths.append(parameters.index(param))
|
|
1202
|
+
|
|
1203
|
+
if len(subtract_truths) == 0:
|
|
1204
|
+
subtract_truths = None
|
|
1205
|
+
|
|
1206
|
+
# set styles to different detectors
|
|
1207
|
+
if plotifos[0] == "Joint":
|
|
1208
|
+
histops = {
|
|
1209
|
+
"histtype": "stepfilled",
|
|
1210
|
+
"color": "darkslategrey",
|
|
1211
|
+
"edgecolor": coldict["Joint"],
|
|
1212
|
+
"linewidth": 1.5,
|
|
1213
|
+
}
|
|
1214
|
+
contourops = {"colors": coldict[plotifos[0]]}
|
|
1215
|
+
showcontours = self._showcontours
|
|
1216
|
+
if whichtruth == "Joint" or whichtruth == "all":
|
|
1217
|
+
truthops = {"color": "black", "markeredgewidth": 2}
|
|
1218
|
+
else:
|
|
1219
|
+
truthops = {}
|
|
1220
|
+
showpoints = jointsamples
|
|
1221
|
+
else:
|
|
1222
|
+
showcontours = self._showcontours
|
|
1223
|
+
contourops = {"colors": "dark" + coldict[plotifos[0]]}
|
|
1224
|
+
showpoints = True
|
|
1225
|
+
if len(plotifos) == 1: # if just one detector use a filled histogram
|
|
1226
|
+
histops = {
|
|
1227
|
+
"histtype": "stepfilled",
|
|
1228
|
+
"color": coldict[plotifos[0]],
|
|
1229
|
+
"edgecolor": coldict[plotifos[0]],
|
|
1230
|
+
"linewidth": 1.5,
|
|
1231
|
+
}
|
|
1232
|
+
truthops = {"color": "black", "markeredgewidth": 2}
|
|
1233
|
+
else:
|
|
1234
|
+
histops = {
|
|
1235
|
+
"histtype": "step",
|
|
1236
|
+
"color": coldict[plotifos[0]],
|
|
1237
|
+
"edgecolor": coldict[plotifos[0]],
|
|
1238
|
+
"linewidth": 1,
|
|
1239
|
+
}
|
|
1240
|
+
if whichtruth == plotifos[0]:
|
|
1241
|
+
truthops = {"color": "black", "markeredgewidth": 2}
|
|
1242
|
+
elif whichtruth == "all":
|
|
1243
|
+
truthops = {
|
|
1244
|
+
"color": "dark" + coldict[plotifos[0]],
|
|
1245
|
+
"markeredgewidth": 2,
|
|
1246
|
+
}
|
|
1247
|
+
else:
|
|
1248
|
+
truthops = {}
|
|
1249
|
+
|
|
1250
|
+
sc = scotchcorner(
|
|
1251
|
+
x,
|
|
1252
|
+
bins=bins,
|
|
1253
|
+
ratio=ratio,
|
|
1254
|
+
labels=labels,
|
|
1255
|
+
truths=truths[plotifos[0]],
|
|
1256
|
+
datatitle=plotifos[0],
|
|
1257
|
+
showlims="both",
|
|
1258
|
+
hist_kwargs=histops,
|
|
1259
|
+
showcontours=showcontours,
|
|
1260
|
+
contour_levels=credintervals,
|
|
1261
|
+
contour_kwargs=contourops,
|
|
1262
|
+
truths_kwargs=truthops,
|
|
1263
|
+
contour_limits=contourlimits,
|
|
1264
|
+
limits=figlimits,
|
|
1265
|
+
show_level_labels=False,
|
|
1266
|
+
showpoints=showpoints,
|
|
1267
|
+
scatter_kwargs=scatter_kwargs,
|
|
1268
|
+
subtract_truths=subtract_truths,
|
|
1269
|
+
)
|
|
1270
|
+
|
|
1271
|
+
# now add the rest to the plots
|
|
1272
|
+
if len(plotifos) > 1:
|
|
1273
|
+
for k, ifo in enumerate(plotifos[1:]):
|
|
1274
|
+
histops = {
|
|
1275
|
+
"histtype": "step",
|
|
1276
|
+
"color": coldict[ifo],
|
|
1277
|
+
"edgecolor": coldict[ifo],
|
|
1278
|
+
"linewidth": 1,
|
|
1279
|
+
}
|
|
1280
|
+
x = self._posteriors[ifo][parameters[0]].samples
|
|
1281
|
+
for param in parameters[1:]:
|
|
1282
|
+
x = np.hstack((x, self._posteriors[ifo][param].samples))
|
|
1283
|
+
showcontours = self._showcontours
|
|
1284
|
+
contourops = {"colors": "dark" + coldict[plotifos[k + 1]]}
|
|
1285
|
+
if whichtruth == plotifos[k + 1]:
|
|
1286
|
+
truthops = {"color": "black", "markeredgewidth": 2}
|
|
1287
|
+
elif whichtruth == "all":
|
|
1288
|
+
truthops = {
|
|
1289
|
+
"color": "dark" + coldict[plotifos[k + 1]],
|
|
1290
|
+
"markeredgewidth": 2,
|
|
1291
|
+
}
|
|
1292
|
+
else:
|
|
1293
|
+
truthops = {}
|
|
1294
|
+
sc.add_data(
|
|
1295
|
+
x,
|
|
1296
|
+
hist_kwargs=histops,
|
|
1297
|
+
datatitle=ifo,
|
|
1298
|
+
truths=truths[ifo],
|
|
1299
|
+
showcontours=showcontours,
|
|
1300
|
+
contour_kwargs=contourops,
|
|
1301
|
+
contour_levels=credintervals,
|
|
1302
|
+
show_level_labels=False,
|
|
1303
|
+
truths_kwargs=truthops,
|
|
1304
|
+
scatter_kwargs=scatter_kwargs,
|
|
1305
|
+
contour_limits=contourlimits,
|
|
1306
|
+
limits=figlimits,
|
|
1307
|
+
)
|
|
1308
|
+
|
|
1309
|
+
# add priors plots if required
|
|
1310
|
+
if self._priorfile is not None and len(self._prior_parameters) > 0:
|
|
1311
|
+
for priorparam in self._prior_parameters:
|
|
1312
|
+
if priorparam.lower() in parameters:
|
|
1313
|
+
# get axes for that parameter
|
|
1314
|
+
thisax = sc.get_axis(labels[parameters.index(priorparam.lower())])
|
|
1315
|
+
|
|
1316
|
+
atruth = None
|
|
1317
|
+
if (
|
|
1318
|
+
truths is not None
|
|
1319
|
+
and self._subtract_truths is not None
|
|
1320
|
+
and priorparam.lower() not in amppars
|
|
1321
|
+
):
|
|
1322
|
+
atruth = truths[plotifos[0]][
|
|
1323
|
+
parameters.index(priorparam.lower())
|
|
1324
|
+
]
|
|
1325
|
+
|
|
1326
|
+
# check if this is the vertical histogram or not
|
|
1327
|
+
vertaxrange = sc.histvert[-1].get_ylim()
|
|
1328
|
+
yl = thisax.get_ylim()
|
|
1329
|
+
if (
|
|
1330
|
+
yl[0] == vertaxrange[0] and yl[1] == vertaxrange[1]
|
|
1331
|
+
): # vertical histogram
|
|
1332
|
+
self.plot_prior(
|
|
1333
|
+
thisax,
|
|
1334
|
+
priorparam,
|
|
1335
|
+
self._prior_parameters,
|
|
1336
|
+
truth=atruth,
|
|
1337
|
+
orientation="vertical",
|
|
1338
|
+
)
|
|
1339
|
+
else:
|
|
1340
|
+
self.plot_prior(
|
|
1341
|
+
thisax,
|
|
1342
|
+
priorparam,
|
|
1343
|
+
self._prior_parameters,
|
|
1344
|
+
truth=atruth,
|
|
1345
|
+
orientation="horizontal",
|
|
1346
|
+
)
|
|
1347
|
+
|
|
1348
|
+
# output the plots
|
|
1349
|
+
if "png" not in figformats and "svg" not in figformats:
|
|
1350
|
+
print(
|
|
1351
|
+
"Error... must include 'png' and/or 'svg' in the output figure formats",
|
|
1352
|
+
file=sys.stderr,
|
|
1353
|
+
)
|
|
1354
|
+
sys.exit(1)
|
|
1355
|
+
|
|
1356
|
+
if filename == None: # use default file names
|
|
1357
|
+
if len(parameters) == len(self._parameters):
|
|
1358
|
+
outfilepre = os.path.join(self._outputdir, "all_posteriors")
|
|
1359
|
+
else:
|
|
1360
|
+
outfilepre = os.path.join(self._outputdir, "vs".join(parameters))
|
|
1361
|
+
else:
|
|
1362
|
+
outfilepre = os.path.join(self._outputdir, filename)
|
|
1363
|
+
|
|
1364
|
+
outfiles = []
|
|
1365
|
+
for ftype in figformats:
|
|
1366
|
+
outfile = outfilepre + "." + ftype
|
|
1367
|
+
try:
|
|
1368
|
+
sc.fig.subplots_adjust(
|
|
1369
|
+
left=0.18, bottom=0.18
|
|
1370
|
+
) # adjust size to accommodate axes labels
|
|
1371
|
+
sc.savefig(outfile)
|
|
1372
|
+
except:
|
|
1373
|
+
print(
|
|
1374
|
+
"Error... could not output posterior plot file '%s'." % outfile,
|
|
1375
|
+
file=sys.stderr,
|
|
1376
|
+
)
|
|
1377
|
+
sys.exit(1)
|
|
1378
|
+
outfiles.append(outfile)
|
|
1379
|
+
|
|
1380
|
+
return outfiles # list of output figure file names
|
|
1381
|
+
|
|
1382
|
+
def plot_prior(
|
|
1383
|
+
self, ax, param, prior, orientation="horizontal", truth=0.0, npoints=100
|
|
1384
|
+
):
|
|
1385
|
+
# plot the prior distribution (with truth subtracted if non-zero)
|
|
1386
|
+
priortype = list(prior[param].keys())[0]
|
|
1387
|
+
priorrange = list(prior[param].values())[0]
|
|
1388
|
+
|
|
1389
|
+
if truth is None:
|
|
1390
|
+
truth = 0.0
|
|
1391
|
+
|
|
1392
|
+
if orientation == "horizontal":
|
|
1393
|
+
valrange = np.linspace(ax.get_xlim()[0], ax.get_xlim()[1], npoints)
|
|
1394
|
+
elif orientation == "vertical":
|
|
1395
|
+
valrange = np.linspace(ax.get_ylim()[0], ax.get_ylim()[1], npoints)
|
|
1396
|
+
else:
|
|
1397
|
+
print(
|
|
1398
|
+
"Error... axis orientation not recognised. Must be 'horizontal' or 'vertical'.",
|
|
1399
|
+
file=sys.stderr,
|
|
1400
|
+
)
|
|
1401
|
+
sys.exit(1)
|
|
1402
|
+
|
|
1403
|
+
# get the prior distributions
|
|
1404
|
+
if priortype == "uniform":
|
|
1405
|
+
vals = stats.uniform.pdf(
|
|
1406
|
+
valrange, priorrange[0] - truth, priorrange[1] - priorrange[0]
|
|
1407
|
+
)
|
|
1408
|
+
elif priortype == "gaussian":
|
|
1409
|
+
# crude (not taking account of wrap-around) shift of phi0 and psi into 0->pi and 0->pi/2 ranges)
|
|
1410
|
+
if param.lower() == "psi":
|
|
1411
|
+
priorrange[0] = np.mod(priorrange[0], np.pi / 2.0)
|
|
1412
|
+
if param.lower() == "phi0":
|
|
1413
|
+
if self._usegwphase:
|
|
1414
|
+
priorrange[0] = np.mod(priorrange[0], 2.0 * pi)
|
|
1415
|
+
else:
|
|
1416
|
+
priorrange[0] = np.mod(priorrange[0], pi)
|
|
1417
|
+
|
|
1418
|
+
vals = stats.norm.pdf(valrange, priorrange[0] - truth, priorrange[1])
|
|
1419
|
+
elif (
|
|
1420
|
+
priortype == "fermidirac"
|
|
1421
|
+
): # don't subtract truth from Fermi-Dirac as it should only be use for amplitude parameters anyway
|
|
1422
|
+
sigma = priorrange[0]
|
|
1423
|
+
r = priorrange[1]
|
|
1424
|
+
mu = sigma * r
|
|
1425
|
+
vals = 1.0 / (
|
|
1426
|
+
(sigma * np.log(1.0 + np.exp(r)))
|
|
1427
|
+
* (np.exp((valrange - mu) / sigma) + 1.0)
|
|
1428
|
+
)
|
|
1429
|
+
elif priortype == "loguniform":
|
|
1430
|
+
vals = np.zeros(len(valrange))
|
|
1431
|
+
indices = (valrange >= priorrange[0]) & (valrange <= priorrange[1])
|
|
1432
|
+
vals[indices] = 1.0 / (
|
|
1433
|
+
valrange[indices] * np.log(priorrange[1] / priorrange[0])
|
|
1434
|
+
)
|
|
1435
|
+
elif priortype == "gmm":
|
|
1436
|
+
vals = np.zeros(len(valrange))
|
|
1437
|
+
nmodes = priorrange["nmodes"] # number of modes in GMM
|
|
1438
|
+
pindex = priorrange["pindex"] # parameter index in GMM prior
|
|
1439
|
+
mmeans = np.array([mm[pindex] for mm in priorrange["means"]]) # means
|
|
1440
|
+
mcovs = priorrange["covs"] # covariance matrices
|
|
1441
|
+
mstddevs = []
|
|
1442
|
+
for cov in mcovs:
|
|
1443
|
+
mstddevs.append(np.sqrt(cov[pindex][pindex]))
|
|
1444
|
+
mweights = priorrange["weights"]
|
|
1445
|
+
# check bounds
|
|
1446
|
+
bmin = -np.inf
|
|
1447
|
+
bmax = np.inf
|
|
1448
|
+
plims = priorrange["limits"][pindex]
|
|
1449
|
+
if np.isfinite(plims[0]):
|
|
1450
|
+
bmin = plims[0]
|
|
1451
|
+
if np.isfinite(plims[1]):
|
|
1452
|
+
bmax = plims[1]
|
|
1453
|
+
indices = (valrange >= bmin) & (valrange <= bmax)
|
|
1454
|
+
|
|
1455
|
+
# crude (not taking account of wrap-around) shift of phi0 and psi into 0->pi and 0->pi/2 ranges)
|
|
1456
|
+
if param.lower() == "psi":
|
|
1457
|
+
mmeans = np.mod(mmeans, np.pi / 2.0)
|
|
1458
|
+
if param.lower() == "phi0":
|
|
1459
|
+
if self._usegwphase:
|
|
1460
|
+
mmeans = np.mod(mmeans, 2.0 * pi)
|
|
1461
|
+
else:
|
|
1462
|
+
mmeans = np.mod(mmeans, pi)
|
|
1463
|
+
|
|
1464
|
+
# create Gaussian mixture model
|
|
1465
|
+
for i in range(nmodes):
|
|
1466
|
+
vals[indices] += mweights[i] * stats.norm.pdf(
|
|
1467
|
+
valrange[indices], mmeans[i] - truth, mstddevs[i]
|
|
1468
|
+
)
|
|
1469
|
+
# normalise
|
|
1470
|
+
vals = vals / np.trapz(vals, valrange)
|
|
1471
|
+
else:
|
|
1472
|
+
print(
|
|
1473
|
+
"Error... prior type '%s' not recognised." % priortype, file=sys.stderr
|
|
1474
|
+
)
|
|
1475
|
+
sys.exit(1)
|
|
1476
|
+
|
|
1477
|
+
# make plots
|
|
1478
|
+
if orientation == "horizontal":
|
|
1479
|
+
ax.plot(
|
|
1480
|
+
valrange, vals, linestyle="--", color="lightslategray", linewidth=1.5
|
|
1481
|
+
)
|
|
1482
|
+
if orientation == "vertical":
|
|
1483
|
+
ax.plot(
|
|
1484
|
+
vals, valrange, linestyle="--", color="lightslategray", linewidth=1.5
|
|
1485
|
+
)
|
|
1486
|
+
|
|
1487
|
+
# create standard joint plots
|
|
1488
|
+
def create_joint_plots_table(self, allparams=False, title="Joint distributions"):
|
|
1489
|
+
# create a table containing a set of standard 2D or 3D joint posterior plots (depending on the analysis setup)
|
|
1490
|
+
header = htmltag("h2", title, newline=True)
|
|
1491
|
+
|
|
1492
|
+
table = htmltable()
|
|
1493
|
+
table.addrow()
|
|
1494
|
+
paramlist = []
|
|
1495
|
+
|
|
1496
|
+
# set limits for credible interval contours plots using maximum allowed ranges (see e.g. Tables 1 and 2 of http://arxiv.org/abs/1508.00416v2)
|
|
1497
|
+
limits = {}
|
|
1498
|
+
for param in self._parameters:
|
|
1499
|
+
if param == "h0":
|
|
1500
|
+
# only set lower limit on amplitudes if posteriors are close (less than 3 sigma) to zero
|
|
1501
|
+
limits[param] = ()
|
|
1502
|
+
for ifo in self._ifos:
|
|
1503
|
+
if (
|
|
1504
|
+
self._posteriors[ifo][param].mean
|
|
1505
|
+
- 3.0 * self._posteriors[ifo][param].stdev
|
|
1506
|
+
< 0.0
|
|
1507
|
+
):
|
|
1508
|
+
limits[param] = (0.0, None) # must be greater than 0.
|
|
1509
|
+
break
|
|
1510
|
+
elif param == "cosiota":
|
|
1511
|
+
limits[param] = (-1.0, 1.0) # cos(iota)
|
|
1512
|
+
elif param == "phi0":
|
|
1513
|
+
if self._usegwphase:
|
|
1514
|
+
limits[param] = (0.0, 2.0 * np.pi)
|
|
1515
|
+
else:
|
|
1516
|
+
limits[param] = (0.0, np.pi)
|
|
1517
|
+
elif param == "psi":
|
|
1518
|
+
if self._biaxial and self._modeltype == "source":
|
|
1519
|
+
limits[param] = (0.0, np.pi)
|
|
1520
|
+
else:
|
|
1521
|
+
limits[param] = (0.0, np.pi / 2.0)
|
|
1522
|
+
elif param == "c21" or param == "c22":
|
|
1523
|
+
if self._biaxial and self._modeltype == "waveform":
|
|
1524
|
+
limits[param] = ()
|
|
1525
|
+
else:
|
|
1526
|
+
limits[param] = ()
|
|
1527
|
+
for ifo in self._ifos:
|
|
1528
|
+
if (
|
|
1529
|
+
self._posteriors[ifo][param].mean
|
|
1530
|
+
- 3.0 * self._posteriors[ifo][param].stdev
|
|
1531
|
+
< 0.0
|
|
1532
|
+
):
|
|
1533
|
+
limits[param] = (0.0, None) # must be greater than 0.
|
|
1534
|
+
break
|
|
1535
|
+
elif param == "lambda":
|
|
1536
|
+
limits[param] = (0.0, np.pi)
|
|
1537
|
+
elif param == "costheta":
|
|
1538
|
+
limits[param] = (0.0, 1.0)
|
|
1539
|
+
else: # default to empty tuple
|
|
1540
|
+
limits[param] = () # empty tuple
|
|
1541
|
+
|
|
1542
|
+
if allparams: # plot all parameters
|
|
1543
|
+
paramlist = [self._parameters]
|
|
1544
|
+
else:
|
|
1545
|
+
if len(self._harmonics) == 1:
|
|
1546
|
+
if harmonics[0] == 2.0: # for emission at twice the rotation frequency
|
|
1547
|
+
# plot h0 versus cos(iota) and psi verus phi0
|
|
1548
|
+
paramlist = [["h0", "cosiota"], ["phi0", "psi"]]
|
|
1549
|
+
else:
|
|
1550
|
+
if self._modeltype == "source":
|
|
1551
|
+
print(
|
|
1552
|
+
"Error... do not know 'source' parameterisation for emission at purely the rotation frequency",
|
|
1553
|
+
file=sys.stderr,
|
|
1554
|
+
)
|
|
1555
|
+
sys.exit(1)
|
|
1556
|
+
else:
|
|
1557
|
+
# plot C21 versus cosiota and psi versus phi21
|
|
1558
|
+
paramlist = [["c21", "cosiota"], ["phi21", "psi"]]
|
|
1559
|
+
else:
|
|
1560
|
+
if self._modeltype == "source":
|
|
1561
|
+
if self._biaxial:
|
|
1562
|
+
# plot I31 vs cosiota vs phi0 and psi vs lambda vs theta (I21 is zero)
|
|
1563
|
+
paramlist = [
|
|
1564
|
+
["i31", "cosiota", "phi0"],
|
|
1565
|
+
["psi", "lambda", "costheta"],
|
|
1566
|
+
]
|
|
1567
|
+
else:
|
|
1568
|
+
# plot I21 vs I31 vs cosiota and phi0 vs psi vs lambda vs theta
|
|
1569
|
+
paramlist = [
|
|
1570
|
+
["i21", "i31", "cosiota"],
|
|
1571
|
+
["phi0", "psi", "lambda", "costheta"],
|
|
1572
|
+
]
|
|
1573
|
+
else:
|
|
1574
|
+
# plot C21 vs C22 vs cosiota and psi vs phi21 vs phi22
|
|
1575
|
+
paramlist = [["c21", "c22", "cosiota"], ["psi", "phi21", "phi22"]]
|
|
1576
|
+
|
|
1577
|
+
notpresent = False
|
|
1578
|
+
for parampairs in paramlist:
|
|
1579
|
+
contourlimits = []
|
|
1580
|
+
figlimits = []
|
|
1581
|
+
for p in parampairs:
|
|
1582
|
+
if p not in self._parameters:
|
|
1583
|
+
notpresent = True
|
|
1584
|
+
else:
|
|
1585
|
+
contourlimits.append(limits[p])
|
|
1586
|
+
figlimits.append(limits[p])
|
|
1587
|
+
if notpresent:
|
|
1588
|
+
break
|
|
1589
|
+
|
|
1590
|
+
pf = self.create_joint_posterior_plot(
|
|
1591
|
+
parampairs,
|
|
1592
|
+
figformats=["png"],
|
|
1593
|
+
ratio=2,
|
|
1594
|
+
figlimits=figlimits,
|
|
1595
|
+
contourlimits=contourlimits,
|
|
1596
|
+
jointsamples=False,
|
|
1597
|
+
)
|
|
1598
|
+
if allparams:
|
|
1599
|
+
tagclass = "jointplot"
|
|
1600
|
+
else:
|
|
1601
|
+
tagclass = "posplot"
|
|
1602
|
+
table.adddata(
|
|
1603
|
+
atag(
|
|
1604
|
+
os.path.basename(pf[0]),
|
|
1605
|
+
'<img class="{}" src="{}"/>'.format(
|
|
1606
|
+
tagclass, os.path.basename(pf[0])
|
|
1607
|
+
),
|
|
1608
|
+
).text
|
|
1609
|
+
)
|
|
1610
|
+
|
|
1611
|
+
return header.text + table.tabletext
|
|
1612
|
+
|
|
1613
|
+
def create_sample_plot_table(self, figformats=["png"]):
|
|
1614
|
+
# create the table of posterior sample plots
|
|
1615
|
+
if "png" not in figformats:
|
|
1616
|
+
print(
|
|
1617
|
+
"Error... must include 'png' in the output figure formats",
|
|
1618
|
+
file=sys.stderr,
|
|
1619
|
+
)
|
|
1620
|
+
sys.exit(1)
|
|
1621
|
+
|
|
1622
|
+
header = htmltag(
|
|
1623
|
+
"h2", "Posterior samples", newline=True
|
|
1624
|
+
) # the output html table
|
|
1625
|
+
|
|
1626
|
+
table = htmltable()
|
|
1627
|
+
|
|
1628
|
+
# get the plots
|
|
1629
|
+
for param in self._parameters:
|
|
1630
|
+
chainfig = plot_posterior_chain(
|
|
1631
|
+
self._posteriors.values(), param, self._ifos, grr=None
|
|
1632
|
+
)
|
|
1633
|
+
chainfile = os.path.join(self._outputdir, param + "_postchain")
|
|
1634
|
+
|
|
1635
|
+
for ftype in figformats:
|
|
1636
|
+
thischainfile = chainfile + "." + ftype
|
|
1637
|
+
try:
|
|
1638
|
+
chainfig.savefig(thischainfile)
|
|
1639
|
+
except:
|
|
1640
|
+
print(
|
|
1641
|
+
"Error... could not output posterior samples plot for '%s'."
|
|
1642
|
+
% param,
|
|
1643
|
+
file=sys.stderr,
|
|
1644
|
+
)
|
|
1645
|
+
sys.exit(1)
|
|
1646
|
+
|
|
1647
|
+
if ftype == "png":
|
|
1648
|
+
table.addrow()
|
|
1649
|
+
table.adddata(
|
|
1650
|
+
atag(
|
|
1651
|
+
os.path.basename(thischainfile),
|
|
1652
|
+
'<img class="chainplot" src="{}"/>'.format(
|
|
1653
|
+
os.path.basename(thischainfile)
|
|
1654
|
+
),
|
|
1655
|
+
).text
|
|
1656
|
+
)
|
|
1657
|
+
|
|
1658
|
+
self._samples_table = header.text + table.tabletext
|
|
1659
|
+
return self._samples_table # output html for table
|
|
1660
|
+
|
|
1661
|
+
def create_stats_table(self, credints=[95]):
|
|
1662
|
+
# create table of posterior sample statistics, including credible intervals given by the list
|
|
1663
|
+
self._credint = credints
|
|
1664
|
+
for ci in self._credint:
|
|
1665
|
+
if ci >= 100.0 or ci <= 0.0:
|
|
1666
|
+
print(
|
|
1667
|
+
"Error... credible interval '%s' is outside the range between 0%% and 100%%."
|
|
1668
|
+
% str(ci),
|
|
1669
|
+
file=sys.stderr,
|
|
1670
|
+
)
|
|
1671
|
+
sys.exit(1)
|
|
1672
|
+
|
|
1673
|
+
header = htmltag("h2", "Posterior statistics", newline=True)
|
|
1674
|
+
|
|
1675
|
+
table = htmltable()
|
|
1676
|
+
|
|
1677
|
+
cols = ["Detector", "max. poterior", "mean", "median", "σ"]
|
|
1678
|
+
for ci in self._credint:
|
|
1679
|
+
cols.append("%d%% credible interval" % int(ci))
|
|
1680
|
+
if self._injection_parameters != None:
|
|
1681
|
+
cols.insert(0, "Inj. value") # prepend the injection value
|
|
1682
|
+
cols.insert(0, " ") # add empty cell as header line for the parameter name
|
|
1683
|
+
|
|
1684
|
+
# create header row
|
|
1685
|
+
table.addrow()
|
|
1686
|
+
for col in cols:
|
|
1687
|
+
table.adddata(col, header=True)
|
|
1688
|
+
|
|
1689
|
+
# loop through parameters header row to table
|
|
1690
|
+
for i, param in enumerate(self._parameters):
|
|
1691
|
+
pu = param.upper()
|
|
1692
|
+
dispkwargs = (
|
|
1693
|
+
{}
|
|
1694
|
+
) # any additional arguments required by value display function
|
|
1695
|
+
|
|
1696
|
+
# parameter html to display
|
|
1697
|
+
if pu in paramhtmldict:
|
|
1698
|
+
pdisp = paramhtmldict[pu]
|
|
1699
|
+
|
|
1700
|
+
# some different display styles (compared to the defaults) for certain parameters
|
|
1701
|
+
if pu in ["RA", "DEC", "RAJ", "DECJ"]:
|
|
1702
|
+
dispkwargs = {
|
|
1703
|
+
"stype": "rads"
|
|
1704
|
+
} # display as rad rather than hh/dd:mm:ss string
|
|
1705
|
+
if pu == "F0":
|
|
1706
|
+
dispkwargs = {"dp": 2} # just display with 2 decimal places
|
|
1707
|
+
else:
|
|
1708
|
+
pdisp = param
|
|
1709
|
+
|
|
1710
|
+
# parameter value function to display
|
|
1711
|
+
if pu in paramhtmldispfunc.__dict__:
|
|
1712
|
+
dispfunc = paramhtmldispfunc.__dict__[pu]
|
|
1713
|
+
else:
|
|
1714
|
+
dispfunc = paramhtmldispfunc.__dict__["DEFAULTSTR"]
|
|
1715
|
+
|
|
1716
|
+
for j, ifo in enumerate(self._ifos):
|
|
1717
|
+
table.addrow()
|
|
1718
|
+
if j == 0: # add parameter name and injection value first)
|
|
1719
|
+
table.adddata(pdisp, rowspan=len(self._ifos))
|
|
1720
|
+
if self._injection_parameters != None:
|
|
1721
|
+
if hasattr(self._injection_parameters, param.upper()):
|
|
1722
|
+
table.adddata(
|
|
1723
|
+
dispfunc(
|
|
1724
|
+
str(self._injection_parameters[param.upper()]),
|
|
1725
|
+
**dispkwargs,
|
|
1726
|
+
),
|
|
1727
|
+
rowspan=len(self._ifos),
|
|
1728
|
+
)
|
|
1729
|
+
else:
|
|
1730
|
+
table.adddata(
|
|
1731
|
+
"*", rowspan=len(self._ifos)
|
|
1732
|
+
) # no value for this parameter
|
|
1733
|
+
|
|
1734
|
+
if i == 0:
|
|
1735
|
+
self._injection_credible_regions[
|
|
1736
|
+
ifo
|
|
1737
|
+
] = (
|
|
1738
|
+
{}
|
|
1739
|
+
) # dictionary for injection minimal credible regions to be input for each parameter
|
|
1740
|
+
maxL, maxLparams = self._posteriors[ifo].maxL
|
|
1741
|
+
table.adddata(ifo, dataclass=ifo)
|
|
1742
|
+
table.adddata(
|
|
1743
|
+
dispfunc(str(maxLparams[param]), **dispkwargs)
|
|
1744
|
+
) # maximum likelihood
|
|
1745
|
+
table.adddata(
|
|
1746
|
+
dispfunc(str(self._posteriors[ifo].means[param]), **dispkwargs)
|
|
1747
|
+
) # mean value
|
|
1748
|
+
table.adddata(
|
|
1749
|
+
dispfunc(str(self._posteriors[ifo].medians[param]), **dispkwargs)
|
|
1750
|
+
) # median value
|
|
1751
|
+
tdispkwargs = dispkwargs
|
|
1752
|
+
if param.upper() in ["T0", "TASC"]:
|
|
1753
|
+
tdispkwargs = {"stype": "diff"} # don't display values in MJD
|
|
1754
|
+
table.adddata(
|
|
1755
|
+
dispfunc(str(self._posteriors[ifo].stdevs[param]), **tdispkwargs)
|
|
1756
|
+
) # standard deviations
|
|
1757
|
+
|
|
1758
|
+
for k, ci in enumerate(credints):
|
|
1759
|
+
paramval = None
|
|
1760
|
+
if k == 0 and self._injection_parameters != None:
|
|
1761
|
+
if hasattr(self._injection_parameters, param.upper()):
|
|
1762
|
+
paramval = self._injection_parameters[param.upper()]
|
|
1763
|
+
low, high, cr = self.credible_interval(ifo, param, ci, paramval)
|
|
1764
|
+
|
|
1765
|
+
if k == 0 and self._injection_parameters != None:
|
|
1766
|
+
if hasattr(self._injection_parameters, param.upper()):
|
|
1767
|
+
self._injection_credible_regions[ifo][param] = cr
|
|
1768
|
+
|
|
1769
|
+
table.adddata(
|
|
1770
|
+
"({}, {})".format(
|
|
1771
|
+
dispfunc(str(low), **dispkwargs),
|
|
1772
|
+
dispfunc(str(high), **dispkwargs),
|
|
1773
|
+
)
|
|
1774
|
+
)
|
|
1775
|
+
|
|
1776
|
+
self._stats_section = header.text + table.tabletext
|
|
1777
|
+
return self._stats_section
|
|
1778
|
+
|
|
1779
|
+
def create_limits_table(self, freq, sdlim=None, dist=None, ul=95):
|
|
1780
|
+
# create a table with upper limits on amplitudes and Bayes factors
|
|
1781
|
+
self._limits_table = ""
|
|
1782
|
+
|
|
1783
|
+
table = htmltable()
|
|
1784
|
+
|
|
1785
|
+
self._h0ul = {}
|
|
1786
|
+
self._C21 = {}
|
|
1787
|
+
self._C22 = {}
|
|
1788
|
+
self._I21 = {}
|
|
1789
|
+
self._I31 = {}
|
|
1790
|
+
self._sdratio = {}
|
|
1791
|
+
self._ellipticity = {}
|
|
1792
|
+
self._q22 = {}
|
|
1793
|
+
|
|
1794
|
+
# add header row
|
|
1795
|
+
table.addrow()
|
|
1796
|
+
|
|
1797
|
+
table.adddata(" ", header=True) # nothing in the first column
|
|
1798
|
+
|
|
1799
|
+
if len(self._harmonics) == 1 and self._harmonics[0] == 2:
|
|
1800
|
+
table.adddata(paramhtmldict["H0UL"].format(ul), header=True)
|
|
1801
|
+
table.adddata(paramhtmldict["ELL"], header=True)
|
|
1802
|
+
table.adddata(paramhtmldict["Q22"], header=True)
|
|
1803
|
+
table.adddata(paramhtmldict["SDRAT"], header=True)
|
|
1804
|
+
elif (
|
|
1805
|
+
len(self._harmonics) == 1
|
|
1806
|
+
and self._harmonics[0] == 1
|
|
1807
|
+
and self._modeltype == "waveform"
|
|
1808
|
+
):
|
|
1809
|
+
table.adddata(paramhtmldict["C21UL"].format(ul), header=True)
|
|
1810
|
+
elif len(self._harmonics) == 2 and self._modeltype == "waveform":
|
|
1811
|
+
table.adddata(paramhtmldict["C21UL"].format(ul), header=True)
|
|
1812
|
+
table.adddata(paramhtmldict["C22UL"].format(ul), header=True)
|
|
1813
|
+
table.adddata(
|
|
1814
|
+
paramhtmldict["H0UL"].format(ul) + " (from C<sub>22</sub>)", header=True
|
|
1815
|
+
)
|
|
1816
|
+
table.adddata(paramhtmldict["ELL"] + " (from C<sub>22</sub>)", header=True)
|
|
1817
|
+
table.adddata(paramhtmldict["Q22"] + " (from C<sub>22</sub>)", header=True)
|
|
1818
|
+
table.adddata("ratio", header=True)
|
|
1819
|
+
elif len(self._harmonics) == 2 and self._modeltype == "source":
|
|
1820
|
+
if not self._biaixal:
|
|
1821
|
+
table.adddata(
|
|
1822
|
+
paramhtmldict["I21UL"].format(ul), header=True
|
|
1823
|
+
) # not needed for a biaxial source
|
|
1824
|
+
table.adddata(paramhtmldict["I31UL"].format(ul), header=True)
|
|
1825
|
+
else:
|
|
1826
|
+
print(
|
|
1827
|
+
"Error... do not know how to output results table for this situation.",
|
|
1828
|
+
file=sys.stderr,
|
|
1829
|
+
)
|
|
1830
|
+
sys.exit(1)
|
|
1831
|
+
|
|
1832
|
+
# add SNR
|
|
1833
|
+
table.adddata(paramhtmldict["SNR"], header=True)
|
|
1834
|
+
|
|
1835
|
+
# add max log likelihood
|
|
1836
|
+
table.adddata(paramhtmldict["MAXL"], header=True)
|
|
1837
|
+
|
|
1838
|
+
# add Bayes factor (signal vs noise)
|
|
1839
|
+
table.adddata(paramhtmldict["BSN"], header=True)
|
|
1840
|
+
|
|
1841
|
+
# check whether to add coherent vs incoherent Bayes factor (and coherent vs (incoherent or noise) Bayes factor)
|
|
1842
|
+
if len(self._ifos) > 2 and "Joint" in self._ifos:
|
|
1843
|
+
table.adddata(paramhtmldict["BCI"], header=True)
|
|
1844
|
+
table.adddata(paramhtmldict["BCIN"], header=True)
|
|
1845
|
+
|
|
1846
|
+
for ifo in self._ifos:
|
|
1847
|
+
table.addrow()
|
|
1848
|
+
table.adddata("{}".format(ifo), dataclass=ifo)
|
|
1849
|
+
|
|
1850
|
+
if self._modeltype == "waveform" and len(self._harmonics) == 2:
|
|
1851
|
+
for p in ["c21", "c22"]:
|
|
1852
|
+
Cul = upper_limit_greedy(
|
|
1853
|
+
self._posteriors[ifo][p].samples, upperlimit=(ul / 100.0)
|
|
1854
|
+
)
|
|
1855
|
+
table.adddata("{}".format(exp_str(Cul)), dataclass=ifo)
|
|
1856
|
+
if p == "c21":
|
|
1857
|
+
self._C21[ifo] = Cul
|
|
1858
|
+
if p == "c22":
|
|
1859
|
+
self._C22[ifo] = Cul
|
|
1860
|
+
|
|
1861
|
+
self._h0ul[ifo] = self._C22[ifo] * 2.0
|
|
1862
|
+
table.adddata(
|
|
1863
|
+
"{}".format(exp_str(self._h0ul[ifo])), dataclass=ifo
|
|
1864
|
+
) # convert to h0
|
|
1865
|
+
|
|
1866
|
+
if (len(self._harmonics) == 1 and self._harmonics[0] == 2) or (
|
|
1867
|
+
len(self._harmonics) == 2 and self._modeltype == "waveform"
|
|
1868
|
+
):
|
|
1869
|
+
# get h0 upper limit
|
|
1870
|
+
if len(self._harmonics) == 1 and self._harmonics[0] == 2:
|
|
1871
|
+
h0ul = upper_limit_greedy(
|
|
1872
|
+
self._posteriors[ifo]["h0"].samples, upperlimit=(ul / 100.0)
|
|
1873
|
+
)
|
|
1874
|
+
self._h0ul[ifo] = h0ul
|
|
1875
|
+
table.adddata("{}".format(exp_str(h0ul)), dataclass=ifo)
|
|
1876
|
+
|
|
1877
|
+
# ellipticity
|
|
1878
|
+
if dist == None:
|
|
1879
|
+
self._ellipticity[ifo] = None
|
|
1880
|
+
table.adddata("*", dataclass=ifo)
|
|
1881
|
+
else:
|
|
1882
|
+
self._ellipticity[ifo] = h0_to_ellipticity(
|
|
1883
|
+
self._h0ul[ifo], freq, dist
|
|
1884
|
+
)
|
|
1885
|
+
table.adddata(
|
|
1886
|
+
"{}".format(exp_str(self._ellipticity[ifo])), dataclass=ifo
|
|
1887
|
+
)
|
|
1888
|
+
|
|
1889
|
+
# quadrupole
|
|
1890
|
+
if dist == None:
|
|
1891
|
+
self._q22[ifo] = None
|
|
1892
|
+
table.adddata("*", dataclass=ifo)
|
|
1893
|
+
else:
|
|
1894
|
+
self._q22[ifo] = h0_to_quadrupole(self._h0ul[ifo], freq, dist)
|
|
1895
|
+
table.adddata("{}".format(exp_str(self._q22[ifo])), dataclass=ifo)
|
|
1896
|
+
|
|
1897
|
+
# get spin down limit ratio
|
|
1898
|
+
if sdlim == None:
|
|
1899
|
+
self._sdratio[ifo] = None
|
|
1900
|
+
table.adddata("*", dataclass=ifo)
|
|
1901
|
+
else:
|
|
1902
|
+
self._sdratio[ifo] = self._h0ul[ifo] / sdlim
|
|
1903
|
+
table.adddata("%.02f" % self._sdratio[ifo], dataclass=ifo)
|
|
1904
|
+
|
|
1905
|
+
if len(self._harmonics) == 2 and self._modeltype == "source":
|
|
1906
|
+
if not self._biaxial:
|
|
1907
|
+
self._I21[ifo] = upper_limit_greedy(
|
|
1908
|
+
self._posteriors[ifo]["I21"].samples, upperlimit=(ul / 100.0)
|
|
1909
|
+
)
|
|
1910
|
+
table.adddata("{}".format(exp_str(self._I21[ifo])), dataclass=ifo)
|
|
1911
|
+
|
|
1912
|
+
self._I31[ifo] = upper_limit_greedy(
|
|
1913
|
+
self._posteriors[ifo]["I31"].samples, upperlimit=(ul / 100.0)
|
|
1914
|
+
)
|
|
1915
|
+
table.adddata("{}".format(exp_str(self._I31[ifo])), dataclass=ifo)
|
|
1916
|
+
|
|
1917
|
+
# add SNR
|
|
1918
|
+
if ifo in self._optimal_snrs:
|
|
1919
|
+
table.adddata("%.1f" % self._optimal_snrs[ifo], dataclass=ifo)
|
|
1920
|
+
else:
|
|
1921
|
+
table.adddata("*", dataclass=ifo)
|
|
1922
|
+
|
|
1923
|
+
# add max log likelihood values
|
|
1924
|
+
table.adddata(
|
|
1925
|
+
"%.f" % (self._maxL[ifo] / np.log(10.0)), dataclass=ifo
|
|
1926
|
+
) # convert to log base 10
|
|
1927
|
+
table.adddata(
|
|
1928
|
+
"%.1f" % (self._Bsn[ifo] / np.log(10.0)), dataclass=ifo
|
|
1929
|
+
) # convert to log base 10
|
|
1930
|
+
|
|
1931
|
+
# add coherent vs incoherent and coherent vs (incoherent or noise) for Joint ifo)
|
|
1932
|
+
if len(self._ifos) > 2 and "Joint" in self._ifos:
|
|
1933
|
+
if ifo == "Joint":
|
|
1934
|
+
table.adddata(
|
|
1935
|
+
"%.1f" % (self._Bci / np.log(10.0)), dataclass=ifo
|
|
1936
|
+
) # convert to log base 10
|
|
1937
|
+
table.adddata(
|
|
1938
|
+
"%.1f" % (self._Bcin / np.log(10.0)), dataclass=ifo
|
|
1939
|
+
) # convert to log base 10
|
|
1940
|
+
else:
|
|
1941
|
+
table.adddata("*", dataclass=ifo)
|
|
1942
|
+
table.adddata("*", dataclass=ifo)
|
|
1943
|
+
|
|
1944
|
+
self._limits_table += table.tabletext
|
|
1945
|
+
return self._limits_table
|
|
1946
|
+
|
|
1947
|
+
def credible_interval(self, ifo, param, ci=95, paramval=None):
|
|
1948
|
+
# get the given percentage (minimum) credible interval from samples for detector given by ifo and param
|
|
1949
|
+
# (for injections, where we have parameter values (paramval) get the corresponding smallest credible
|
|
1950
|
+
# region that contains the parameter value)
|
|
1951
|
+
samples = self._posteriors[ifo][param].samples.squeeze()
|
|
1952
|
+
samples.sort()
|
|
1953
|
+
lowbound, highbound, _ = self._ci_loop(samples, ci)
|
|
1954
|
+
|
|
1955
|
+
cival = None
|
|
1956
|
+
if paramval != None:
|
|
1957
|
+
cifound = False
|
|
1958
|
+
# loop over different credible intervals until finding the one that contains the injection
|
|
1959
|
+
for cit in range(1, 101):
|
|
1960
|
+
l, h, cr = self._ci_loop(samples, cit)
|
|
1961
|
+
if paramval >= l and paramval <= h:
|
|
1962
|
+
cifound = True
|
|
1963
|
+
cival = cit
|
|
1964
|
+
break
|
|
1965
|
+
if not cifound:
|
|
1966
|
+
cival = 100
|
|
1967
|
+
|
|
1968
|
+
return lowbound, highbound, cival
|
|
1969
|
+
|
|
1970
|
+
def _ci_loop(self, sortedsamples, ci):
|
|
1971
|
+
lowbound = sortedsamples[0]
|
|
1972
|
+
highbound = sortedsamples[-1]
|
|
1973
|
+
cregion = highbound - lowbound
|
|
1974
|
+
lsam = len(sortedsamples)
|
|
1975
|
+
cllen = int(lsam * float(ci) / 100.0)
|
|
1976
|
+
for j in range(lsam - cllen):
|
|
1977
|
+
if sortedsamples[j + cllen] - sortedsamples[j] < cregion:
|
|
1978
|
+
lowbound = sortedsamples[j]
|
|
1979
|
+
highbound = sortedsamples[j + cllen]
|
|
1980
|
+
cregion = highbound - lowbound
|
|
1981
|
+
|
|
1982
|
+
return lowbound, highbound, cregion
|
|
1983
|
+
|
|
1984
|
+
|
|
1985
|
+
class create_background(posteriors):
|
|
1986
|
+
"""
|
|
1987
|
+
Get information (evidence ratios and SNRs) from any the background analyses
|
|
1988
|
+
"""
|
|
1989
|
+
|
|
1990
|
+
def __init__(
|
|
1991
|
+
self,
|
|
1992
|
+
backgrounddirs,
|
|
1993
|
+
snrs,
|
|
1994
|
+
Bsn,
|
|
1995
|
+
outputdir,
|
|
1996
|
+
Bci=None,
|
|
1997
|
+
Bcin=None,
|
|
1998
|
+
showcontours=True,
|
|
1999
|
+
):
|
|
2000
|
+
# initialise with a dictionary (keyed to detectors) of directories containing the background analyses,
|
|
2001
|
+
# a dictionary of signal vs noise Bayes factors, a coherent vs incoherent Bayes factor and a coherent
|
|
2002
|
+
# vs incoherent or noise Bayes factor (all created from the posterior class)
|
|
2003
|
+
self._ifos = list(backgrounddirs.keys()) # detectors
|
|
2004
|
+
self._backgrounddirs = backgrounddirs
|
|
2005
|
+
self._dir_lists = (
|
|
2006
|
+
{}
|
|
2007
|
+
) # dictionary with a list of background results directories for each detector
|
|
2008
|
+
self._Bci_fore = Bci # the "foreground" Bayes factor for coherent vs incoherent
|
|
2009
|
+
self._Bcin_fore = (
|
|
2010
|
+
Bcin # the "foreground" Bayes factor for coherent vs incoherent or noise
|
|
2011
|
+
)
|
|
2012
|
+
|
|
2013
|
+
self._Bsn = (
|
|
2014
|
+
{}
|
|
2015
|
+
) # dictionary of "background" signal vs noise Bayes factor lists for each detector
|
|
2016
|
+
self._Bci = [] # list of "background" coherent vs incoherent Bayes factors
|
|
2017
|
+
self._Bcin = (
|
|
2018
|
+
[]
|
|
2019
|
+
) # list of "background" coherent vs incoherent or noise Bayes factors
|
|
2020
|
+
self._optimal_snrs = (
|
|
2021
|
+
{}
|
|
2022
|
+
) # dictionary of "background" SNR lists for each detector
|
|
2023
|
+
self._signal_evidence = {}
|
|
2024
|
+
self._noise_evidence = {}
|
|
2025
|
+
self._maxL = {}
|
|
2026
|
+
|
|
2027
|
+
# figure and contour limits
|
|
2028
|
+
self._figlimits = [(0.0, None), ()] # assumes SNR is first value
|
|
2029
|
+
self._contourlimits = [(0.0, None), ()]
|
|
2030
|
+
|
|
2031
|
+
# set some default arguments for create_joint_posterior_plot
|
|
2032
|
+
self._plot_kwargs = {
|
|
2033
|
+
"ratio": 2,
|
|
2034
|
+
"whichtruth": "all",
|
|
2035
|
+
"scatter_kwargs": {"alpha": 0.5},
|
|
2036
|
+
"figlimits": self._figlimits,
|
|
2037
|
+
"contourlimits": self._contourlimits,
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
self._Bsn_prob = (
|
|
2041
|
+
{}
|
|
2042
|
+
) # probability of the "foreground value" given a Gaussian KDE applied to the background
|
|
2043
|
+
self._Bci_prob = None
|
|
2044
|
+
self._Bcin_prob = None
|
|
2045
|
+
|
|
2046
|
+
self._injection_parameters = None # set to None
|
|
2047
|
+
|
|
2048
|
+
self._outputdir = outputdir # set output directory
|
|
2049
|
+
|
|
2050
|
+
dirlen = []
|
|
2051
|
+
for i, ifo in enumerate(self._ifos):
|
|
2052
|
+
if ifo not in Bsn or ifo not in snrs:
|
|
2053
|
+
print(
|
|
2054
|
+
"Error... Bsn/SNR dictionary is not consistent with the background directories dictionary.",
|
|
2055
|
+
file=sys.stderr,
|
|
2056
|
+
)
|
|
2057
|
+
sys.exit(1)
|
|
2058
|
+
|
|
2059
|
+
self._Bsn[ifo] = [] # create empty list
|
|
2060
|
+
self._optimal_snrs[ifo] = [] # create empty list
|
|
2061
|
+
self._signal_evidence[ifo] = []
|
|
2062
|
+
self._noise_evidence[ifo] = []
|
|
2063
|
+
self._maxL[ifo] = []
|
|
2064
|
+
|
|
2065
|
+
# get directory lists
|
|
2066
|
+
self._dir_lists[ifo] = [
|
|
2067
|
+
os.path.join(self._backgrounddirs[ifo], d)
|
|
2068
|
+
for d in os.listdir(self._backgrounddirs[ifo])
|
|
2069
|
+
if os.path.isdir(os.path.join(self._backgrounddirs[ifo], d))
|
|
2070
|
+
]
|
|
2071
|
+
dirlen.append(len(self._dir_lists[ifo]))
|
|
2072
|
+
if dirlen[i] == 0:
|
|
2073
|
+
print(
|
|
2074
|
+
"Error... no background results directories were present for '%s'."
|
|
2075
|
+
% ifo,
|
|
2076
|
+
file=sys.stderr,
|
|
2077
|
+
)
|
|
2078
|
+
sys.exit(1)
|
|
2079
|
+
|
|
2080
|
+
# check there are the same number of background runs for each ifo
|
|
2081
|
+
if i > 0:
|
|
2082
|
+
if dirlen[i] != dirlen[0]:
|
|
2083
|
+
print(
|
|
2084
|
+
"Error... number of background results directories not then same for different detectors."
|
|
2085
|
+
% ifo,
|
|
2086
|
+
file=sys.stderr,
|
|
2087
|
+
)
|
|
2088
|
+
sys.exit(1)
|
|
2089
|
+
|
|
2090
|
+
self._Bsn_fore = Bsn # the "foreground" Bayes factor for signal vs noise
|
|
2091
|
+
self._snrs_fore = snrs # the "foreground" optimal snrs
|
|
2092
|
+
|
|
2093
|
+
# get SNRs
|
|
2094
|
+
self._get_snrs()
|
|
2095
|
+
|
|
2096
|
+
# get Bayes factors
|
|
2097
|
+
self._get_bayes_factors()
|
|
2098
|
+
|
|
2099
|
+
# get probabilities the background distribution being greater than the foreground value
|
|
2100
|
+
self._get_bsn_prob()
|
|
2101
|
+
if len(self._ifos) > 2 and "Joint" in self._ifos:
|
|
2102
|
+
self._get_bci_prob()
|
|
2103
|
+
|
|
2104
|
+
@property
|
|
2105
|
+
def bci_prob(self):
|
|
2106
|
+
return self._Bci_prob
|
|
2107
|
+
|
|
2108
|
+
@property
|
|
2109
|
+
def bcin_prob(self):
|
|
2110
|
+
return self._Bcin_prob
|
|
2111
|
+
|
|
2112
|
+
def bsn_prob(self, ifo):
|
|
2113
|
+
return self._Bsn_prob[ifo]
|
|
2114
|
+
|
|
2115
|
+
def _get_snrs(self):
|
|
2116
|
+
# get the returned match filter SNRs
|
|
2117
|
+
for ifo in self._ifos: # loop over detectors
|
|
2118
|
+
# loop over background directories
|
|
2119
|
+
for pdir in self._dir_lists[ifo]:
|
|
2120
|
+
self._optimal_snrs[ifo].append(self.get_snr(pdir))
|
|
2121
|
+
|
|
2122
|
+
def _get_bayes_factors(self):
|
|
2123
|
+
# get the Bayes factors for the signal
|
|
2124
|
+
incoherent = np.zeros(
|
|
2125
|
+
len(self._dir_lists[self._ifos[0]])
|
|
2126
|
+
) # the incoherent evidence
|
|
2127
|
+
|
|
2128
|
+
for ifo in self._ifos:
|
|
2129
|
+
for i, pdir in enumerate(self._dir_lists[ifo]):
|
|
2130
|
+
pfiles = os.listdir(pdir)
|
|
2131
|
+
Bsn = None
|
|
2132
|
+
for pfile in pfiles: # get HDF5 file with extenstion '.hdf' or '.h5'
|
|
2133
|
+
if fnmatch.fnmatch(
|
|
2134
|
+
pfile, "posterior_samples*.hdf"
|
|
2135
|
+
) or fnmatch.fnmatch(pfile, "posterior_samples*.h5"):
|
|
2136
|
+
Bsn, sigev, noiseev, maxL = self.get_bayes_factor(
|
|
2137
|
+
os.path.join(pdir, pfile)
|
|
2138
|
+
)
|
|
2139
|
+
|
|
2140
|
+
self._Bsn[ifo].append(Bsn)
|
|
2141
|
+
self._signal_evidence[ifo].append(sigev)
|
|
2142
|
+
self._noise_evidence[ifo].append(noiseev)
|
|
2143
|
+
self._maxL[ifo].append(maxL)
|
|
2144
|
+
break
|
|
2145
|
+
if Bsn == None:
|
|
2146
|
+
print(
|
|
2147
|
+
"Error... no HDF5 file with 'posterior_samples' in the name was found in '%s'."
|
|
2148
|
+
% pdir,
|
|
2149
|
+
file=sys.stderr,
|
|
2150
|
+
)
|
|
2151
|
+
sys.exit(1)
|
|
2152
|
+
|
|
2153
|
+
if ifo != "Joint":
|
|
2154
|
+
incoherent[i] += self._signal_evidence[ifo][i]
|
|
2155
|
+
|
|
2156
|
+
# get the coherent vs incoherent noise evidence
|
|
2157
|
+
if len(self._ifos) > 2 and "Joint" in self._ifos:
|
|
2158
|
+
for i in range(len(self._dir_lists[self._ifos[0]])):
|
|
2159
|
+
self._Bci.append(self._signal_evidence["Joint"][i] - incoherent[i])
|
|
2160
|
+
self._Bcin.append(
|
|
2161
|
+
self._signal_evidence["Joint"][i]
|
|
2162
|
+
- np.logaddexp(incoherent[i], self._noise_evidence["Joint"][i])
|
|
2163
|
+
)
|
|
2164
|
+
|
|
2165
|
+
def _get_bsn_prob(self):
|
|
2166
|
+
# get the probability of the background distribution of signal vs noise Bayes factors
|
|
2167
|
+
# being greater than the foreground value for each detector by using a Gaussian KDE on the
|
|
2168
|
+
# 1D samples from the background
|
|
2169
|
+
for ifo in self._ifos:
|
|
2170
|
+
kernel = stats.gaussian_kde(self._Bsn[ifo])
|
|
2171
|
+
self._Bsn_prob[ifo] = kernel.integrate_box_1d(
|
|
2172
|
+
self._Bsn_fore[ifo], np.inf
|
|
2173
|
+
) # integrate between foreground value and infinity
|
|
2174
|
+
|
|
2175
|
+
def _get_bci_prob(self):
|
|
2176
|
+
kernel = stats.gaussian_kde(self._Bci)
|
|
2177
|
+
self._Bci_prob = kernel.integrate_box_1d(self._Bci_fore, np.inf)
|
|
2178
|
+
kernel = stats.gaussian_kde(self._Bcin)
|
|
2179
|
+
self._Bcin_prob = kernel.integrate_box_1d(self._Bcin_fore, np.inf)
|
|
2180
|
+
|
|
2181
|
+
def bsn_plot(self, credint=[0.5, 0.95]):
|
|
2182
|
+
# create 2D scatter plots of SNR vs Bsn (with KDE estimated probability contours - if present just for Joint)
|
|
2183
|
+
# and 1D histograms for each - use the create_joint_posterior_plot's function
|
|
2184
|
+
|
|
2185
|
+
self._posteriors = {}
|
|
2186
|
+
truths = {}
|
|
2187
|
+
|
|
2188
|
+
# create fake posterior objects (requires logL to be there) for each detector
|
|
2189
|
+
for ifo in self._ifos:
|
|
2190
|
+
self._posteriors[ifo] = Posterior((["tmp", "logL"], np.zeros((100, 2))))
|
|
2191
|
+
|
|
2192
|
+
# add the SNR and Bsn values
|
|
2193
|
+
snrs = PosteriorOneDPDF("snr", np.array([self._optimal_snrs[ifo]]).T)
|
|
2194
|
+
self._posteriors[ifo].append(snrs)
|
|
2195
|
+
|
|
2196
|
+
bsn = PosteriorOneDPDF(
|
|
2197
|
+
"bsn", np.array([self._Bsn[ifo]]).T / np.log(10.0)
|
|
2198
|
+
) # convert into base 10 log
|
|
2199
|
+
self._posteriors[ifo].append(bsn)
|
|
2200
|
+
|
|
2201
|
+
# remove temporary varaibles
|
|
2202
|
+
self._posteriors[ifo].pop("tmp")
|
|
2203
|
+
self._posteriors[ifo].pop("logl")
|
|
2204
|
+
|
|
2205
|
+
self._parameters = ["snr", "bsn"] # set parameters
|
|
2206
|
+
truths[ifo] = [self._snrs_fore[ifo], self._Bsn_fore[ifo] / np.log(10.0)]
|
|
2207
|
+
|
|
2208
|
+
return self.create_joint_posterior_plot(
|
|
2209
|
+
["snr", "bsn"],
|
|
2210
|
+
bins=int(np.log2(len(snrs.samples))),
|
|
2211
|
+
truths=truths,
|
|
2212
|
+
credintervals=credint,
|
|
2213
|
+
filename="bsn",
|
|
2214
|
+
**self._plot_kwargs,
|
|
2215
|
+
)
|
|
2216
|
+
|
|
2217
|
+
def bci_plot(self, credint=[0.5, 0.95], which="bci"):
|
|
2218
|
+
self._posteriors = {}
|
|
2219
|
+
if which == "bcin":
|
|
2220
|
+
truths = [self._snrs_fore["Joint"], self._Bcin_fore / np.log(10.0)]
|
|
2221
|
+
self._parameters = ["snr", "bcin"]
|
|
2222
|
+
else: # default to bci
|
|
2223
|
+
truths = [self._snrs_fore["Joint"], self._Bci_fore / np.log(10.0)]
|
|
2224
|
+
self._parameters = ["snr", "bci"]
|
|
2225
|
+
|
|
2226
|
+
if (
|
|
2227
|
+
which != "bci"
|
|
2228
|
+
): # force which to be 'bci' (as there are only the two options)
|
|
2229
|
+
which = "bci"
|
|
2230
|
+
|
|
2231
|
+
self._posteriors["Joint"] = Posterior((["tmp", "logL"], np.zeros((100, 2))))
|
|
2232
|
+
|
|
2233
|
+
# add the SNR and Bci values
|
|
2234
|
+
snrs = PosteriorOneDPDF("snr", np.array([self._optimal_snrs["Joint"]]).T)
|
|
2235
|
+
self._posteriors["Joint"].append(snrs)
|
|
2236
|
+
|
|
2237
|
+
if which == "bcin":
|
|
2238
|
+
bci = PosteriorOneDPDF("bcin", np.array([self._Bcin]).T / np.log(10.0))
|
|
2239
|
+
else:
|
|
2240
|
+
bci = PosteriorOneDPDF("bci", np.array([self._Bci]).T / np.log(10.0))
|
|
2241
|
+
self._posteriors["Joint"].append(bci)
|
|
2242
|
+
|
|
2243
|
+
curifos = self._ifos # save current detectors
|
|
2244
|
+
self._ifos = ["Joint"] # set for just the joint detector
|
|
2245
|
+
bciplot = self.create_joint_posterior_plot(
|
|
2246
|
+
self._parameters,
|
|
2247
|
+
bins=int(np.log2(len(snrs.samples))),
|
|
2248
|
+
truths=truths,
|
|
2249
|
+
credintervals=credint,
|
|
2250
|
+
filename=which,
|
|
2251
|
+
**self._plot_kwargs,
|
|
2252
|
+
)
|
|
2253
|
+
self._ifos = curifos # reset detectors (in case they are needed later)
|
|
2254
|
+
|
|
2255
|
+
return bciplot
|
|
2256
|
+
|
|
2257
|
+
def create_background_table(self):
|
|
2258
|
+
# create table with background plots in them
|
|
2259
|
+
background_plots_table = htmltag(
|
|
2260
|
+
"h2", "Evidence distributions", newline=True
|
|
2261
|
+
).text
|
|
2262
|
+
|
|
2263
|
+
table = htmltable()
|
|
2264
|
+
table.addrow()
|
|
2265
|
+
cols = 1 # number of columns
|
|
2266
|
+
|
|
2267
|
+
# add Bsn plot
|
|
2268
|
+
bsnplot = self.bsn_plot()
|
|
2269
|
+
table.adddata(
|
|
2270
|
+
atag(
|
|
2271
|
+
os.path.basename(bsnplot[0]),
|
|
2272
|
+
'<img class="backgroundplot" src="{}"/>'.format(
|
|
2273
|
+
os.path.basename(bsnplot[0])
|
|
2274
|
+
),
|
|
2275
|
+
).text
|
|
2276
|
+
)
|
|
2277
|
+
|
|
2278
|
+
if self._Bci_fore != None:
|
|
2279
|
+
bciplot = self.bci_plot(which="bci")
|
|
2280
|
+
table.adddata(
|
|
2281
|
+
atag(
|
|
2282
|
+
os.path.basename(bciplot[0]),
|
|
2283
|
+
'<img class="backgroundplot" src="{}"/>'.format(
|
|
2284
|
+
os.path.basename(bciplot[0])
|
|
2285
|
+
),
|
|
2286
|
+
).text
|
|
2287
|
+
)
|
|
2288
|
+
cols += 1
|
|
2289
|
+
|
|
2290
|
+
if self._Bcin_fore != None:
|
|
2291
|
+
bcinplot = self.bci_plot(which="bcin")
|
|
2292
|
+
table.adddata(
|
|
2293
|
+
atag(
|
|
2294
|
+
os.path.basename(bcinplot[0]),
|
|
2295
|
+
'<img class="backgroundplot" src="{}"/>'.format(
|
|
2296
|
+
os.path.basename(bcinplot[0])
|
|
2297
|
+
),
|
|
2298
|
+
).text
|
|
2299
|
+
)
|
|
2300
|
+
cols += 1
|
|
2301
|
+
|
|
2302
|
+
# add probabilities for the background distribution being greater than the foreground value
|
|
2303
|
+
innertable = htmltable(tableclass="evidencetable")
|
|
2304
|
+
innertable.addrow()
|
|
2305
|
+
innertable.adddata(" ")
|
|
2306
|
+
innertable.adddata(
|
|
2307
|
+
"Probability of background distribution being greater than foreground",
|
|
2308
|
+
colspan=(len(self._ifos) + cols - 1),
|
|
2309
|
+
header=True,
|
|
2310
|
+
)
|
|
2311
|
+
innertable.addrow()
|
|
2312
|
+
innertable.adddata("Detector", header=True)
|
|
2313
|
+
for ifo in self._ifos:
|
|
2314
|
+
innertable.adddata(ifo, dataclass=ifo)
|
|
2315
|
+
if self._Bci_fore != None:
|
|
2316
|
+
innertable.adddata("B<sub>CvI</sub>")
|
|
2317
|
+
if self._Bcin_fore != None:
|
|
2318
|
+
innertable.adddata("B<sub>CvIN</sub>")
|
|
2319
|
+
|
|
2320
|
+
innertable.addrow()
|
|
2321
|
+
innertable.adddata(" ")
|
|
2322
|
+
for ifo in self._ifos:
|
|
2323
|
+
innertable.adddata(exp_str(self.bsn_prob(ifo)), dataclass=ifo)
|
|
2324
|
+
|
|
2325
|
+
if self._Bci_fore != None:
|
|
2326
|
+
innertable.adddata(exp_str(float(self.bci_prob), 1))
|
|
2327
|
+
|
|
2328
|
+
if self._Bcin_fore != None:
|
|
2329
|
+
innertable.adddata(exp_str(float(self.bcin_prob), 1))
|
|
2330
|
+
|
|
2331
|
+
table.addrow()
|
|
2332
|
+
table.adddata(innertable.tabletext, colspan=cols)
|
|
2333
|
+
|
|
2334
|
+
background_plots_table += table.tabletext
|
|
2335
|
+
|
|
2336
|
+
return background_plots_table
|
|
2337
|
+
|
|
2338
|
+
|
|
2339
|
+
if __name__ == "__main__":
|
|
2340
|
+
description = """This script will create a results page for a single pulsar from the known pulsar analysis pipeline. A configuration (.ini) file is required."""
|
|
2341
|
+
epilog = """An example configuration file could contain the following:
|
|
2342
|
+
|
|
2343
|
+
# a section for general analysis information
|
|
2344
|
+
[general]
|
|
2345
|
+
parfile = 'path_to_par_file' # the path to the pulsar parameter file
|
|
2346
|
+
detectors = ['H1', 'L1'] # a list of the detectors to use
|
|
2347
|
+
with_joint = True # a boolean stating whether to also add the joint multi-detector analysis
|
|
2348
|
+
joint_only = False # a boolean stating whether to only output the joint multi-detector analysis
|
|
2349
|
+
with_background = False # a boolean stating whether to include background analyses
|
|
2350
|
+
injection = False # a boolean stating whether this pulsar is a software/hardware injection
|
|
2351
|
+
upper_limit = 95 # the percentage credible upper limit value
|
|
2352
|
+
credible_interval = [95] # a list of the percentage credible intervals for output statistics
|
|
2353
|
+
use_gw_phase = False # a boolean stating whether to assume the initial phase parameter is the rotational, or gravitational wave (l=m=2), phase (e.g. if looking a hardware injections)
|
|
2354
|
+
harmonics = [2] # a list of the frequency harmonics used in this analysis
|
|
2355
|
+
model_type = waveform # either 'waveform' (default) or 'source' specify the parameterisation
|
|
2356
|
+
biaxial = False # set whether the signal searched for was from a biaxial source
|
|
2357
|
+
priorfile = 'path_to_prior' # the path to the prior file used in the analysis (if given priors will be plotted)
|
|
2358
|
+
|
|
2359
|
+
# a section for parameter estimation files
|
|
2360
|
+
[parameter_estimation]
|
|
2361
|
+
posteriors = {'H1': 'path_to_H1_posteriors', 'L1': 'path_to_L1_posteriors', 'Joint': 'path_to_Joint_posteriors'} # a dictionary (keyed on detectors) pointing to the locations of posterior sample files
|
|
2362
|
+
background = {'H1': 'path_to_H1_background_dir', 'L1': 'path_to_L1_background_dir', 'Joint': 'path_to_Joint_backgroud_dir'} # a dictionary (keyed on detectors) pointing to directories containing the background posterior files
|
|
2363
|
+
|
|
2364
|
+
# a section for pre-processed data information
|
|
2365
|
+
[data]
|
|
2366
|
+
files = {'H1': 'path_to_H1_data', 'L1': 'path_to_L1_data'} # a dictionary (keyed on detectors) pointing to the locations (or lists of locations for multiple harmonics) of pre-processed data files
|
|
2367
|
+
|
|
2368
|
+
# a section for the output location for this pulsar
|
|
2369
|
+
[output]
|
|
2370
|
+
path = 'path_to_output_base_directory' # the path to the base directory in which the results page will be created
|
|
2371
|
+
indexpage = 'path_to_index_page' # an optional path (relative to the base directory) to the index page containing results from multiple pulsars
|
|
2372
|
+
|
|
2373
|
+
# a section for plotting options
|
|
2374
|
+
[plotting]
|
|
2375
|
+
all_posteriors = False # a boolean stating whether to show joint posterior plots of all parameters (default: False)
|
|
2376
|
+
subtract_truths = False # a boolean stating whether to subtract the true/heterodyned value from any phase parameters to centre the plot at zero for that value
|
|
2377
|
+
show_contours = False # a boolean stating whether to show probabilty contours on 2D posterior plots (default: False)
|
|
2378
|
+
eps_output = False # a boolean stating whether to also output eps versions of figures (png figures will automatically be produced)
|
|
2379
|
+
pdf_output = False # a boolean stating whether to also output pdf versions of figures (png figures will automatically be produced)
|
|
2380
|
+
|
|
2381
|
+
"""
|
|
2382
|
+
|
|
2383
|
+
parser = argparse.ArgumentParser(
|
|
2384
|
+
description=description,
|
|
2385
|
+
epilog=epilog,
|
|
2386
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
2387
|
+
)
|
|
2388
|
+
parser.add_argument("inifile", help="The configuration (.ini) file")
|
|
2389
|
+
|
|
2390
|
+
# parse input options
|
|
2391
|
+
opts = parser.parse_args()
|
|
2392
|
+
|
|
2393
|
+
inifile = opts.inifile
|
|
2394
|
+
|
|
2395
|
+
# open and parse config file
|
|
2396
|
+
cp = ConfigParser()
|
|
2397
|
+
try:
|
|
2398
|
+
cp.read(inifile)
|
|
2399
|
+
except:
|
|
2400
|
+
print(
|
|
2401
|
+
"Error... cannot parse configuration file '%s'" % inifile, file=sys.stderr
|
|
2402
|
+
)
|
|
2403
|
+
sys.exit(1)
|
|
2404
|
+
|
|
2405
|
+
# get the output directory
|
|
2406
|
+
try:
|
|
2407
|
+
outdir = cp.get("output", "path")
|
|
2408
|
+
except:
|
|
2409
|
+
print(
|
|
2410
|
+
"Error... no output directory 'path' specified in [output] section.",
|
|
2411
|
+
file=sys.stderr,
|
|
2412
|
+
)
|
|
2413
|
+
sys.exit(1)
|
|
2414
|
+
|
|
2415
|
+
# create directory if required
|
|
2416
|
+
if not os.access(outdir, os.W_OK) and not os.path.isdir(
|
|
2417
|
+
outdir
|
|
2418
|
+
): # check if directory already exists
|
|
2419
|
+
try:
|
|
2420
|
+
os.makedirs(outdir)
|
|
2421
|
+
except:
|
|
2422
|
+
print(
|
|
2423
|
+
"Error... cannot make output directory '%s'." % outdir, file=sys.stderr
|
|
2424
|
+
)
|
|
2425
|
+
sys.exit(1)
|
|
2426
|
+
|
|
2427
|
+
# get the index page location
|
|
2428
|
+
try:
|
|
2429
|
+
indexpage = cp.get("output", "indexpage")
|
|
2430
|
+
except:
|
|
2431
|
+
indexpage = None
|
|
2432
|
+
|
|
2433
|
+
# get the pulsar parameter file
|
|
2434
|
+
parfile = None
|
|
2435
|
+
try:
|
|
2436
|
+
parfile = cp.get("general", "parfile")
|
|
2437
|
+
except:
|
|
2438
|
+
print(
|
|
2439
|
+
"Error... Pulsar parameter 'parfile' must specified in the [general] section.",
|
|
2440
|
+
file=sys.stderr,
|
|
2441
|
+
)
|
|
2442
|
+
sys.exit(1)
|
|
2443
|
+
|
|
2444
|
+
# read in data from par file
|
|
2445
|
+
try:
|
|
2446
|
+
par = psr_par(parfile)
|
|
2447
|
+
except:
|
|
2448
|
+
print(
|
|
2449
|
+
"Error... Pulsar parameter (.par) file '%s' could not be opened!" % parfile,
|
|
2450
|
+
file=sys.stderr,
|
|
2451
|
+
)
|
|
2452
|
+
sys.exit(1)
|
|
2453
|
+
|
|
2454
|
+
# get pulsar PSRJ name
|
|
2455
|
+
pname = par["PSRJ"]
|
|
2456
|
+
if not pname:
|
|
2457
|
+
print(
|
|
2458
|
+
"Error... no PSRJ name set in pulsar parameter file '%s'." % parfile,
|
|
2459
|
+
file=sys.stderr,
|
|
2460
|
+
)
|
|
2461
|
+
|
|
2462
|
+
# check/get required parameters
|
|
2463
|
+
f0 = par["F0"] # pulsar rotation frequency (Hz)
|
|
2464
|
+
if not f0:
|
|
2465
|
+
print(
|
|
2466
|
+
"Error... no 'F0' value in the parameter file '%s'." % parfile,
|
|
2467
|
+
file=sys.stderr,
|
|
2468
|
+
)
|
|
2469
|
+
sys.exit(1)
|
|
2470
|
+
|
|
2471
|
+
f1 = par["F1"] # pulsar first time derivative of rotational frequency (Hz/s)
|
|
2472
|
+
if not f1:
|
|
2473
|
+
f1 = 0.0 # set to zero if not given
|
|
2474
|
+
|
|
2475
|
+
# get the upper limit credible interval
|
|
2476
|
+
try:
|
|
2477
|
+
upperlim = ast.literval_eval(cp.get("general", "upper_limit"))
|
|
2478
|
+
except: # default to 95%
|
|
2479
|
+
upperlim = 95
|
|
2480
|
+
|
|
2481
|
+
# get credible intervals for output statistics
|
|
2482
|
+
try:
|
|
2483
|
+
credints = ast.literval_eval(cp.get("general", "credible_interval"))
|
|
2484
|
+
except: # default to 95%
|
|
2485
|
+
credints = [95]
|
|
2486
|
+
|
|
2487
|
+
# check whether looking at an injection or not
|
|
2488
|
+
try:
|
|
2489
|
+
injection = cp.getboolean("general", "injection")
|
|
2490
|
+
except:
|
|
2491
|
+
injection = (
|
|
2492
|
+
False # if nothing is given then assume that this is not an injection
|
|
2493
|
+
)
|
|
2494
|
+
|
|
2495
|
+
# check whether to use the rotational, or gravitational wave phase (e.g. for hardware injections), in output plots
|
|
2496
|
+
try:
|
|
2497
|
+
usegwphase = cp.getboolean("general", "use_gw_phase")
|
|
2498
|
+
except:
|
|
2499
|
+
usegwphase = False
|
|
2500
|
+
|
|
2501
|
+
# check whther a prior file is given
|
|
2502
|
+
try:
|
|
2503
|
+
priorfile = cp.get("general", "priorfile")
|
|
2504
|
+
except:
|
|
2505
|
+
priorfile = None
|
|
2506
|
+
|
|
2507
|
+
# attempt to get pulsar distance, proper motion corrected age and any association (e.g. GC from the ATNF catalogue)
|
|
2508
|
+
dist = p1_I = assoc = sdlim = f1sd = None
|
|
2509
|
+
atnfurl = None
|
|
2510
|
+
if not injection:
|
|
2511
|
+
# set ATNF URL where pulsar can be found
|
|
2512
|
+
atnfurl = (
|
|
2513
|
+
"http://www.atnf.csiro.au/people/pulsar/psrcat/proc_form.php?version="
|
|
2514
|
+
+ ATNF_VERSION
|
|
2515
|
+
)
|
|
2516
|
+
atnfurl += "&startUserDefined=true&pulsar_names=" + re.sub(r"\+", "%2B", pname)
|
|
2517
|
+
atnfurl += "&ephemeris=long&submit_ephemeris=Get+Ephemeris&state=query"
|
|
2518
|
+
|
|
2519
|
+
# try getting information already parsed from ATNF catalogue by lalpulsar_knope pipeline setup
|
|
2520
|
+
jsonfile = os.path.join(outdir, pname + ".json")
|
|
2521
|
+
tryatnf = True
|
|
2522
|
+
if os.path.isfile(jsonfile):
|
|
2523
|
+
try:
|
|
2524
|
+
fp = open(jsonfile, "r")
|
|
2525
|
+
info = json.load(fp)
|
|
2526
|
+
fp.close()
|
|
2527
|
+
|
|
2528
|
+
# extract distance, intrinsic period derivative, pulsar association and required URL
|
|
2529
|
+
dist = info["Pulsar data"]["DIST"]
|
|
2530
|
+
p1_I = info["Pulsar data"]["P1_I"]
|
|
2531
|
+
assoc = info["Pulsar data"]["ASSOC"]
|
|
2532
|
+
tryatnf = False
|
|
2533
|
+
except:
|
|
2534
|
+
print(
|
|
2535
|
+
"Warning... could not read in JSON file '%s'." % jsonfile,
|
|
2536
|
+
file=sys.stderr,
|
|
2537
|
+
)
|
|
2538
|
+
|
|
2539
|
+
if tryatnf: # try getting ATNF info now
|
|
2540
|
+
pinfo = get_atnf_info(pname)
|
|
2541
|
+
if pinfo is not None:
|
|
2542
|
+
dist, p1_I, assoc, atnfurlref = pinfo # unpack values
|
|
2543
|
+
|
|
2544
|
+
# if distance is in the par file use that instead
|
|
2545
|
+
if par["DIST"]:
|
|
2546
|
+
dist = par["DIST"] / KPC # convert back into kpc
|
|
2547
|
+
|
|
2548
|
+
# set the corrected spin-down value (based on intrinsic period derivative or using conservative age (10^9) value from GC pulsars)
|
|
2549
|
+
f1sd = set_spin_down(p1_I, assoc, f0, f1)
|
|
2550
|
+
|
|
2551
|
+
# get spin-down limit
|
|
2552
|
+
if f1sd is not None and dist is not None:
|
|
2553
|
+
sdlim = spin_down_limit(f0, f1sd, dist)
|
|
2554
|
+
|
|
2555
|
+
# check whether to only include results from a joint (multi-detector) analysis
|
|
2556
|
+
try:
|
|
2557
|
+
jointonly = cp.getboolean("general", "joint_only")
|
|
2558
|
+
except:
|
|
2559
|
+
jointonly = False
|
|
2560
|
+
|
|
2561
|
+
# check which frequency harmonics were used in this analysis
|
|
2562
|
+
try:
|
|
2563
|
+
harmonics = ast.literal_eval(cp.get("general", "harmonics"))
|
|
2564
|
+
except:
|
|
2565
|
+
harmonics = [2] # default to twice the rotation frequency
|
|
2566
|
+
|
|
2567
|
+
# check whether the waveform or source model is being used
|
|
2568
|
+
try:
|
|
2569
|
+
modeltype = cp.get("general", "model_type")
|
|
2570
|
+
except:
|
|
2571
|
+
modeltype = "waveform"
|
|
2572
|
+
|
|
2573
|
+
if modeltype not in ["waveform", "source"]:
|
|
2574
|
+
print(
|
|
2575
|
+
"Error... unknown 'model type' '%s' specified." % modeltype, file=sys.stderr
|
|
2576
|
+
)
|
|
2577
|
+
sys.exit(1)
|
|
2578
|
+
|
|
2579
|
+
try:
|
|
2580
|
+
biaxial = cp.getboolean("general", "biaxial")
|
|
2581
|
+
except:
|
|
2582
|
+
biaxial = False
|
|
2583
|
+
|
|
2584
|
+
# check whether a background analysis has also been performed
|
|
2585
|
+
try:
|
|
2586
|
+
with_background = cp.getboolean("general", "with_background")
|
|
2587
|
+
except:
|
|
2588
|
+
with_background = False
|
|
2589
|
+
|
|
2590
|
+
if with_background:
|
|
2591
|
+
try:
|
|
2592
|
+
backgrounddir = ast.literal_eval(
|
|
2593
|
+
cp.get("parameter_estimation", "background")
|
|
2594
|
+
)
|
|
2595
|
+
except:
|
|
2596
|
+
with_background = False
|
|
2597
|
+
|
|
2598
|
+
# check whether to plot all joint posteriors
|
|
2599
|
+
try:
|
|
2600
|
+
allposteriors = cp.getboolean("plotting", "all_posteriors")
|
|
2601
|
+
except:
|
|
2602
|
+
allposteriors = False # default to False
|
|
2603
|
+
|
|
2604
|
+
# check whether to subtract true/heterodyned values from distributions
|
|
2605
|
+
try:
|
|
2606
|
+
subtracttruths = cp.getboolean("plotting", "subtract_truths")
|
|
2607
|
+
except:
|
|
2608
|
+
subtracttruths = False
|
|
2609
|
+
|
|
2610
|
+
# check whether to show probability contours on 2D posterior plots
|
|
2611
|
+
try:
|
|
2612
|
+
showcontours = cp.getboolean("plotting", "show_contours")
|
|
2613
|
+
except:
|
|
2614
|
+
showcontours = False
|
|
2615
|
+
|
|
2616
|
+
figformat = ["png"] # default to outputting png versions of figures
|
|
2617
|
+
# check whether to (also) output figures as eps
|
|
2618
|
+
try:
|
|
2619
|
+
witheps = cp.getboolean("plotting", "eps_output")
|
|
2620
|
+
except:
|
|
2621
|
+
witheps = False
|
|
2622
|
+
|
|
2623
|
+
if witheps:
|
|
2624
|
+
figformat.append("eps")
|
|
2625
|
+
|
|
2626
|
+
# check whether to (also) output figures as pdf
|
|
2627
|
+
try:
|
|
2628
|
+
withpdf = cp.getboolean("plotting", "pdf_output")
|
|
2629
|
+
except:
|
|
2630
|
+
withpdf = False
|
|
2631
|
+
|
|
2632
|
+
if withpdf:
|
|
2633
|
+
figformat.append("pdf")
|
|
2634
|
+
|
|
2635
|
+
# get the detectors to use
|
|
2636
|
+
ifos = [] # list of detectors to use
|
|
2637
|
+
withjoint = False
|
|
2638
|
+
preprocdat = None
|
|
2639
|
+
datatable = None
|
|
2640
|
+
if not jointonly:
|
|
2641
|
+
try:
|
|
2642
|
+
ifos = ast.literal_eval(cp.get("general", "detectors"))
|
|
2643
|
+
except:
|
|
2644
|
+
print(
|
|
2645
|
+
"Error... could not parse list of 'detectors' in the [general] section.",
|
|
2646
|
+
file=sys.stderr,
|
|
2647
|
+
)
|
|
2648
|
+
sys.exit(1)
|
|
2649
|
+
|
|
2650
|
+
if not isinstance(ifos, list):
|
|
2651
|
+
print(
|
|
2652
|
+
"Error... the 'detectors' value in the [general] section must be a list.",
|
|
2653
|
+
file=sys.stderr,
|
|
2654
|
+
)
|
|
2655
|
+
sys.exit(1)
|
|
2656
|
+
|
|
2657
|
+
if len(ifos) < 1:
|
|
2658
|
+
print(
|
|
2659
|
+
"Error... the 'detectors' value in the [general] section must contain at least one detector name.",
|
|
2660
|
+
file=sys.stderr,
|
|
2661
|
+
)
|
|
2662
|
+
sys.exit(1)
|
|
2663
|
+
|
|
2664
|
+
# check whether to include the joint (multi-detector) analysis
|
|
2665
|
+
if len(ifos) > 1: # only required if there's been more than one detector
|
|
2666
|
+
try:
|
|
2667
|
+
withjoint = cp.getboolean("general", "with_joint")
|
|
2668
|
+
except:
|
|
2669
|
+
withjoint = True # default to including the joint (multi-detector) analysis results
|
|
2670
|
+
|
|
2671
|
+
# get paths to pre-processed data files
|
|
2672
|
+
try:
|
|
2673
|
+
preprocdat = ast.literal_eval(cp.get("data", "files"))
|
|
2674
|
+
except:
|
|
2675
|
+
print(
|
|
2676
|
+
"Error... could not parse dictionary of 'files' in the [data] section.",
|
|
2677
|
+
file=sys.stderr,
|
|
2678
|
+
)
|
|
2679
|
+
sys.exit(1)
|
|
2680
|
+
|
|
2681
|
+
if not isinstance(preprocdat, dict):
|
|
2682
|
+
print(
|
|
2683
|
+
"Error... the 'files' value in the [data] section must be a dictionary.",
|
|
2684
|
+
file=sys.stderr,
|
|
2685
|
+
)
|
|
2686
|
+
sys.exit(1)
|
|
2687
|
+
|
|
2688
|
+
# check there is a value for each detector
|
|
2689
|
+
for ifo in ifos:
|
|
2690
|
+
if ifo not in preprocdat: # check if detector is in dictionary
|
|
2691
|
+
print(
|
|
2692
|
+
"Error... no pre-processed data file is given for '%s'." % ifo,
|
|
2693
|
+
file=sys.stderr,
|
|
2694
|
+
)
|
|
2695
|
+
sys.exit(1)
|
|
2696
|
+
|
|
2697
|
+
# make table with all stats and plots
|
|
2698
|
+
datatable = create_data_table(
|
|
2699
|
+
preprocdat, outdir, figformats=figformat, harmonics=harmonics
|
|
2700
|
+
)
|
|
2701
|
+
|
|
2702
|
+
# add 'Joint' on to the list of detectors if required
|
|
2703
|
+
if withjoint or jointonly:
|
|
2704
|
+
ifos.append("Joint")
|
|
2705
|
+
|
|
2706
|
+
# get the posterior sample files
|
|
2707
|
+
try:
|
|
2708
|
+
postfiles = ast.literal_eval(cp.get("parameter_estimation", "posteriors"))
|
|
2709
|
+
except:
|
|
2710
|
+
print(
|
|
2711
|
+
"Error... could not parse dictionary of 'posteriors' in the [parameter_estimation] section.",
|
|
2712
|
+
file=sys.stderr,
|
|
2713
|
+
)
|
|
2714
|
+
sys.exit(1)
|
|
2715
|
+
|
|
2716
|
+
if not isinstance(postfiles, dict):
|
|
2717
|
+
print(
|
|
2718
|
+
"Error... the 'posteriors' value in the [parameter_estimation] section must be a dictionary.",
|
|
2719
|
+
file=sys.stderr,
|
|
2720
|
+
)
|
|
2721
|
+
sys.exit(1)
|
|
2722
|
+
|
|
2723
|
+
for ifo in ifos:
|
|
2724
|
+
if ifo not in postfiles: # check if detector is in dictionary
|
|
2725
|
+
print(
|
|
2726
|
+
"Error... no posterior file is given for '%s'." % ifo, file=sys.stderr
|
|
2727
|
+
)
|
|
2728
|
+
sys.exit(1)
|
|
2729
|
+
else: # check file exists
|
|
2730
|
+
if not os.path.isfile(postfiles[ifo]):
|
|
2731
|
+
print(
|
|
2732
|
+
"Error... posterior file '%s' for '%s' does not exist."
|
|
2733
|
+
% (postfiles[ifo], ifo),
|
|
2734
|
+
file=sys.stderr,
|
|
2735
|
+
)
|
|
2736
|
+
sys.exit(1)
|
|
2737
|
+
|
|
2738
|
+
# create list of links to the various parts of the page
|
|
2739
|
+
linktable = htmltag("div", tagstyle="text-align: left; float: left")
|
|
2740
|
+
linkstable = htmltable()
|
|
2741
|
+
linkstable.addrow()
|
|
2742
|
+
|
|
2743
|
+
# dictionary for output html page
|
|
2744
|
+
htmlinput = {}
|
|
2745
|
+
|
|
2746
|
+
htmlinput["psrname"] = pname
|
|
2747
|
+
htmlinput["title"] = pname
|
|
2748
|
+
if injection:
|
|
2749
|
+
titlename = "INJ " + pname
|
|
2750
|
+
else:
|
|
2751
|
+
titlename = "PSR " + pname
|
|
2752
|
+
if atnfurl != None:
|
|
2753
|
+
htmlinput["h1title"] = atag(atnfurl, linktext=titlename).text
|
|
2754
|
+
else:
|
|
2755
|
+
htmlinput["h1title"] = titlename
|
|
2756
|
+
|
|
2757
|
+
# create table of pulsar info from par file
|
|
2758
|
+
psrtable = create_psr_table(par)
|
|
2759
|
+
htmlinput["pulsartable"] = psrtable
|
|
2760
|
+
|
|
2761
|
+
# get posterior class (containing samples, sample plots and posterior plots)
|
|
2762
|
+
postinfo = posteriors(
|
|
2763
|
+
postfiles,
|
|
2764
|
+
outdir,
|
|
2765
|
+
ifos=ifos,
|
|
2766
|
+
harmonics=harmonics,
|
|
2767
|
+
modeltype=modeltype,
|
|
2768
|
+
biaxial=biaxial,
|
|
2769
|
+
parfile=parfile,
|
|
2770
|
+
usegwphase=usegwphase,
|
|
2771
|
+
subtracttruths=subtracttruths,
|
|
2772
|
+
priorfile=priorfile,
|
|
2773
|
+
showcontours=showcontours,
|
|
2774
|
+
)
|
|
2775
|
+
|
|
2776
|
+
# create table of upper limits, SNR and evidence ratios
|
|
2777
|
+
htmlinput["limitstable"] = postinfo.create_limits_table(
|
|
2778
|
+
f0, sdlim=sdlim, dist=dist, ul=upperlim
|
|
2779
|
+
)
|
|
2780
|
+
|
|
2781
|
+
htmlinput["selectedposteriors"] = postinfo.create_joint_plots_table(
|
|
2782
|
+
title="Selected parameters"
|
|
2783
|
+
)
|
|
2784
|
+
|
|
2785
|
+
if allposteriors:
|
|
2786
|
+
htmlinput["jointposteriors"] = postinfo.create_joint_plots_table(allparams=True)
|
|
2787
|
+
linkstable.adddata(
|
|
2788
|
+
"Posteriors ("
|
|
2789
|
+
+ atag("#selectedposteriors", linktext="Selected").text
|
|
2790
|
+
+ ", "
|
|
2791
|
+
+ atag("#jointposteriors", linktext="All").text
|
|
2792
|
+
+ ")",
|
|
2793
|
+
dataclass="rightborder",
|
|
2794
|
+
)
|
|
2795
|
+
else:
|
|
2796
|
+
htmlinput["jointposteriors"] = ""
|
|
2797
|
+
linkstable.adddata(
|
|
2798
|
+
atag("#selectedposteriors", linktext="Posteriors").text,
|
|
2799
|
+
dataclass="rightborder",
|
|
2800
|
+
)
|
|
2801
|
+
|
|
2802
|
+
if with_background:
|
|
2803
|
+
bginfo = create_background(
|
|
2804
|
+
backgrounddir,
|
|
2805
|
+
postinfo.snrs,
|
|
2806
|
+
postinfo.bsn,
|
|
2807
|
+
outdir,
|
|
2808
|
+
Bci=postinfo.bci,
|
|
2809
|
+
Bcin=postinfo.bcin,
|
|
2810
|
+
)
|
|
2811
|
+
|
|
2812
|
+
# add background evidence plots
|
|
2813
|
+
htmlinput["evidenceplots"] = bginfo.create_background_table()
|
|
2814
|
+
linkstable.adddata(
|
|
2815
|
+
atag("#evidenceplots", linktext="Backgrounds").text, dataclass="rightborder"
|
|
2816
|
+
)
|
|
2817
|
+
else:
|
|
2818
|
+
htmlinput["evidenceplots"] = ""
|
|
2819
|
+
|
|
2820
|
+
# add data plots
|
|
2821
|
+
if datatable is not None:
|
|
2822
|
+
htmlinput["dataplots"] = str(datatable)
|
|
2823
|
+
linkstable.adddata(
|
|
2824
|
+
atag("#dataplots", linktext="Data Plots").text, dataclass="rightborder"
|
|
2825
|
+
)
|
|
2826
|
+
|
|
2827
|
+
# add posterior samples plots
|
|
2828
|
+
htmlinput["posteriorsamples"] = postinfo.create_sample_plot_table(
|
|
2829
|
+
figformats=figformat
|
|
2830
|
+
)
|
|
2831
|
+
linkstable.adddata(
|
|
2832
|
+
atag("#posteriorsamples", linktext="Samples").text, dataclass="rightborder"
|
|
2833
|
+
)
|
|
2834
|
+
|
|
2835
|
+
# add statistics
|
|
2836
|
+
htmlinput["posteriorstats"] = postinfo.create_stats_table(credints=credints)
|
|
2837
|
+
linkstable.adddata(atag("#posteriorstats", linktext="Statistics").text)
|
|
2838
|
+
|
|
2839
|
+
linktable.set_tagtext(linkstable.tabletext)
|
|
2840
|
+
|
|
2841
|
+
# set index page link
|
|
2842
|
+
if indexpage != None:
|
|
2843
|
+
indexlink = htmltag(
|
|
2844
|
+
"div", tagstyle="text-align: left; float: right; padding-right: 8px"
|
|
2845
|
+
)
|
|
2846
|
+
indexlink.set_tagtext(atag(indexpage, linktext="Index Page").text)
|
|
2847
|
+
indexlinktxt = indexlink.text
|
|
2848
|
+
else:
|
|
2849
|
+
indexlinktxt = ""
|
|
2850
|
+
|
|
2851
|
+
htmlinput["linkstable"] = linktable.text + indexlinktxt
|
|
2852
|
+
|
|
2853
|
+
# output CSS file
|
|
2854
|
+
cssfile = os.path.join(outdir, "resultspage.css")
|
|
2855
|
+
fp = open(cssfile, "w")
|
|
2856
|
+
fp.write(result_page_css)
|
|
2857
|
+
fp.close()
|
|
2858
|
+
|
|
2859
|
+
htmlinput["cssfile"] = os.path.basename(cssfile)
|
|
2860
|
+
|
|
2861
|
+
# get time/date for file creation
|
|
2862
|
+
now = datetime.datetime.now()
|
|
2863
|
+
|
|
2864
|
+
# add footer containing author, date and command lines used for page
|
|
2865
|
+
htmlinput["footer"] = "{} - {}<br><br>Command lines used:<br>{}<br>{}<br>".format(
|
|
2866
|
+
__author__, now.strftime("%a %d %b %Y"), " ".join(sys.argv), __version__
|
|
2867
|
+
)
|
|
2868
|
+
|
|
2869
|
+
# create page
|
|
2870
|
+
try:
|
|
2871
|
+
htmlfile = os.path.join(outdir, pname + ".html")
|
|
2872
|
+
fp = open(htmlfile, "w")
|
|
2873
|
+
fp.write(htmlpage.format(**htmlinput))
|
|
2874
|
+
fp.close()
|
|
2875
|
+
except:
|
|
2876
|
+
print("Error... there was a problem outputting the html page.", file=sys.stderr)
|
|
2877
|
+
sys.exit(1)
|
|
2878
|
+
|
|
2879
|
+
# output JSON file with results information
|
|
2880
|
+
info = {} # a dictionary with the analysis information
|
|
2881
|
+
|
|
2882
|
+
info["PSR"] = pname # set the pulsar name
|
|
2883
|
+
|
|
2884
|
+
# data about the pulsar
|
|
2885
|
+
info["Pulsar data"] = {}
|
|
2886
|
+
info["Pulsar data"]["F0"] = f0
|
|
2887
|
+
info["Pulsar data"]["F0ROT"] = f0
|
|
2888
|
+
info["Pulsar data"]["F0GW"] = 2.0 * f0 # assuming l=m=2 mode emission
|
|
2889
|
+
info["Pulsar data"]["F1"] = f1
|
|
2890
|
+
info["Pulsar data"]["F1ROT"] = f1
|
|
2891
|
+
info["Pulsar data"]["F1GW"] = 2.0 * f1 # assuming l=m=2 mode emission
|
|
2892
|
+
info["Pulsar data"]["F1SD"] = f1sd # acceleration corrected f1
|
|
2893
|
+
info["Pulsar data"][
|
|
2894
|
+
"P1_I"
|
|
2895
|
+
] = p1_I # intrinsic period derivative (corrected for proper motion/GC acceleration effects)
|
|
2896
|
+
info["Pulsar data"]["DIST"] = dist
|
|
2897
|
+
info["Pulsar data"]["RA"] = par["RA_RAD"] # right ascension in radians
|
|
2898
|
+
info["Pulsar data"]["DEC"] = par["DEC_RAD"] # declination in radians
|
|
2899
|
+
info["Pulsar data"]["START"] = par["START"]
|
|
2900
|
+
info["Pulsar data"]["FINISH"] = par["FINISH"]
|
|
2901
|
+
info["Pulsar data"]["BINARY"] = par["BINARY"]
|
|
2902
|
+
info["Pulsar data"]["PEPOCH"] = par["PEPOCH"]
|
|
2903
|
+
info["Pulsar data"]["POSEPOCH"] = par["POSEPOCH"]
|
|
2904
|
+
info["Pulsar data"]["EPHEM"] = par["EPHEM"]
|
|
2905
|
+
info["Pulsar data"]["UNITS"] = par["UNITS"]
|
|
2906
|
+
info["Pulsar data"]["ASSOC"] = assoc # any association for the pulsar
|
|
2907
|
+
info["Pulsar data"]["spin-down limit"] = sdlim
|
|
2908
|
+
info["Pulsar data"]["par file"] = parfile
|
|
2909
|
+
info["Pulsar data"]["ATNF URL"] = atnfurl
|
|
2910
|
+
|
|
2911
|
+
# data about the upper limits
|
|
2912
|
+
for ifo in ifos:
|
|
2913
|
+
info[ifo] = {}
|
|
2914
|
+
info[ifo]["Upper limits"] = {}
|
|
2915
|
+
info[ifo]["Upper limits"]["credible region"] = upperlim
|
|
2916
|
+
info[ifo]["Upper limits"]["H0"] = postinfo.h0_ul(ifo)
|
|
2917
|
+
info[ifo]["Upper limits"]["ELL"] = postinfo.ellipticity_ul(ifo)
|
|
2918
|
+
info[ifo]["Upper limits"]["Q22"] = postinfo.q22_ul(ifo)
|
|
2919
|
+
info[ifo]["Upper limits"]["C21"] = postinfo.C21_ul(ifo)
|
|
2920
|
+
info[ifo]["Upper limits"]["C22"] = postinfo.C22_ul(ifo)
|
|
2921
|
+
info[ifo]["Upper limits"]["I21"] = postinfo.I21_ul(ifo)
|
|
2922
|
+
info[ifo]["Upper limits"]["I31"] = postinfo.I21_ul(ifo)
|
|
2923
|
+
info[ifo]["Upper limits"]["spin-down ratio"] = postinfo.sdlim_ratio(ifo)
|
|
2924
|
+
|
|
2925
|
+
# evidence ratios
|
|
2926
|
+
info[ifo]["Bayes factors"] = {}
|
|
2927
|
+
info[ifo]["Bayes factors"]["Signal vs Noise"] = postinfo.bsn[ifo]
|
|
2928
|
+
|
|
2929
|
+
if "Joint" == ifo:
|
|
2930
|
+
info[ifo]["Bayes factors"]["Coherent vs Incoherent"] = postinfo.bci
|
|
2931
|
+
info[ifo]["Bayes factors"][
|
|
2932
|
+
"Coherent vs Incoherent or Noise"
|
|
2933
|
+
] = postinfo.bcin
|
|
2934
|
+
|
|
2935
|
+
info[ifo]["SNR"] = postinfo.snr(ifo)
|
|
2936
|
+
|
|
2937
|
+
# amplitude noise spectal densities
|
|
2938
|
+
if ifo != "Joint":
|
|
2939
|
+
info[ifo]["Amplitude spectral density"] = {}
|
|
2940
|
+
|
|
2941
|
+
if len(harmonics) == 1:
|
|
2942
|
+
info[ifo]["Amplitude spectral density"]["Spectrum"] = datatable.asds[
|
|
2943
|
+
harmonics[0]
|
|
2944
|
+
][ifo].tolist()
|
|
2945
|
+
info[ifo]["Amplitude spectral density"]["Mean"] = np.mean(
|
|
2946
|
+
datatable.asds[harmonics[0]][ifo]
|
|
2947
|
+
)
|
|
2948
|
+
info[ifo]["Amplitude spectral density"]["Median"] = np.median(
|
|
2949
|
+
datatable.asds[harmonics[0]][ifo]
|
|
2950
|
+
)
|
|
2951
|
+
info[ifo]["Amplitude spectral density"]["Maximum"] = np.max(
|
|
2952
|
+
datatable.asds[harmonics[0]][ifo]
|
|
2953
|
+
)
|
|
2954
|
+
else:
|
|
2955
|
+
for h in harmonics:
|
|
2956
|
+
info[ifo]["Amplitude spectral density"][
|
|
2957
|
+
"%df harmonic" % int(h)
|
|
2958
|
+
] = {}
|
|
2959
|
+
info[ifo]["Amplitude spectral density"]["%df harmonic" % int(h)][
|
|
2960
|
+
"Spectrum"
|
|
2961
|
+
] = datatable.asds[h][ifo].tolist()
|
|
2962
|
+
info[ifo]["Amplitude spectral density"]["%df harmonic" % int(h)][
|
|
2963
|
+
"Mean"
|
|
2964
|
+
] = np.mean(datatable.asds[h][ifo])
|
|
2965
|
+
info[ifo]["Amplitude spectral density"]["%df harmonic" % int(h)][
|
|
2966
|
+
"Median"
|
|
2967
|
+
] = np.median(datatable.asds[h][ifo])
|
|
2968
|
+
info[ifo]["Amplitude spectral density"]["%df harmonic" % int(h)][
|
|
2969
|
+
"Maximum"
|
|
2970
|
+
] = np.max(datatable.asds[h][ifo])
|
|
2971
|
+
|
|
2972
|
+
jsonfile = os.path.join(outdir, pname + ".json")
|
|
2973
|
+
fp = open(jsonfile, "w")
|
|
2974
|
+
json.dump(info, fp, indent=2)
|
|
2975
|
+
fp.close()
|
|
2976
|
+
|
|
2977
|
+
sys.exit(0)
|