def ligolw_bucut(xmldoc, options, burst_test_func, veto_segments=segments.segmentlistdict(), del_non_coincs=False, del_skipped_injections=False, program=None, verbose=False): contents = DocContents(xmldoc, program) process = append_process(xmldoc, options) apply_filters(contents, burst_test_func, veto_segments, del_non_coincs=del_non_coincs, del_skipped_injections=del_skipped_injections, verbose=verbose) ligolw_process.set_process_end_time(process) seg = contents.outsegs.extent_all() ligolw_search_summary.append_search_summary(xmldoc, process, inseg=seg, outseg=seg, nevents=len( contents.snglbursttable)) return xmldoc
def tosegmentxml(file, segs): """ Write the glue.segments.segmentlist object segs to file object file in xml format with appropriate tables. """ # generate empty document xmldoc = ligolw.Document() xmldoc.appendChild(ligolw.LIGO_LW()) xmldoc.childNodes[-1].appendChild(lsctables.New(lsctables.ProcessTable)) xmldoc.childNodes[-1].appendChild(lsctables.New(lsctables.ProcessParamsTable)) # append process to table process = ligolw_process.append_process(xmldoc,\ program='pylal.dq.dqSegmentUtils',\ version=__version__,\ cvs_repository='lscsoft',\ cvs_entry_time=__date__) gpssegs = segments.segmentlist() for seg in segs: gpssegs.append(segments.segment(LIGOTimeGPS(seg[0]), LIGOTimeGPS(seg[1]))) # append segs and seg definer segments_tables = ligolw_segments.LigolwSegments(xmldoc) segments_tables.add(ligolw_segments.LigolwSegmentList(active=gpssegs)) # finalise segments_tables.coalesce() segments_tables.optimize() segments_tables.finalize(process) ligolw_process.set_process_end_time(process) # write file utils.write_fileobj(xmldoc, file, gz=False)
def gen_likelihood_control(coinc_params_distributions, seglists, name=u"ligolw_burca_tailor", comment=u""): xmldoc = ligolw.Document() node = xmldoc.appendChild(ligolw.LIGO_LW()) process = ligolw_process.register_to_xmldoc(xmldoc, program=process_program_name, paramdict={}, version=__version__, cvs_repository="lscsoft", cvs_entry_time=__date__, comment=comment) coinc_params_distributions.process_id = process.process_id ligolw_search_summary.append_search_summary(xmldoc, process, ifos=seglists.keys(), inseg=seglists.extent_all(), outseg=seglists.extent_all()) node.appendChild(coinc_params_distributions.to_xml(name)) ligolw_process.set_process_end_time(process) return xmldoc
def gen_likelihood_control(coinc_params_distributions, seglists, name = u"ligolw_burca_tailor", comment = u""): xmldoc = ligolw.Document() node = xmldoc.appendChild(ligolw.LIGO_LW()) process = ligolw_process.register_to_xmldoc(xmldoc, program = process_program_name, paramdict = {}, version = __version__, cvs_repository = "lscsoft", cvs_entry_time = __date__, comment = comment) coinc_params_distributions.process_id = process.process_id ligolw_search_summary.append_search_summary(xmldoc, process, ifos = seglists.keys(), inseg = seglists.extent_all(), outseg = seglists.extent_all()) node.appendChild(coinc_params_distributions.to_xml(name)) ligolw_process.set_process_end_time(process) return xmldoc
def ligolw_bucut(xmldoc, options, burst_test_func, veto_segments = segments.segmentlistdict(), del_non_coincs = False, del_skipped_injections = False, program = None, verbose = False): contents = DocContents(xmldoc, program) process = append_process(xmldoc, options) apply_filters(contents, burst_test_func, veto_segments, del_non_coincs = del_non_coincs, del_skipped_injections = del_skipped_injections, verbose = verbose) ligolw_process.set_process_end_time(process) seg = contents.outsegs.extent_all() ligolw_search_summary.append_search_summary(xmldoc, process, inseg = seg, outseg = seg, nevents = len(contents.snglbursttable)) return xmldoc
def ligolw_sicluster(doc, **kwargs): # Extract segments and tables inseg, outseg, snglinspiraltable = get_tables(doc) # Add process information try: process = append_process(doc, **kwargs) except ValueError: process = None # Delete all triggers below threshold if kwargs["snr_threshold"] > 0: thresh = float(kwargs["snr_threshold"]) if kwargs["verbose"]: print >>sys.stderr, "discarding triggers with snr < %f ..." % \ kwargs["snr_threshold"] for i in range(len(snglinspiraltable) - 1, -1, -1): if snglinspiraltable[i].snr <= thresh: del snglinspiraltable[i] # Cluster snglcluster.cluster_events( snglinspiraltable, testfunc=lambda a, b: SnglInspiralUtils.CompareSnglInspiral( a, b, twindow=kwargs["cluster_window"]), clusterfunc=SnglInspiralCluster, sortfunc=SnglInspiralUtils.CompareSnglInspiralByEndTime, bailoutfunc=lambda a, b: SnglInspiralUtils.CompareSnglInspiral( a, b, twindow=kwargs["cluster_window"]), verbose=kwargs["verbose"]) # Sort by signal-to-noise ratio if kwargs["sort_ascending_snr"] or kwargs["sort_descending_snr"]: if kwargs["verbose"]: print >> sys.stderr, "sorting by snr ..." snglinspiraltable.sort(SnglInspiralUtils.CompareSnglInspiralBySnr) if kwargs["sort_descending_snr"]: snglinspiraltable.reverse() # Add search summary information if process and inseg and outseg: ligolw_search_summary.append_search_summary( doc, process, inseg=inseg, outseg=outseg, nevents=len(snglinspiraltable)) if process: ligolw_process.set_process_end_time(process) return doc
def checkpoint_save(xmldoc, fout, process): print >> sys.stderr, "\t[Checkpointing ...]" # save rng state rng_state = np.random.get_state() np.savez(fout + "_checkpoint.rng.npz", state1=rng_state[1], state2=np.array(rng_state[2]), state3=np.array(rng_state[3]), state4=np.array(rng_state[4])) # write out the document ligolw_process.set_process_end_time(process) utils.write_filename(xmldoc, fout + "_checkpoint.gz", gz=True)
def checkpoint_save(xmldoc, fout, process): print >>sys.stderr, "\t[Checkpointing ...]" # save rng state rng_state = np.random.get_state() np.savez(fout + "_checkpoint.rng.npz", state1=rng_state[1], state2=np.array(rng_state[2]), state3=np.array(rng_state[3]), state4=np.array(rng_state[4])) # write out the document ligolw_process.set_process_end_time(process) utils.write_filename(xmldoc, fout + "_checkpoint.gz", gz=True)
def ligolw_sicluster(doc, **kwargs): # Extract segments and tables inseg, outseg, snglinspiraltable = get_tables(doc) # Add process information try: process = append_process(doc, **kwargs) except ValueError: process = None # Delete all triggers below threshold if kwargs["snr_threshold"] > 0: thresh = float(kwargs["snr_threshold"]) if kwargs["verbose"]: print >>sys.stderr, "discarding triggers with snr < %f ..." % \ kwargs["snr_threshold"] for i in range(len(snglinspiraltable) - 1, -1, -1): if snglinspiraltable[i].snr <= thresh: del snglinspiraltable[i] # Cluster snglcluster.cluster_events( snglinspiraltable, testfunc = lambda a, b: SnglInspiralUtils.CompareSnglInspiral(a, b, twindow = kwargs["cluster_window"]), clusterfunc = SnglInspiralCluster, sortfunc = SnglInspiralUtils.CompareSnglInspiralByEndTime, bailoutfunc = lambda a, b: SnglInspiralUtils.CompareSnglInspiral(a, b, twindow = kwargs["cluster_window"]), verbose = kwargs["verbose"] ) # Sort by signal-to-noise ratio if kwargs["sort_ascending_snr"] or kwargs["sort_descending_snr"]: if kwargs["verbose"]: print >>sys.stderr, "sorting by snr ..." snglinspiraltable.sort(SnglInspiralUtils.CompareSnglInspiralBySnr) if kwargs["sort_descending_snr"]: snglinspiraltable.reverse() # Add search summary information if process and inseg and outseg: ligolw_search_summary.append_search_summary(doc, process, inseg = inseg, outseg = outseg, nevents = len(snglinspiraltable)) if process: ligolw_process.set_process_end_time(process) return doc
def tosegmentxml(file, segs): """ Write the glue.segments.segmentlist object segs to file object file in xml format with appropriate tables. """ # generate empty document xmldoc = ligolw.Document() xmldoc.appendChild(ligolw.LIGO_LW()) xmldoc.childNodes[-1].appendChild(lsctables.New(lsctables.ProcessTable)) xmldoc.childNodes[-1].appendChild( lsctables.New(lsctables.ProcessParamsTable)) # append process to table process = ligolw_process.append_process(xmldoc,\ program='pylal.dq.dqSegmentUtils',\ version=__version__,\ cvs_repository='lscsoft',\ cvs_entry_time=__date__) gpssegs = segments.segmentlist() for seg in segs: gpssegs.append( segments.segment(LIGOTimeGPS(seg[0]), LIGOTimeGPS(seg[1]))) # append segs and seg definer segments_tables = ligolw_segments.LigolwSegments(xmldoc) segments_tables.add(ligolw_segments.LigolwSegmentList(active=gpssegs)) # finalise segments_tables.coalesce() segments_tables.optimize() segments_tables.finalize(process) ligolw_process.set_process_end_time(process) # write file with utils.SignalsTrap(): utils.write_fileobj(xmldoc, file, gz=False)
timeslidetable = lsctables.TimeSlideTable.get_table(xmldoc) # # How many slides will go into this file? # N = int(round(float(len(time_slides)) / len(filenames))) # # Put them in. # for offsetvect in time_slides[:N]: timeslidetable.append_offsetvector(offsetvect, process) del time_slides[:N] # # Finish off the document. # ligolw_process.set_process_end_time(process) # # Write. # filename = filenames.pop(0) ligolw_utils.write_filename(xmldoc, filename, verbose = options.verbose, gz = (filename or "stdout").endswith(".gz")) assert not time_slides
# # Call clustering library # xmldoc, changed = bucluster.bucluster( xmldoc, program = options.program, process = process, prefunc = prefunc, postfunc = postfunc, testfunc = testfunc, clusterfunc = clusterfunc, sortfunc = sortfunc, bailoutfunc = bailoutfunc, verbose = options.verbose ) # # Finish process information # ligolw_process.set_process_end_time(process) # # Write document # if changed: utils.write_filename(xmldoc, filename, gz = (filename or "stdout").endswith(".gz"), verbose = options.verbose) xmldoc.unlink()
ext_node.set_ihope_base_dir(ihope_base_dir) for node in lc_nodes: ext_node.add_parent(node) dag.add_node(ext_node) ############################################################################## ############################################################################## # Final Step: Write the DAG print "Writing DAG and sub files..." # set max-jobs: currently, only minifollowups is set dag.add_maxjobs_category('minifollowups', 15) dag.write_sub_files() dag.write_script() dag.write_dag() # write process end time to log file and write log file process.set_process_end_time(proc_id) utils.write_filename(logdoc, basename+'.log.xml', xsl_file = "ligolw.xsl") print "Finished!" print "Now run:\n\tcondor_submit_dag %s" % os.path.basename(dag.get_dag_file()) sys.exit(0)
def main(args=None): p = parser() opts = p.parse_args(args) # LIGO-LW XML imports. from glue.ligolw import ligolw from glue.ligolw.param import Param from glue.ligolw.utils import process as ligolw_process from glue.ligolw.utils.search_summary import append_search_summary from glue.ligolw import utils as ligolw_utils from glue.ligolw.lsctables import (New, CoincDefTable, CoincID, CoincInspiralTable, CoincMapTable, CoincTable, ProcessParamsTable, ProcessTable, SimInspiralTable, SnglInspiralTable, TimeSlideTable) # glue, LAL and pylal imports. from ligo import segments import glue.lal import lal.series import lalsimulation from lalinspiral.inspinjfind import InspiralSCExactCoincDef from lalinspiral.thinca import InspiralCoincDef from tqdm import tqdm # FIXME: disable progress bar monitor thread. # # I was getting error messages that look like this: # # Traceback (most recent call last): # File "/tqdm/_tqdm.py", line 885, in __del__ # self.close() # File "/tqdm/_tqdm.py", line 1090, in close # self._decr_instances(self) # File "/tqdm/_tqdm.py", line 454, in _decr_instances # cls.monitor.exit() # File "/tqdm/_monitor.py", line 52, in exit # self.join() # File "/usr/lib64/python3.6/threading.py", line 1053, in join # raise RuntimeError("cannot join current thread") # RuntimeError: cannot join current thread # # I don't know what causes this... maybe a race condition in tqdm's cleanup # code. Anyway, this should disable the tqdm monitor thread entirely. tqdm.monitor_interval = 0 # BAYESTAR imports. from ..io.events.ligolw import ContentHandler from ..bayestar import filter # Read PSDs. xmldoc, _ = ligolw_utils.load_fileobj( opts.reference_psd, contenthandler=lal.series.PSDContentHandler) psds = lal.series.read_psd_xmldoc(xmldoc, root_name=None) psds = { key: filter.InterpolatedPSD(filter.abscissa(psd), psd.data.data) for key, psd in psds.items() if psd is not None } psds = [psds[ifo] for ifo in opts.detector] # Extract simulation table from injection file. inj_xmldoc, _ = ligolw_utils.load_fileobj(opts.input, contenthandler=ContentHandler) orig_sim_inspiral_table = SimInspiralTable.get_table(inj_xmldoc) # Prune injections that are outside distance limits. orig_sim_inspiral_table[:] = [ row for row in orig_sim_inspiral_table if opts.min_distance <= row.distance <= opts.max_distance ] # Open output file. xmldoc = ligolw.Document() xmlroot = xmldoc.appendChild(ligolw.LIGO_LW()) # Create tables. Process and ProcessParams tables are copied from the # injection file. coinc_def_table = xmlroot.appendChild(New(CoincDefTable)) coinc_inspiral_table = xmlroot.appendChild(New(CoincInspiralTable)) coinc_map_table = xmlroot.appendChild(New(CoincMapTable)) coinc_table = xmlroot.appendChild(New(CoincTable)) xmlroot.appendChild(ProcessParamsTable.get_table(inj_xmldoc)) xmlroot.appendChild(ProcessTable.get_table(inj_xmldoc)) sim_inspiral_table = xmlroot.appendChild(New(SimInspiralTable)) sngl_inspiral_table = xmlroot.appendChild(New(SnglInspiralTable)) time_slide_table = xmlroot.appendChild(New(TimeSlideTable)) # Write process metadata to output file. process = register_to_xmldoc(xmldoc, p, opts, ifos=opts.detector, comment="Simulated coincidences") # Add search summary to output file. all_time = segments.segment( [glue.lal.LIGOTimeGPS(0), glue.lal.LIGOTimeGPS(2e9)]) append_search_summary(xmldoc, process, inseg=all_time, outseg=all_time) # Create a time slide entry. Needed for coinc_event rows. time_slide_id = time_slide_table.get_time_slide_id( {ifo: 0 for ifo in opts.detector}, create_new=process) # Populate CoincDef table. inspiral_coinc_def = copy.copy(InspiralCoincDef) inspiral_coinc_def.coinc_def_id = coinc_def_table.get_next_id() coinc_def_table.append(inspiral_coinc_def) found_coinc_def = copy.copy(InspiralSCExactCoincDef) found_coinc_def.coinc_def_id = coinc_def_table.get_next_id() coinc_def_table.append(found_coinc_def) # Precompute values that are common to all simulations. detectors = [ lalsimulation.DetectorPrefixToLALDetector(ifo) for ifo in opts.detector ] responses = [det.response for det in detectors] locations = [det.location for det in detectors] if opts.jobs == 1: pool_map = map else: from .. import omp from multiprocessing import Pool omp.num_threads = 1 # disable OpenMP parallelism pool_map = Pool(opts.jobs).imap func = functools.partial(simulate, psds=psds, responses=responses, locations=locations, measurement_error=opts.measurement_error, f_low=opts.f_low, waveform=opts.waveform) # Make sure that each thread gets a different random number state. # We start by drawing a random integer s in the main thread, and # then the i'th subprocess will seed itself with the integer i + s. # # The seed must be an unsigned 32-bit integer, so if there are n # threads, then s must be drawn from the interval [0, 2**32 - n). # # Note that *we* are thread 0, so there are a total of # n=1+len(sim_inspiral_table) threads. seed = np.random.randint(0, 2**32 - len(sim_inspiral_table) - 1) np.random.seed(seed) count_coincs = 0 with tqdm(total=len(orig_sim_inspiral_table)) as progress: for sim_inspiral, simulation in zip( orig_sim_inspiral_table, pool_map( func, zip( np.arange(len(orig_sim_inspiral_table)) + seed + 1, orig_sim_inspiral_table))): progress.update() sngl_inspirals = [] used_snr_series = [] net_snr = 0.0 count_triggers = 0 # Loop over individual detectors and create SnglInspiral entries. for ifo, (horizon, abs_snr, arg_snr, toa, series) \ in zip(opts.detector, simulation): if np.random.uniform() > opts.duty_cycle: continue elif abs_snr >= opts.snr_threshold: # If SNR < threshold, then the injection is not found. # Skip it. count_triggers += 1 net_snr += np.square(abs_snr) elif not opts.keep_subthreshold: continue # Create SnglInspiral entry. used_snr_series.append(series) sngl_inspirals.append( sngl_inspiral_table.RowType(**dict( dict.fromkeys(sngl_inspiral_table.validcolumns, None), process_id=process.process_id, ifo=ifo, mass1=sim_inspiral.mass1, mass2=sim_inspiral.mass2, spin1x=sim_inspiral.spin1x, spin1y=sim_inspiral.spin1y, spin1z=sim_inspiral.spin1z, spin2x=sim_inspiral.spin2x, spin2y=sim_inspiral.spin2y, spin2z=sim_inspiral.spin2z, end=toa, snr=abs_snr, coa_phase=arg_snr, eff_distance=horizon / abs_snr))) net_snr = np.sqrt(net_snr) # If too few triggers were found, then skip this event. if count_triggers < opts.min_triggers: continue # If network SNR < threshold, then the injection is not found. # Skip it. if net_snr < opts.net_snr_threshold: continue # Add Coinc table entry. coinc = coinc_table.appendRow( coinc_event_id=coinc_table.get_next_id(), process_id=process.process_id, coinc_def_id=inspiral_coinc_def.coinc_def_id, time_slide_id=time_slide_id, insts=opts.detector, nevents=len(opts.detector), likelihood=None) # Add CoincInspiral table entry. coinc_inspiral_table.appendRow( coinc_event_id=coinc.coinc_event_id, instruments=[ sngl_inspiral.ifo for sngl_inspiral in sngl_inspirals ], end=lal.LIGOTimeGPS(1e-9 * np.mean([ sngl_inspiral.end.ns() for sngl_inspiral in sngl_inspirals if sngl_inspiral.end is not None ])), mass=sim_inspiral.mass1 + sim_inspiral.mass2, mchirp=sim_inspiral.mchirp, combined_far=0.0, # Not provided false_alarm_rate=0.0, # Not provided minimum_duration=None, # Not provided snr=net_snr) # Record all sngl_inspiral records and associate them with coincs. for sngl_inspiral, series in zip(sngl_inspirals, used_snr_series): # Give this sngl_inspiral record an id and add it to the table. sngl_inspiral.event_id = sngl_inspiral_table.get_next_id() sngl_inspiral_table.append(sngl_inspiral) if opts.enable_snr_series: elem = lal.series.build_COMPLEX8TimeSeries(series) elem.appendChild( Param.from_pyvalue(u'event_id', sngl_inspiral.event_id)) xmlroot.appendChild(elem) # Add CoincMap entry. coinc_map_table.appendRow( coinc_event_id=coinc.coinc_event_id, table_name=sngl_inspiral_table.tableName, event_id=sngl_inspiral.event_id) # Record injection if not opts.preserve_ids: sim_inspiral.simulation_id = sim_inspiral_table.get_next_id() sim_inspiral_table.append(sim_inspiral) count_coincs += 1 progress.set_postfix(saved=count_coincs) # Record coincidence associating injections with events. for i, sim_inspiral in enumerate(sim_inspiral_table): coinc = coinc_table.appendRow( coinc_event_id=coinc_table.get_next_id(), process_id=process.process_id, coinc_def_id=found_coinc_def.coinc_def_id, time_slide_id=time_slide_id, instruments=None, nevents=None, likelihood=None) coinc_map_table.appendRow(coinc_event_id=coinc.coinc_event_id, table_name=sim_inspiral_table.tableName, event_id=sim_inspiral.simulation_id) coinc_map_table.appendRow(coinc_event_id=coinc.coinc_event_id, table_name=coinc_table.tableName, event_id=CoincID(i)) # Record process end time. ligolw_process.set_process_end_time(process) # Write output file. write_fileobj(xmldoc, opts.output)
subparser.add_argument('ifo1', choices=available_ifos) subparser.add_argument('ifo2', choices=available_ifos) subparser = add_parser(conj) subparser.add_argument('ifos', choices=available_ifos, nargs='+') subparser = add_parser(amplify) subparser.add_argument('ifos', choices=available_ifos, nargs='+') subparser.add_argument('gain', type=float) args = parser.parse_args() kwargs = dict(args.__dict__) func = locals()[kwargs.pop('func')] infile = kwargs.pop('input') outfile = kwargs.pop('output') # Read input file. xmldoc, _ = load_fileobj( infile, contenthandler=LSCTablesAndSeriesContentHandler) # Process it. process = command.register_to_xmldoc(xmldoc, parser, args) func(xmldoc, **kwargs) set_process_end_time(process) # Write output file. with SignalsTrap(): write_fileobj( xmldoc, outfile, gz=(os.path.splitext(outfile.name)[-1] == '.gz'))
def main(args=None): from glue.ligolw import lsctables from glue.ligolw.utils import process as ligolw_process from glue.ligolw import utils as ligolw_utils from glue.ligolw import ligolw import lal.series from scipy import stats p = parser() args = p.parse_args(args) xmldoc = ligolw.Document() xmlroot = xmldoc.appendChild(ligolw.LIGO_LW()) process = register_to_xmldoc(xmldoc, p, args) cosmo = cosmology.default_cosmology.get_cosmology_from_string( args.cosmology) ns_mass_min = 1.0 ns_mass_max = 2.0 bh_mass_min = 5.0 bh_mass_max = 50.0 ns_astro_spin_min = -0.05 ns_astro_spin_max = +0.05 ns_astro_mass_dist = stats.norm(1.33, 0.09) ns_astro_spin_dist = stats.uniform(ns_astro_spin_min, ns_astro_spin_max - ns_astro_spin_min) ns_broad_spin_min = -0.4 ns_broad_spin_max = +0.4 ns_broad_mass_dist = stats.uniform(ns_mass_min, ns_mass_max - ns_mass_min) ns_broad_spin_dist = stats.uniform(ns_broad_spin_min, ns_broad_spin_max - ns_broad_spin_min) bh_astro_spin_min = -0.99 bh_astro_spin_max = +0.99 bh_astro_mass_dist = stats.pareto(b=1.3) bh_astro_spin_dist = stats.uniform(bh_astro_spin_min, bh_astro_spin_max - bh_astro_spin_min) bh_broad_spin_min = -0.99 bh_broad_spin_max = +0.99 bh_broad_mass_dist = stats.reciprocal(bh_mass_min, bh_mass_max) bh_broad_spin_dist = stats.uniform(bh_broad_spin_min, bh_broad_spin_max - bh_broad_spin_min) if args.distribution.startswith('bns_'): m1_min = m2_min = ns_mass_min m1_max = m2_max = ns_mass_max if args.distribution.endswith('_astro'): x1_min = x2_min = ns_astro_spin_min x1_max = x2_max = ns_astro_spin_max m1_dist = m2_dist = ns_astro_mass_dist x1_dist = x2_dist = ns_astro_spin_dist elif args.distribution.endswith('_broad'): x1_min = x2_min = ns_broad_spin_min x1_max = x2_max = ns_broad_spin_max m1_dist = m2_dist = ns_broad_mass_dist x1_dist = x2_dist = ns_broad_spin_dist else: # pragma: no cover assert_not_reached() elif args.distribution.startswith('nsbh_'): m1_min = bh_mass_min m1_max = bh_mass_max m2_min = ns_mass_min m2_max = ns_mass_max if args.distribution.endswith('_astro'): x1_min = bh_astro_spin_min x1_max = bh_astro_spin_max x2_min = ns_astro_spin_min x2_max = ns_astro_spin_max m1_dist = bh_astro_mass_dist m2_dist = ns_astro_mass_dist x1_dist = bh_astro_spin_dist x2_dist = ns_astro_spin_dist elif args.distribution.endswith('_broad'): x1_min = bh_broad_spin_min x1_max = bh_broad_spin_max x2_min = ns_broad_spin_min x2_max = ns_broad_spin_max m1_dist = bh_broad_mass_dist m2_dist = ns_broad_mass_dist x1_dist = bh_broad_spin_dist x2_dist = ns_broad_spin_dist else: # pragma: no cover assert_not_reached() elif args.distribution.startswith('bbh_'): m1_min = m2_min = bh_mass_min m1_max = m2_max = bh_mass_max if args.distribution.endswith('_astro'): x1_min = x2_min = bh_astro_spin_min x1_max = x2_max = bh_astro_spin_max m1_dist = m2_dist = bh_astro_mass_dist x1_dist = x2_dist = bh_astro_spin_dist elif args.distribution.endswith('_broad'): x1_min = x2_min = bh_broad_spin_min x1_max = x2_max = bh_broad_spin_max m1_dist = m2_dist = bh_broad_mass_dist x1_dist = x2_dist = bh_broad_spin_dist else: # pragma: no cover assert_not_reached() else: # pragma: no cover assert_not_reached() dists = (m1_dist, m2_dist, x1_dist, x2_dist) # Read PSDs psds = list( lal.series.read_psd_xmldoc( ligolw_utils.load_fileobj( args.reference_psd, contenthandler=lal.series.PSDContentHandler)[0]).values()) # Construct mass1, mass2, spin1z, spin2z grid. m1 = np.geomspace(m1_min, m1_max, 10) m2 = np.geomspace(m2_min, m2_max, 10) x1 = np.linspace(x1_min, x1_max, 10) x2 = np.linspace(x2_min, x2_max, 10) params = m1, m2, x1, x2 # Calculate the maximum distance on the grid. max_z = get_max_z(cosmo, psds, args.waveform, args.f_low, args.min_snr, m1, m2, x1, x2, jobs=args.jobs) max_distance = sensitive_distance(cosmo, max_z).to_value(units.Mpc) # Find piecewise constant approximate upper bound on distance. max_distance = cell_max(max_distance) # Calculate V * T in each grid cell cdfs = [dist.cdf(param) for param, dist in zip(params, dists)] cdf_los = [cdf[:-1] for cdf in cdfs] cdfs = [np.diff(cdf) for cdf in cdfs] probs = np.prod(np.meshgrid(*cdfs, indexing='ij'), axis=0) probs /= probs.sum() probs *= 4 / 3 * np.pi * max_distance**3 volume = probs.sum() probs /= volume probs = probs.ravel() volumetric_rate = args.nsamples / volume * units.year**-1 * units.Mpc**-3 # Draw random grid cells dist = stats.rv_discrete(values=(np.arange(len(probs)), probs)) indices = np.unravel_index(dist.rvs(size=args.nsamples), max_distance.shape) # Draw random intrinsic params from each cell cols = {} cols['mass1'], cols['mass2'], cols['spin1z'], cols['spin2z'] = [ dist.ppf(stats.uniform(cdf_lo[i], cdf[i]).rvs(size=args.nsamples)) for i, dist, cdf_lo, cdf in zip(indices, dists, cdf_los, cdfs) ] # Draw random extrinsic parameters cols['distance'] = stats.powerlaw( a=3, scale=max_distance[indices]).rvs(size=args.nsamples) cols['longitude'] = stats.uniform(0, 2 * np.pi).rvs(size=args.nsamples) cols['latitude'] = np.arcsin(stats.uniform(-1, 2).rvs(size=args.nsamples)) cols['inclination'] = np.arccos( stats.uniform(-1, 2).rvs(size=args.nsamples)) cols['polarization'] = stats.uniform(0, 2 * np.pi).rvs(size=args.nsamples) cols['coa_phase'] = stats.uniform(-np.pi, 2 * np.pi).rvs(size=args.nsamples) cols['time_geocent'] = stats.uniform(1e9, units.year.to( units.second)).rvs(size=args.nsamples) # Convert from sensitive distance to redshift and comoving distance. # FIXME: Replace this brute-force lookup table with a solver. z = np.linspace(0, max_z.max(), 10000) ds = sensitive_distance(cosmo, z).to_value(units.Mpc) dc = cosmo.comoving_distance(z).to_value(units.Mpc) z_for_ds = interp1d(ds, z, kind='cubic', assume_sorted=True) dc_for_ds = interp1d(ds, dc, kind='cubic', assume_sorted=True) zp1 = 1 + z_for_ds(cols['distance']) cols['distance'] = dc_for_ds(cols['distance']) # Apply redshift factor to convert from comoving distance and source frame # masses to luminosity distance and observer frame masses. for key in ['distance', 'mass1', 'mass2']: cols[key] *= zp1 # Populate sim_inspiral table sims = xmlroot.appendChild(lsctables.New(lsctables.SimInspiralTable)) for row in zip(*cols.values()): sims.appendRow(**dict(dict.fromkeys(sims.validcolumns, None), process_id=process.process_id, simulation_id=sims.get_next_id(), waveform=args.waveform, f_lower=args.f_low, **dict(zip(cols.keys(), row)))) # Record process end time. process.comment = str(volumetric_rate) ligolw_process.set_process_end_time(process) # Write output file. write_fileobj(xmldoc, args.output)