def get_found_param(injfile, bankfile, trigfile, param, ifo): """ Translates some popular trigger parameters into functions that calculate them from an hdf found injection file Parameters ---------- injfile: hdf5 File object Injection file of format known to ANitz (DOCUMENTME) bankfile: hdf5 File object or None Template bank file trigfile: hdf5 File object or None Single-detector trigger file param: string Parameter to be calculated for the recovered triggers ifo: string or None Standard ifo name, ex. 'L1' Returns ------- [return value]: NumPy array of floats The calculated parameter values """ foundtmp = injfile["found_after_vetoes/template_id"][:] if trigfile is not None: # get the name of the ifo in the injection file, eg "detector_1" # and the integer from that name ifolabel = [name for name, val in injfile.attrs.items() if \ "detector" in name and val == ifo][0] foundtrg = injfile["found_after_vetoes/trigger_id" + ifolabel[-1]] if bankfile is not None and param in bankfile.keys(): return bankfile[param][:][foundtmp] elif trigfile is not None and param in trigfile[ifo].keys(): return trigfile[ifo][param][:][foundtrg] else: b = bankfile found_param_dict = { "mtotal": (b['mass1'][:] + b['mass2'][:])[foundtmp], "mchirp": pnutils.mass1_mass2_to_mchirp_eta(b['mass1'][:], b['mass2'][:])[0][foundtmp], "eta": pnutils.mass1_mass2_to_mchirp_eta(b['mass1'][:], b['mass2'][:])[1][foundtmp], "effective_spin": pnutils.phenomb_chi(b['mass1'][:], b['mass2'][:], b['spin1z'][:], b['spin2z'][:])[foundtmp] } return found_param_dict[param]
def get_found_param(injfile, bankfile, trigfile, param, ifo): """ Translates some popular trigger parameters into functions that calculate them from an hdf found injection file Parameters ---------- injfile: hdf5 File object Injection file of format known to ANitz (DOCUMENTME) bankfile: hdf5 File object or None Template bank file trigfile: hdf5 File object or None Single-detector trigger file param: string Parameter to be calculated for the recovered triggers ifo: string or None Standard ifo name, ex. 'L1' Returns ------- [return value]: NumPy array of floats The calculated parameter values """ foundtmp = injfile["found_after_vetoes/template_id"][:] if trigfile is not None: # get the name of the ifo in the injection file, eg "detector_1" # and the integer from that name ifolabel = [name for name, val in injfile.attrs.items() if \ "detector" in name and val == ifo][0] foundtrg = injfile["found_after_vetoes/trigger_id" + ifolabel[-1]] if bankfile is not None and param in bankfile.keys(): return bankfile[param][:][foundtmp] elif trigfile is not None and param in trigfile[ifo].keys(): return trigfile[ifo][param][:][foundtrg] else: b = bankfile found_param_dict = { "mtotal" : (b['mass1'][:] + b['mass2'][:])[foundtmp], "mchirp" : pnutils.mass1_mass2_to_mchirp_eta(b['mass1'][:], b['mass2'][:])[0][foundtmp], "eta" : pnutils.mass1_mass2_to_mchirp_eta(b['mass1'][:], b['mass2'][:])[1][foundtmp], "effective_spin" : pnutils.phenomb_chi(b['mass1'][:], b['mass2'][:], b['spin1z'][:], b['spin2z'][:])[foundtmp] } return found_param_dict[param]
def __init__(self, filename, f_lower, sample_rate, minimum_buffer, approximant=None, increment=8, parameters=None, load_compressed=True, load_compressed_now=False, **kwds): self.increment = increment self.f_lower = f_lower self.filename = filename self.sample_rate = sample_rate self.minimum_buffer = minimum_buffer super(LiveFilterBank, self).__init__(filename, approximant=approximant, parameters=parameters, load_compressed=load_compressed, load_compressed_now=load_compressed_now, **kwds) if not hasattr(self.table, 'template_duration'): self.table = self.table.add_fields(numpy.zeros(len(self.table), dtype=numpy.float32), 'template_duration') from pycbc.pnutils import mass1_mass2_to_mchirp_eta self.table = sorted(self.table, key=lambda t: mass1_mass2_to_mchirp_eta(t.mass1, t.mass2)[0]) self.hash_lookup = {} for i, p in enumerate(self.table): hash_value = hash((p.mass1, p.mass2, p.spin1z, p.spin2z)) self.hash_lookup[hash_value] = i
def convert_to_sngl_inspiral_table(params, proc_id): """ Convert a list of m1,m2,spin1z,spin2z values into a basic sngl_inspiral table with mass and spin parameters populated and event IDs assigned Parameters ----------- params : iterable Each entry in the params iterable should be a sequence of [mass1, mass2, spin1z, spin2z] in that order proc_id : ilwd char Process ID to add to each row of the sngl_inspiral table Returns ---------- SnglInspiralTable Bank of templates in SnglInspiralTable format """ sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) col_names = ["mass1", "mass2", "spin1z", "spin2z"] for values in params: tmplt = return_empty_sngl() tmplt.process_id = proc_id for colname, value in zip(col_names, values): setattr(tmplt, colname, value) tmplt.mtotal, tmplt.eta = pnutils.mass1_mass2_to_mtotal_eta(tmplt.mass1, tmplt.mass2) tmplt.mchirp, junk = pnutils.mass1_mass2_to_mchirp_eta(tmplt.mass1, tmplt.mass2) tmplt.template_duration = 0 # FIXME tmplt.event_id = sngl_inspiral_table.get_next_id() sngl_inspiral_table.append(tmplt) return sngl_inspiral_table
def get_param(par, args, m1, m2, s1z, s2z): """ Helper function Parameters ---------- par : string Name of parameter to calculate args : Namespace object returned from ArgumentParser instance Calling code command line options, used for f_lower value m1 : float or array of floats First binary component mass (etc.) Returns ------- parvals : float or array of floats Calculated parameter values """ if par == 'mchirp': parvals, _ = pnutils.mass1_mass2_to_mchirp_eta(m1, m2) elif par == 'mtotal': parvals = m1 + m2 elif par == 'template_duration': # default to SEOBNRv4 duration function parvals = pnutils.get_imr_duration(m1, m2, s1z, s2z, args.f_lower, args.approximant or "SEOBNRv4") if args.min_duration: parvals += args.min_duration elif par in pnutils.named_frequency_cutoffs.keys(): parvals = pnutils.frequency_cutoff_from_name(par, m1, m2, s1z, s2z) else: # try asking for a LALSimulation frequency function parvals = pnutils.get_freq(par, m1, m2, s1z, s2z) return parvals
def read_samples_from_walker(self, variable_arg, nwalker, thin_start=None, thin_interval=1): """ Reads all samples from a specific walker for a parameter. Parameters ----------- variable_arg : str Name of parameter to get independent samples. nwalker : int Index of the walker to get samples. thin_start : int Index of the sample to begin returning samples. thin_interval : int Interval to accept every i-th sample. Returns ------- numpy.array Samples from a specific walker for a parameter. """ # default is to skip burn in samples thin_start = self.attrs["burn_in_iterations"] if thin_start is None else thin_start # derived parameter case for mchirp will calculate mchrip # from mass1 and mass2 if variable_arg == "mchirp" and "mchirp" not in self.keys(): mass1 = self.read_samples_from_walker("mass1", nwalker, thin_start=thin_start, thin_interval=thin_interval) mass2 = self.read_samples_from_walker("mass2", nwalker, thin_start=thin_start, thin_interval=thin_interval) return pnutils.mass1_mass2_to_mchirp_eta(mass1, mass2)[0] # derived parameter case for eta will calculate eta # from mass1 and mass2 elif variable_arg == "eta" and "eta" not in self.keys(): mass1 = self.read_samples_from_walker("mass1", nwalker, thin_start=thin_start, thin_interval=thin_interval) mass2 = self.read_samples_from_walker("mass2", nwalker, thin_start=thin_start, thin_interval=thin_interval) return pnutils.mass1_mass2_to_mchirp_eta(mass1, mass2)[1] return self[variable_arg]["walker%d"%nwalker][thin_start::thin_interval]
def outside_mchirp_window(bank, sim, w): # template mchirp if hasattr(bank, "mchirp"): bmchirp = bank.mchirp elif hasattr(bank, "mass1") and hasattr(bank, "mass2"): bmchirp, eta =\ pnutils.mass1_mass2_to_mchirp_eta(bank.mass1, bank.mass2) elif hasattr(bank, "mtotal") and hasattr(bank, "eta"): bmchirp = bank.mtotal * (bank.eta**0.6) # signal / injection / proposal mchirp if hasattr(sim, "mchirp"): smchirp = sim.mchirp elif hasattr(sim, "mass1") and hasattr(sim, "mass2"): smchirp, eta =\ pnutils.mass1_mass2_to_mchirp_eta(sim.mass1, sim.mass2) elif hasattr(sim, "mtotal") and hasattr(sim, "eta"): smchirp = sim.mtotal * (sim.eta**0.6) return abs(smchirp - bmchirp) > (w * bmchirp)
def get_inj_param(injfile, param, ifo): """ Translates some popular injection parameters into functions that calculate them from an hdf found injection file Parameters ---------- injfile: hdf5 File object Injection file of format known to ANitz (DOCUMENTME) param: string Parameter to be calculated for the injected signals ifo: string Standard detector name, ex. 'L1' Returns ------- [return value]: NumPy array of floats The calculated parameter values """ det = pycbc.detector.Detector(ifo) time_delay = numpy.vectorize(#lambda dec, ra, t : det.time_delay_from_earth_center)#(dec, ra, t)) inj = injfile["injections"] if param in inj.keys(): return inj["injections/"+param] inj_param_dict = { "mtotal" : inj['mass1'][:] + inj['mass2'][:], "mchirp" : pnutils.mass1_mass2_to_mchirp_eta(inj['mass1'][:], inj['mass2'][:])[0], "eta" : pnutils.mass1_mass2_to_mchirp_eta(inj['mass1'][:], inj['mass2'][:])[1], "effective_spin" : pnutils.phenomb_chi(inj['mass1'][:], inj['mass2'][:], inj['spin1z'][:], inj['spin2z'][:]), "end_time_"+ifo[0].lower() : inj['end_time'][:] + time_delay(inj['longitude'][:], inj['latitude'][:], inj['end_time'][:]), } return inj_param_dict[param]
def get_inj_param(injfile, param, ifo): """ Translates some popular injection parameters into functions that calculate them from an hdf found injection file Parameters ---------- injfile: hdf5 File object Injection file of format known to ANitz (DOCUMENTME) param: string Parameter to be calculated for the injected signals ifo: string Standard detector name, ex. 'L1' Returns ------- [return value]: NumPy array of floats The calculated parameter values """ det = pycbc.detector.Detector(ifo) time_delay = numpy.vectorize( #lambda dec, ra, t : det.time_delay_from_earth_center) #(dec, ra, t)) inj = injfile["injections"] if param in inj.keys(): return inj["injections/" + param] inj_param_dict = { "mtotal": inj['mass1'][:] + inj['mass2'][:], "mchirp": pnutils.mass1_mass2_to_mchirp_eta(inj['mass1'][:], inj['mass2'][:])[0], "eta": pnutils.mass1_mass2_to_mchirp_eta(inj['mass1'][:], inj['mass2'][:])[1], "effective_spin": pnutils.phenomb_chi(inj['mass1'][:], inj['mass2'][:], inj['spin1z'][:], inj['spin2z'][:]), "end_time_" + ifo[0].lower(): inj['end_time'][:] + time_delay( inj['longitude'][:], inj['latitude'][:], inj['end_time'][:]), } return inj_param_dict[param]
def __init__(self, filename, f_lower, sample_rate, minimum_buffer, approximant=None, **kwds): self.f_lower = f_lower self.filename = filename self.sample_rate = sample_rate self.minimum_buffer = minimum_buffer super(LiveFilterBank, self).__init__(filename, approximant=approximant, **kwds) from pycbc.pnutils import mass1_mass2_to_mchirp_eta self.table = sorted(self.table, key=lambda t: mass1_mass2_to_mchirp_eta(t.mass1, t.mass2)[0])
def __init__(self, filename, f_lower, sample_rate, minimum_buffer, approximant=None, increment=8, **kwds): self.increment = increment self.f_lower = f_lower self.filename = filename self.sample_rate = sample_rate self.minimum_buffer = minimum_buffer super(LiveFilterBank, self).__init__(filename, approximant=approximant, **kwds) from pycbc.pnutils import mass1_mass2_to_mchirp_eta self.table = sorted(self.table, key=lambda t: mass1_mass2_to_mchirp_eta(t.mass1, t.mass2)[0]) self.hash_lookup = {} for i, p in enumerate(self.table): hash_value = hash((p.mass1, p.mass2, p.spin1z, p.spin2z)) self.hash_lookup[hash_value] = i
def __init__(self, filename, f_lower, sample_rate, minimum_buffer, approximant=None, **kwds): self.f_lower = f_lower self.filename = filename self.sample_rate = sample_rate self.minimum_buffer = minimum_buffer super(LiveFilterBank, self).__init__(filename, approximant=approximant, **kwds) from pycbc.pnutils import mass1_mass2_to_mchirp_eta self.table = sorted( self.table, key=lambda t: mass1_mass2_to_mchirp_eta(t.mass1, t.mass2)[0])
def _imrphenombfreq(**p): import lalinspiral params = lalinspiral.InspiralTemplate() m1 = p['mass1'] m2 = p['mass2'] mc, et = pnutils.mass1_mass2_to_mchirp_eta(m1, m2) params.approximant = lalsimulation.IMRPhenomB params.fLower = p['f_lower'] params.eta = et params.distance = p['distance'] * lal.PC_SI * 1e6 params.mass1 = m1 params.mass2 = m2 params.spin1[2] = p['spin1z'] params.spin2[2] = p['spin2z'] params.startPhase = p['coa_phase']*2 - lal.PI params.startTime = 0 params.tSampling = 8192 N = int(params.tSampling / p['delta_f']) n = N / 2 # Create temporary memory to hold the results and call the generator hpt = zeros(N, dtype=float32) hct = zeros(N, dtype=float32) hpt=hpt.lal() hct=hct.lal() lalinspiral.BBHPhenWaveBFreqDomTemplates(hpt, hct, params) # Copy the results to a complex frequencyseries format hctc = FrequencySeries(zeros(n, dtype=complex64), delta_f=p['delta_f']) hptc = FrequencySeries(zeros(n, dtype=complex64), delta_f=p['delta_f']) hptc.data += hpt.data[0:n] hptc.data[1:n] += hpt.data[N:N-n:-1] * 1j hctc.data += hct.data[0:n] hctc.data[1:n] += hct.data[N:N-n:-1] * 1j return hptc.astype(complex128), hctc.astype(complex128)
def __init__(self, filename, f_lower, sample_rate, minimum_buffer, approximant=None, increment=8, parameters=None, load_compressed=True, load_compressed_now=False, **kwds): self.increment = increment self.f_lower = f_lower self.filename = filename self.sample_rate = sample_rate self.minimum_buffer = minimum_buffer super(LiveFilterBank, self).__init__(filename, approximant=approximant, parameters=parameters, load_compressed=load_compressed, load_compressed_now=load_compressed_now, **kwds) if not hasattr(self.table, 'template_duration'): self.table = self.table.add_fields( numpy.zeros(len(self.table), dtype=numpy.float32), 'template_duration') from pycbc.pnutils import mass1_mass2_to_mchirp_eta self.table = sorted( self.table, key=lambda t: mass1_mass2_to_mchirp_eta(t.mass1, t.mass2)[0]) self.hash_lookup = {} for i, p in enumerate(self.table): hash_value = hash((p.mass1, p.mass2, p.spin1z, p.spin2z)) self.hash_lookup[hash_value] = i
def _imrphenombfreq(**p): params = lalinspiral.InspiralTemplate() m1 = p['mass1'] m2 = p['mass2'] mc, et = pnutils.mass1_mass2_to_mchirp_eta(m1, m2) params.approximant = lalsimulation.IMRPhenomB params.fLower = p['f_lower'] params.eta = et params.distance = p['distance'] * lal.PC_SI * 1e6 params.mass1 = m1 params.mass2 = m2 params.spin1[2] = p['spin1z'] params.spin2[2] = p['spin2z'] params.startPhase = p['coa_phase'] * 2 - lal.PI params.startTime = 0 params.tSampling = 8192 N = int(params.tSampling / p['delta_f']) n = N / 2 # Create temporary memory to hold the results and call the generator hpt = zeros(N, dtype=float32) hct = zeros(N, dtype=float32) hpt = hpt.lal() hct = hct.lal() lalinspiral.BBHPhenWaveBFreqDomTemplates(hpt, hct, params) # Copy the results to a complex frequencyseries format hctc = FrequencySeries(zeros(n, dtype=complex64), delta_f=p['delta_f']) hptc = FrequencySeries(zeros(n, dtype=complex64), delta_f=p['delta_f']) hptc.data += hpt.data[0:n] hptc.data[1:n] += hpt.data[N:N - n:-1] * 1j hctc.data += hct.data[0:n] hctc.data[1:n] += hct.data[N:N - n:-1] * 1j return hptc.astype(complex128), hctc.astype(complex128)
def convert_to_sngl_inspiral_table(params, proc_id): ''' Convert a list of m1,m2,spin1z,spin2z values into a basic sngl_inspiral table with mass and spin parameters populated and event IDs assigned Parameters ----------- params : iterable Each entry in the params iterable should be a sequence of [mass1, mass2, spin1z, spin2z] in that order proc_id : ilwd char Process ID to add to each row of the sngl_inspiral table Returns ---------- SnglInspiralTable Bank of templates in SnglInspiralTable format ''' sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) col_names = ['mass1', 'mass2', 'spin1z', 'spin2z'] for values in params: tmplt = return_empty_sngl() tmplt.process_id = proc_id for colname, value in zip(col_names, values): setattr(tmplt, colname, value) tmplt.mtotal, tmplt.eta = pnutils.mass1_mass2_to_mtotal_eta( tmplt.mass1, tmplt.mass2) tmplt.mchirp, junk = pnutils.mass1_mass2_to_mchirp_eta( tmplt.mass1, tmplt.mass2) tmplt.template_duration = 0 # FIXME tmplt.event_id = sngl_inspiral_table.get_next_id() sngl_inspiral_table.append(tmplt) return sngl_inspiral_table
def __init__(self, ifos, coinc_results, **kwargs): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos participating in this trigger. coinc_results: dict of values A dictionary of values. The format is defined in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. psds: dict of FrequencySeries Dictionary providing PSD estimates for all involved detectors. low_frequency_cutoff: float Minimum valid frequency for the PSD estimates. high_frequency_cutoff: float, optional Maximum frequency considered for the PSD estimates. Default None. followup_data: dict of dicts, optional Dictionary providing SNR time series for each detector, to be used in sky localization with BAYESTAR. The format should be `followup_data['H1']['snr_series']`. More detectors can be present than given in `ifos`. If so, the extra detectors will only be used for sky localization. channel_names: dict of strings, optional Strain channel names for each detector Will be recorded in the sngl_inspiral table. padata: PAstroData instance, organizes info relevant to p astro. mc_area_args: dict of dicts, optional Dictionary providing arguments to be used in source probability estimation with pycbc/mchirp_area.py """ self.template_id = coinc_results['foreground/%s/template_id' % ifos[0]] self.coinc_results = coinc_results self.ifos = ifos self.basename = None # remember if this should be marked as HWINJ self.is_hardware_injection = ('HWINJ' in coinc_results and coinc_results['HWINJ']) # Check if we need to apply a time offset (this may be permerger) self.time_offset = 0 rtoff = 'foreground/{}/time_offset'.format(ifos[0]) if rtoff in coinc_results: self.time_offset = coinc_results[rtoff] if 'followup_data' in kwargs: fud = kwargs['followup_data'] assert len({fud[ifo]['snr_series'].delta_t for ifo in fud}) == 1, \ "delta_t for all ifos do not match" self.snr_series = {ifo: fud[ifo]['snr_series'] for ifo in fud} usable_ifos = fud.keys() followup_ifos = list(set(usable_ifos) - set(ifos)) for ifo in self.snr_series: self.snr_series[ifo].start_time += self.time_offset else: self.snr_series = None usable_ifos = ifos followup_ifos = [] # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) # FIXME is it safe (in terms of downstream operations) to let # `program_name` default to the actual script name? proc_id = create_process_table(outdoc, program_name='pycbc', detectors=usable_ifos).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(usable_ifos) coinc_event_row.instruments = ','.join(usable_ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_populated = None network_snrsq = 0 for sngl_id, ifo in enumerate(usable_ifos): sngl = return_empty_sngl(nones=True) sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.process_id = proc_id sngl.ifo = ifo names = [ n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n ] for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': val += self.time_offset sngl.end = lal.LIGOTimeGPS(val) else: try: setattr(sngl, name, val) except AttributeError: pass if sngl.mass1 and sngl.mass2: sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl_populated = sngl if sngl.snr: sngl.eff_distance = sngl.sigmasq**0.5 / sngl.snr network_snrsq += sngl.snr**2.0 if 'channel_names' in kwargs and ifo in kwargs['channel_names']: sngl.channel = kwargs['channel_names'][ifo] sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) if self.snr_series is not None: snr_series_to_xml(self.snr_series[ifo], outdoc, sngl.event_id) # Set merger time to the average of the ifo peaks self.merger_time = numpy.mean([ coinc_results['foreground/{}/end_time'.format(ifo)] for ifo in ifos ]) + self.time_offset # For subthreshold detectors, respect BAYESTAR's assumptions and checks bayestar_check_fields = ('mass1 mass2 mtotal mchirp eta spin1x ' 'spin1y spin1z spin2x spin2y spin2z').split() for sngl in sngl_inspiral_table: if sngl.ifo in followup_ifos: for bcf in bayestar_check_fields: setattr(sngl, bcf, getattr(sngl_populated, bcf)) sngl.end = lal.LIGOTimeGPS(self.merger_time) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.instruments = tuple(usable_ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_populated.mchirp coinc_inspiral_row.mass = sngl_populated.mtotal coinc_inspiral_row.end_time = sngl_populated.end_time coinc_inspiral_row.end_time_ns = sngl_populated.end_time_ns coinc_inspiral_row.snr = network_snrsq**0.5 far = 1.0 / (lal.YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) # Append the PSDs self.psds = kwargs['psds'] psds_lal = {} for ifo in self.psds: psd = self.psds[ifo] kmin = int(kwargs['low_frequency_cutoff'] / psd.delta_f) fseries = lal.CreateREAL8FrequencySeries( "psd", psd.epoch, kwargs['low_frequency_cutoff'], psd.delta_f, lal.StrainUnit**2 / lal.HertzUnit, len(psd) - kmin) fseries.data.data = psd.numpy()[kmin:] / pycbc.DYN_RANGE_FAC**2.0 psds_lal[ifo] = fseries make_psd_xmldoc(psds_lal, outdoc) # P astro calculation if 'padata' in kwargs: padata = kwargs['padata'] trigger_data = { 'mass1': sngl_populated.mass1, 'mass2': sngl_populated.mass2, 'spin1z': sngl_populated.spin1z, 'spin2z': sngl_populated.spin2z, 'network_snr': network_snrsq**0.5, 'far': far } horizons = {ifo: self.psds[ifo].dist for ifo in self.psds} self.p_astro, self.p_terr = \ padata.do_pastro_calc(trigger_data, horizons) else: self.p_astro, self.p_terr = None, None # Source probabilities estimation if 'mc_area_args' in kwargs: eff_distances = [sngl.eff_distance for sngl in sngl_inspiral_table] self.probabilities = calc_probabilities(coinc_inspiral_row.mchirp, coinc_inspiral_row.snr, min(eff_distances), kwargs['mc_area_args']) else: self.probabilities = None # Combine p astro and source probs if self.p_astro is not None and self.probabilities is not None: self.astro_probs = { cl: pr * self.p_astro for cl, pr in self.probabilities.items() } self.astro_probs['p_terr'] = self.p_terr else: self.astro_probs = None self.outdoc = outdoc self.time = sngl_populated.end
def get_td_waveform_resp(params): """ Generate time domain data of gw detector response This function will produce data of a gw detector response based on a numerical relativity waveform. Parameters ---------- params: object The fields of this object correspond to the kwargs of the `pycbc.waveform.get_td_waveform()` method and the positional arguments of `pycbc.detector.Detector.antenna_pattern()`. For the later the fields should be supplied as `params.ra`, `.dec`, `.polarization` and `.geocentric_end_time` Returns ------- h_plus: pycbc.Types.TimeSeries h_cross: pycbc.Types.TimeSeries pats: dictionary Dictionary containing 'H1' and 'L1' keys. Each key maps to an object of containing the field `.f_plus` and `.f_cross` corresponding to the plus and cross antenna patterns for the two ifos 'H1' and 'L1'. """ # # construct waveform string that can be parsed by lalsimulation waveform_string = params.approximant if not pn_orders[params.order] == -1: waveform_string += params.order name, phase_order = legacy_approximant_name(waveform_string) # Populate additional fields of params object params.mchirp, params.eta = pnutils.mass1_mass2_to_mchirp_eta( params.mass1, params.mass2) params.waveform = waveform_string params.approximant = name params.phase_order = phase_order # generate waveform h_plus, h_cross = get_td_waveform(params) # Generate antenna patterns for all ifos pats = {} for ifo in params.instruments: # get Detector instance for IFO det = Detector(ifo) # get antenna pattern f_plus, f_cross = det.antenna_pattern( params.ra, params.dec, params.polarization, params.geocentric_end_time) # Populate antenna patterns with new pattern pat = type('AntennaPattern', (object,), {}) pat.f_plus = f_plus pat.f_cross = f_cross pats[ifo] = pat return h_plus, h_cross, pats
def test_get_random_mass(self): # Want to do this for a variety of mass combinations for i in update_mass_parameters(self): curr_min_mass = self.min_total_mass curr_max_mass = self.max_total_mass try: pycbc.tmpltbank.verify_mass_range_options(self, parser=parser) except ValueError: # Some of the inputs are unphysical and will fail. # These cases are known to fail, the inputs are unphysical # 35 has inconsistent total mass and eta restrictions # 38 Component mass, [upper] chirp mass and [lower] eta limits # rule out the entire space. # 41 Same as 38 # 44 Same as 38 # 62 From component mass and total mass limits only total masses # between 7 and 7.5 are possible. This range all has eta # lower than the limit of 0.17. # 65 Same as 38 # 68 Same as 38 # 71 Same as 38 # 80 Same as 62 if i in [35,38,41,44,62,65,68,71,80]: continue raise # Check that if the mass limits have changed, it was right to do so # This is not exhaustive, but gets most things if not self.min_total_mass == curr_min_mass: min_comp_mass = self.min_mass1 + self.min_mass2 min_eta = self.min_mass1 * self.min_mass2 /\ (min_comp_mass * min_comp_mass) min_chirp_mass = min_comp_mass * min_eta**(3./5.) if self.min_total_mass == min_comp_mass: # Okay, the total mass is changed by the components pass elif min_eta < self.min_eta or min_eta > self.max_eta: # Okay, not possible from eta pass elif min_chirp_mass < self.min_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Minimum total mass changed unexpectedly." print self.min_total_mass, curr_min_mass print self.min_mass1, self.min_mass2, min_comp_mass print min_eta, self.min_eta, self.max_eta print min_chirp_mass, self.min_chirp_mass self.fail(err_msg) if not self.max_total_mass == curr_max_mass: max_comp_mass = self.max_mass1 + self.max_mass2 max_eta = self.max_mass1 * self.max_mass2 /\ (max_comp_mass * max_comp_mass) max_chirp_mass = max_comp_mass * max_eta**(3./5.) if self.max_total_mass == max_comp_mass: # Okay, the total mass is changed by the components pass elif max_eta < self.min_eta or max_eta > self.max_eta: # Okay, not possible from eta pass elif max_chirp_mass > self.max_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Maximum total mass changed unexpectedly." self.fail(err_msg) massRangeParams = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ ns_bh_boundary_mass=self.ns_bh_boundary_mass) # And again with the nsbh flag massRangeParams2 = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ nsbhFlag=True) mass,eta,beta,sigma,gamma,spin1z,spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams) errMsg = "pycbc.tmpltbank.get_random_mass returns invalid ranges." if (mass < self.min_total_mass).any(): idx = mass.argmin() diff = (mass*mass * (1-4*eta))**0.5 mass1 = (mass + diff)/2. mass2 = (mass - diff)/2. self.assertTrue(not (mass < self.min_total_mass).any(),msg=errMsg) self.assertTrue(not (mass > self.max_total_mass).any(),msg=errMsg) # Get individual masses diff = (mass*mass * (1-4*eta))**0.5 mass1 = (mass + diff)/2. mass2 = (mass - diff)/2. self.assertTrue(not (mass1 > self.max_mass1 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass1 < self.min_mass1 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass2 > self.max_mass2 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass2 < self.min_mass2 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass1 < mass2).any(),msg=errMsg) # Chirp mass and eta mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(mass1,mass2) if self.max_chirp_mass: self.assertTrue(not (mchirp > self.max_chirp_mass*1.0001).any(), msg=errMsg) if self.min_chirp_mass: self.assertTrue(not (mchirp < self.min_chirp_mass*0.9999).any(), msg=errMsg) if self.min_eta: self.assertTrue(not (eta < self.min_eta*0.9999).any(), msg=errMsg) self.assertTrue(not (eta > self.max_eta*1.0001).any(), msg=errMsg) nsSpin1 = spin1z[mass1 < self.ns_bh_boundary_mass] nsSpin2 = spin2z[mass2 < self.ns_bh_boundary_mass] bhSpin1 = spin1z[mass1 > self.ns_bh_boundary_mass] bhSpin2 = spin2z[mass2 > self.ns_bh_boundary_mass] self.assertTrue(not (abs(nsSpin1) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(nsSpin2) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin1) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin2) > 0.9).any(), msg=errMsg) # Check that *some* spins are bigger than 0.5 if len(bhSpin1): self.assertTrue((abs(bhSpin1) > 0.5).any(), msg=errMsg) if len(bhSpin2): self.assertTrue((abs(bhSpin2) > 0.5).any(), msg=errMsg) # This can be used to test the boundaries are all applied visually # FIXME: This would need to be updated for all of the mass limits #pylab.plot(mass1, mass2, 'b.') #pylab.plot([3.0,5.0],[3.0,1.0],'r-') #pylab.plot([1.7216566400945545,1.9921146662296347,3.4433132801891091,4.01175560949798],[1.1477710933963694,1.0066274466204264,2.2955421867927388,1.002938902374495],'mx') #pylab.ylim([0.8,3.0]) #pylab.xlim([1.5,5.0]) #pylab.savefig("masses_%d.png" %(idx,)) # Check nsbh flag mass,eta,beta,sigma,gamma,spin1z,spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams2) self.assertTrue(not (abs(spin1z) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(spin2z) > 0.5).any(), msg=errMsg) self.assertTrue((abs(spin1z) > 0.5).any(), msg=errMsg)
""" xmldoc = ligolw.Document() xmldoc.appendChild(ligolw.LIGO_LW()) for table in tables: xmldoc.childNodes[0].appendChild(table) return xmldoc input_bank = 'H1L1-UBERBANK_MAXM100_NS0p05_ER8HMPSD-1126033217-223200.xml.gz' output_bank = 'H1L1-EDGEBIN_FROM_UBERBANK_ER8HMPSD-1126033217-223200.xml.gz' xmldoc = utils.load_filename(input_bank, contenthandler=LIGOLWContentHandler, gz=True) all_templates = table.get_table(xmldoc, 'sngl_inspiral') # get the other tables that are in the document other_table_names = [y.Name for y in xmldoc.childNodes[0].getElements( lambda x: x.tagName == ligolw.Table.tagName) if y.Name != u'sngl_inspiral'] other_tables = [table.get_table(xmldoc, x) for x in other_table_names] keep_templates = lsctables.New(lsctables.SnglInspiralTable) # only add templates that fall in the edge bin for tmplt in all_templates: mchirp = pnutils.mass1_mass2_to_mchirp_eta(tmplt.mass1, tmplt.mass2)[0] peakfreq = pnutils.get_freq('fSEOBNRv2Peak', tmplt.mass1, tmplt.mass2, tmplt.spin1z, tmplt.spin2z) if mchirp >= 1.74 and peakfreq < 220.: keep_templates.append(tmplt) outdoc = create_xmldoc(other_tables + [keep_templates]) utils.write_filename(outdoc, output_bank, gz=True)
def writeHybrid_h5(path_name_part, metadata, approx, sim_name, h1, h1_ts, h2, h2_ts, delta_t, ip2, fp2): solar_mass_mpc = MRSUN_SI / ((1 * 10**6) * PC_SI) grav_m1 = metadata[0][0] grav_m2 = metadata[0][1] baryon_m1 = metadata[1][0] baryon_m2 = metadata[1][1] m1 = metadata[2][0] m2 = metadata[2][1] s1x = metadata[3][0] s1y = metadata[3][1] s1z = metadata[3][2] s2x = metadata[3][3] s2y = metadata[3][4] s2z = metadata[3][5] LNhatx = metadata[4][0] LNhaty = metadata[4][1] LNhatz = metadata[4][2] n_hatx = 1.0 #metadata[5][0] n_haty = 0.0 #metadata[5][1] n_hatz = 0.0 #metadata[5][2] tidal_1 = metadata[6][0] tidal_2 = metadata[6][1] type_sim = metadata[7] f_low = metadata[8] EOS = metadata[9] f_low_num = metadata[10] M = 300 ## length of the windowing function total_mass = grav_m1 + grav_m2 ### used masses are the masses used in the characterization procedure ### hybridize numerical (h2) and analytical waveform (h1) at a particular match window length set by fp2 hybridPN_Num = hy.hybridize(h1, h1_ts, h2, h2_ts, match_i=0, match_f=fp2, delta_t=delta_t, M=M, info=1) shift_time = (hybridPN_Num[6], fp2) hh_freq = (hybridPN_Num[7], fp2) match = hybridPN_Num[0] ### path_name_part contains simulation details that must be passed into this function. path_name = path_name_part + 'fp2_' + str(fp2) + '.h5' f_low_M = f_low * (TWOPI * total_mass * MTSUN_SI) with h5py.File(path_name, 'w') as fd: mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(grav_m1, grav_m2) fd.attrs['type'] = 'Hybrid:%s' % type_sim fd.attrs['hgroup'] = 'Read_CSUF' fd.attrs['Format'] = 1 fd.attrs['Lmax'] = 2 fd.attrs['approx'] = approx fd.attrs['sim_name'] = sim_name fd.attrs['f_lower_at_1MSUN'] = f_low fd.attrs['eta'] = eta fd.attrs['spin1x'] = s1x fd.attrs['spin1y'] = s1y fd.attrs['spin1z'] = s1z fd.attrs['spin2x'] = s2x fd.attrs['spin2y'] = s2y fd.attrs['spin2z'] = s2z fd.attrs['LNhatx'] = LNhatx fd.attrs['LNhaty'] = LNhaty fd.attrs['LNhatz'] = LNhatz fd.attrs['nhatx'] = 1.0 #n_hatx fd.attrs['nhaty'] = 0.0 #n_haty fd.attrs['nhatz'] = 0.0 #n_hatz fd.attrs['mass1'] = m1 fd.attrs['mass2'] = m2 fd.attrs['grav_mass1'] = grav_m1 fd.attrs['grav_mass2'] = grav_m2 fd.attrs['baryon_mass1'] = baryon_m1 fd.attrs['baryon_mass2'] = baryon_m2 fd.attrs['lambda1'] = tidal_1 fd.attrs['lambda2'] = tidal_2 fd.attrs['fp1'] = len(h1) fd.attrs['ip2'] = ip2 fd.attrs['hybrid_match'] = match fd.attrs['shift_time'] = shift_time fd.attrs['hybridize_freq'] = hh_freq fd.attrs['EOS'] = EOS fd.attrs['f_low_num'] = f_low_num gramp = fd.create_group('amp_l2_m2') grphase = fd.create_group('phase_l2_m2') times = hybridPN_Num[5][0] hplus = hybridPN_Num[5][1] hcross = hybridPN_Num[5][2] massMpc = total_mass * solar_mass_mpc hplusMpc = pycbc.types.TimeSeries(hplus / massMpc, delta_t=delta_t) hcrossMpc = pycbc.types.TimeSeries(hcross / massMpc, delta_t=delta_t) times_M = times / (MTSUN_SI * total_mass) HlmAmp = wfutils.amplitude_from_polarizations(hplusMpc, hcrossMpc).data HlmPhase = wfutils.phase_from_polarizations(hplusMpc, hcrossMpc).data sAmph = romspline.ReducedOrderSpline(times_M, HlmAmp, rel=True, verbose=False) sPhaseh = romspline.ReducedOrderSpline(times_M, HlmPhase, rel=True, verbose=False) sAmph.write(gramp) sPhaseh.write(grphase) fd.close() ## this function returns the hybridization frequency (hh_freq) and the time shift (shift_time) associated with each hybrid. return (shift_time, hh_freq)
def __init__(self, ifos, coinc_results, **kwargs): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is defined in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. psds: dict of FrequencySeries Dictionary providing PSD estimates for all involved detectors. low_frequency_cutoff: float Minimum valid frequency for the PSD estimates. followup_data: dict of dicts, optional Dictionary providing SNR time series for each detector, to be used in sky localization with BAYESTAR. The format should be `followup_data['H1']['snr_series']`. More detectors can be present than given in `ifos`. If so, the extra detectors will only be used for sky localization. channel_names: dict of strings, optional Strain channel names for each detector. Will be recorded in the sngl_inspiral table. """ self.template_id = coinc_results['foreground/%s/template_id' % ifos[0]] self.coinc_results = coinc_results self.ifos = ifos # remember if this should be marked as HWINJ self.is_hardware_injection = ('HWINJ' in coinc_results and coinc_results['HWINJ']) if 'followup_data' in kwargs: fud = kwargs['followup_data'] assert len({fud[ifo]['snr_series'].delta_t for ifo in fud}) == 1, \ "delta_t for all ifos do not match" self.snr_series = {ifo: fud[ifo]['snr_series'] for ifo in fud} usable_ifos = fud.keys() followup_ifos = list(set(usable_ifos) - set(ifos)) else: self.snr_series = None usable_ifos = ifos followup_ifos = [] # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=usable_ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/'+pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(usable_ifos) coinc_event_row.instruments = ','.join(usable_ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_populated = None network_snrsq = 0 for sngl_id, ifo in enumerate(usable_ifos): sngl = return_empty_sngl(nones=True) sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.process_id = proc_id sngl.ifo = ifo names = [n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n] for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(lal.LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass if sngl.mass1 and sngl.mass2: sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl_populated = sngl if sngl.snr: sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr network_snrsq += sngl.snr ** 2.0 if 'channel_names' in kwargs and ifo in kwargs['channel_names']: sngl.channel = kwargs['channel_names'][ifo] sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) if self.snr_series is not None: snr_series_to_xml(self.snr_series[ifo], outdoc, sngl.event_id) # for subthreshold detectors, respect BAYESTAR's assumptions and checks bayestar_check_fields = ('mass1 mass2 mtotal mchirp eta spin1x ' 'spin1y spin1z spin2x spin2y spin2z').split() subthreshold_sngl_time = numpy.mean( [coinc_results['foreground/{}/end_time'.format(ifo)] for ifo in ifos]) for sngl in sngl_inspiral_table: if sngl.ifo in followup_ifos: for bcf in bayestar_check_fields: setattr(sngl, bcf, getattr(sngl_populated, bcf)) sngl.set_end(lal.LIGOTimeGPS(subthreshold_sngl_time)) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(usable_ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_populated.mchirp coinc_inspiral_row.mass = sngl_populated.mtotal coinc_inspiral_row.end_time = sngl_populated.end_time coinc_inspiral_row.end_time_ns = sngl_populated.end_time_ns coinc_inspiral_row.snr = network_snrsq ** 0.5 far = 1.0 / (lal.YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) # append the PSDs self.psds = kwargs['psds'] psds_lal = {} for ifo in self.psds: psd = self.psds[ifo] kmin = int(kwargs['low_frequency_cutoff'] / psd.delta_f) fseries = lal.CreateREAL8FrequencySeries( "psd", psd.epoch, kwargs['low_frequency_cutoff'], psd.delta_f, lal.StrainUnit**2 / lal.HertzUnit, len(psd) - kmin) fseries.data.data = psd.numpy()[kmin:] / pycbc.DYN_RANGE_FAC ** 2.0 psds_lal[ifo] = fseries make_psd_xmldoc(psds_lal, outdoc) self.outdoc = outdoc self.time = sngl_populated.get_end()
out_left2 = time[l:r] < (time[l:r][idx_mxsnr] - 0.1) out_left = time[l:r][numpy.invert( (out_left1 - out_left2))].shape[0] out_right1 = time[l:r] <= (time[l:r][idx_mxsnr] + int(args.window)) out_right2 = time[l:r] > (time[l:r][idx_mxsnr] + 0.1) out_right = time[l:r][numpy.invert( (out_right1 - out_right2))].shape[0] count_out.append(out_left + out_right) #determining the chirp mass m1_snr = mass1_full[l:r][idx_mxsnr] m2_snr = mass2_full[l:r][idx_mxsnr] m1_new_snr = mass1_full[l:r][idx_mxnewsnr] m2_new_snr = mass2_full[l:r][idx_mxnewsnr] chirp_snr = pnutils.mass1_mass2_to_mchirp_eta( m1_snr, m2_snr) chirp_m.append(chirp_snr) chirp_new_snr = pnutils.mass1_mass2_to_mchirp_eta( m1_new_snr, m2_new_snr) #Calculating delta chirp and ratio of chirp masses delta_chirp.append( log(chirp_snr[0]) - log(chirp_new_snr[0])) ratio_chirp.append(chirp_snr[0] / chirp_new_snr[0]) for i, (l, r) in enumerate(zip(left_inj, right_inj)): logging.info('%s: %2.1f complete', ifo, float(i) / len(right_inj) * 100) closest_inj_id = numpy.argmin(abs(time_injc - window_times[i])) closest_injt = time_injc[closest_inj_id]
def __init__(self, ifos, coinc_results, **kwargs): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is defined in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. """ followup_ifos = kwargs.get('followup_ifos') or [] self.template_id = coinc_results['foreground/%s/template_id' % ifos[0]] # remember if this should be marked as HWINJ self.is_hardware_injection = ('HWINJ' in coinc_results) # remember if we want to use a non-standard gracedb server self.gracedb_server = kwargs.get('gracedb_server') # compute SNR time series if needed, and figure out which of # the followup detectors are usable subthreshold_sngl_time = numpy.mean( [coinc_results['foreground/%s/end_time' % ifo] for ifo in ifos]) self.upload_snr_series = kwargs.get('upload_snr_series') usable_ifos = [] if self.upload_snr_series: self.snr_series = {} self.snr_series_psd = {} htilde = kwargs['bank'][self.template_id] for ifo in ifos + followup_ifos: if ifo in ifos: trig_time = coinc_results['foreground/%s/end_time' % ifo] else: trig_time = subthreshold_sngl_time # NOTE we only check the state/DQ of followup IFOs here. # IFOs producing the coincidence are assumed to also # produce valid SNR series. snr_series, snr_series_psd = compute_followup_snr_series( kwargs['data_readers'][ifo], htilde, trig_time, check_state=(ifo in followup_ifos)) if snr_series is not None: self.snr_series[ifo] = snr_series self.snr_series_psd[ifo] = snr_series_psd usable_ifos.append(ifo) else: usable_ifos = ifos # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=usable_ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/'+pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(usable_ifos) coinc_event_row.instruments = ','.join(usable_ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_populated = None for sngl_id, ifo in enumerate(usable_ifos): sngl = return_empty_sngl(nones=True) sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.process_id = proc_id sngl.ifo = ifo names = [n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n] for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(lal.LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass if sngl.mass1 and sngl.mass2: sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl_populated = sngl if sngl.snr: sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) if self.upload_snr_series: snr_series_to_xml(self.snr_series[ifo], outdoc, sngl.event_id) # for subthreshold detectors, respect BAYESTAR's assumptions and checks bayestar_check_fields = ('mass1 mass2 mtotal mchirp eta spin1x ' 'spin1y spin1z spin2x spin2y spin2z').split() for sngl in sngl_inspiral_table: if sngl.ifo in followup_ifos: for bcf in bayestar_check_fields: setattr(sngl, bcf, getattr(sngl_populated, bcf)) sngl.set_end(lal.LIGOTimeGPS(subthreshold_sngl_time)) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(usable_ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_populated.mchirp coinc_inspiral_row.mass = sngl_populated.mtotal coinc_inspiral_row.end_time = sngl_populated.end_time coinc_inspiral_row.end_time_ns = sngl_populated.end_time_ns coinc_inspiral_row.snr = coinc_results['foreground/stat'] far = 1.0 / (lal.YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) self.outdoc = outdoc self.time = sngl_populated.get_end()
def test_get_random_mass(self): # Want to do this for a variety of mass combinations for i in update_mass_parameters(self): curr_min_mass = self.min_total_mass curr_max_mass = self.max_total_mass try: pycbc.tmpltbank.verify_mass_range_options(self, parser=parser) except ValueError: # Some of the inputs are unphysical and will fail. # These cases are known to fail, the inputs are unphysical # 35 has inconsistent total mass and eta restrictions # 38 Component mass, [upper] chirp mass and [lower] eta limits # rule out the entire space. # 41 Same as 38 # 44 Same as 38 # 62 From component mass and total mass limits only total masses # between 7 and 7.5 are possible. This range all has eta # lower than the limit of 0.17. # 65 Same as 38 # 68 Same as 38 # 71 Same as 38 # 80 Same as 62 if i in [35,38,41,44,62,65,68,71,80]: continue raise # Check that if the mass limits have changed, it was right to do so # This is not exhaustive, but gets most things if not self.min_total_mass == curr_min_mass: min_comp_mass = self.min_mass1 + self.min_mass2 min_eta = self.min_mass1 * self.min_mass2 /\ (min_comp_mass * min_comp_mass) min_chirp_mass = min_comp_mass * min_eta**(3./5.) if self.min_total_mass == min_comp_mass: # Okay, the total mass is changed by the components pass elif min_eta < self.min_eta or min_eta > self.max_eta: # Okay, not possible from eta pass elif min_chirp_mass < self.min_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Minimum total mass changed unexpectedly." print(self.min_total_mass, curr_min_mass) print(self.min_mass1, self.min_mass2, min_comp_mass) print(min_eta, self.min_eta, self.max_eta) print(min_chirp_mass, self.min_chirp_mass) self.fail(err_msg) if not self.max_total_mass == curr_max_mass: max_comp_mass = self.max_mass1 + self.max_mass2 max_eta = self.max_mass1 * self.max_mass2 /\ (max_comp_mass * max_comp_mass) max_chirp_mass = max_comp_mass * max_eta**(3./5.) if self.max_total_mass == max_comp_mass: # Okay, the total mass is changed by the components pass elif max_eta < self.min_eta or max_eta > self.max_eta: # Okay, not possible from eta pass elif max_chirp_mass > self.max_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Maximum total mass changed unexpectedly." self.fail(err_msg) massRangeParams = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ ns_bh_boundary_mass=self.ns_bh_boundary_mass) # And again with the nsbh flag massRangeParams2 = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ nsbhFlag=True) mass1, mass2, spin1z, spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams) mass = mass1 + mass2 errMsg = "pycbc.tmpltbank.get_random_mass returns invalid ranges." self.assertTrue(not (mass < self.min_total_mass).any(),msg=errMsg) self.assertTrue(not (mass > self.max_total_mass).any(),msg=errMsg) self.assertTrue(not (mass1 > self.max_mass1 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass1 < self.min_mass1 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass2 > self.max_mass2 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass2 < self.min_mass2 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass1 < mass2).any(),msg=errMsg) # Chirp mass and eta mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(mass1,mass2) if self.max_chirp_mass: self.assertTrue(not (mchirp > self.max_chirp_mass*1.0001).any(), msg=errMsg) if self.min_chirp_mass: self.assertTrue(not (mchirp < self.min_chirp_mass*0.9999).any(), msg=errMsg) if self.min_eta: self.assertTrue(not (eta < self.min_eta*0.9999).any(), msg=errMsg) self.assertTrue(not (eta > self.max_eta*1.0001).any(), msg=errMsg) nsSpin1 = spin1z[mass1 < self.ns_bh_boundary_mass] nsSpin2 = spin2z[mass2 < self.ns_bh_boundary_mass] bhSpin1 = spin1z[mass1 > self.ns_bh_boundary_mass] bhSpin2 = spin2z[mass2 > self.ns_bh_boundary_mass] self.assertTrue(not (abs(nsSpin1) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(nsSpin2) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin1) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin2) > 0.9).any(), msg=errMsg) # Check that *some* spins are bigger than 0.5 if len(bhSpin1): self.assertTrue((abs(bhSpin1) > 0.5).any(), msg=errMsg) if len(bhSpin2): self.assertTrue((abs(bhSpin2) > 0.5).any(), msg=errMsg) # Check nsbh flag mass1, mass2, spin1z, spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams2) self.assertTrue(not (abs(spin1z) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(spin2z) > 0.5).any(), msg=errMsg) self.assertTrue((abs(spin1z) > 0.5).any(), msg=errMsg)
def __init__(self, ifos, coinc_results, **kwargs): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is define in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. """ self.ifos = ifos self.template_id = coinc_results['foreground/%s/template_id' % self.ifos[0]] # remember if this should be marked as HWINJ self.is_hardware_injection = False if 'HWINJ' in coinc_results: self.is_hardware_injection = True # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/' + pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ','.join(ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_id = 0 sngl_event_id_map = {} for ifo in ifos: names = [ n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n ] sngl_id += 1 sngl = return_empty_sngl() sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl_event_id_map[ifo] = sngl.event_id sngl.ifo = ifo for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(lal.LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl.mchirp coinc_inspiral_row.mass = sngl.mtotal coinc_inspiral_row.end_time = sngl.end_time coinc_inspiral_row.end_time_ns = sngl.end_time_ns coinc_inspiral_row.snr = coinc_results['foreground/stat'] far = 1.0 / (lal.YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) self.outdoc = outdoc self.time = sngl.get_end() # compute SNR time series self.upload_snr_series = kwargs['upload_snr_series'] if self.upload_snr_series: data_readers = kwargs['data_readers'] bank = kwargs['bank'] htilde = bank[self.template_id] self.snr_series = {} self.snr_series_psd = {} for ifo in self.ifos: stilde = data_readers[ifo].overwhitened_data(htilde.delta_f) norm = 4.0 * htilde.delta_f / (htilde.sigmasq(stilde.psd)**0.5) qtilde = zeros((len(htilde) - 1) * 2, dtype=htilde.dtype) correlate(htilde, stilde, qtilde) snr = qtilde * 0 ifft(qtilde, snr) valid_end = int(len(qtilde) - data_readers[ifo].trim_padding) valid_start = int(valid_end - data_readers[ifo].blocksize * data_readers[ifo].sample_rate) seg = slice(valid_start, valid_end) snr = snr[seg] snr *= norm delta_t = 1.0 / data_readers[ifo].sample_rate start = data_readers[ifo].start_time snr = TimeSeries(snr, delta_t=delta_t, epoch=start) self.snr_series[ifo] = snr self.snr_series_psd[ifo] = stilde.psd # store the on-source slice of the series into the XML doc snr_onsource_time = coinc_results['foreground/%s/end_time' % ifo] - snr.start_time snr_onsource_dur = lal.REARTH_SI / lal.C_SI onsource_idx = round(snr_onsource_time * snr.sample_rate) onsource_start = onsource_idx - int( snr.sample_rate * snr_onsource_dur / 2) onsource_end = onsource_idx + int( snr.sample_rate * snr_onsource_dur / 2) onsource_slice = slice(onsource_start, onsource_end + 1) snr_lal = snr[onsource_slice].lal() snr_lal.name = 'snr' snr_lal.sampleUnits = '' snr_xml = _build_series(snr_lal, (u'Time', u'Time,Real,Imaginary'), None, 'deltaT', 's') snr_node = outdoc.childNodes[-1].appendChild(snr_xml) eid_param = ligolw_param.new_param( u'event_id', u'ilwd:char', unicode(sngl_event_id_map[ifo])) snr_node.appendChild(eid_param)
def __init__(self, ifos, coinc_results): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is define in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. """ # remember if this should be marked as HWINJ self.is_hardware_injection = False if 'HWINJ' in coinc_results: self.is_hardware_injection = True # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/' + pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ','.join(ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_id = 0 for ifo in ifos: names = [ n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n ] sngl_id += 1 sngl = return_empty_sngl() sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.ifo = ifo for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl.mchirp coinc_inspiral_row.mass = sngl.mtotal coinc_inspiral_row.end_time = sngl.end_time coinc_inspiral_row.end_time_ns = sngl.end_time_ns coinc_inspiral_row.snr = coinc_results['foreground/stat'] far = 1.0 / (YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) self.outdoc = outdoc
best_chirp_mass = np.zeros(len(results_data)) sigma_best_match = np.zeros(len(results_data)) sigma_best_mass = np.zeros(len(results_data)) sigma_best_chirp_mass = np.zeros(len(results_data)) best_a1dotL = np.zeros(len(results_data)) best_a2dotL = np.zeros(len(results_data)) best_mass_ratio = np.zeros(len(results_data)) for d,data in enumerate(results_data): results_file = os.path.join(data[0], data[0]+'_'+sys.argv[2]+'.pickle') injected_mass[d] = float(data[1])+float(data[2]) injected_chirp_mass[d], injected_eta = pnutils.mass1_mass2_to_mchirp_eta( float(data[1]),float(data[2])) injected_a1z[d] = float(data[3]) injected_a2z[d] = float(data[4]) matches, masses, inclinations, config, simulations, _, _, _ = pickle.load( open(results_file, 'rb')) # Label figures according to the pickle file if opts.user_tag is None: user_tag=results_file.replace('.pickle','') # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Manipulation and derived FOMs #
def mchirp(self): mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( self.mass1, self.mass2) return mchirp
def to_coinc_xml_object(self, file_name): # FIXME: This function will only work with two ifos!! outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) ifos = [ifo for ifo in self.sngl_files.keys()] proc_id = ligolw_process.register_to_xmldoc( outdoc, "pycbc", {}, ifos=ifos, comment="", version=pycbc_version.git_hash, cvs_repository="pycbc/" + pycbc_version.git_branch, cvs_entry_time=pycbc_version.date, ).process_id search_summ_table = lsctables.New(lsctables.SearchSummaryTable) coinc_h5file = self.coinc_file.h5file start_time = coinc_h5file["segments"]["coinc"]["start"][:].min() end_time = coinc_h5file["segments"]["coinc"]["end"][:].max() num_trigs = len(self.sort_arr) search_summary = return_search_summary(start_time, end_time, num_trigs, ifos) search_summ_table.append(search_summary) outdoc.childNodes[0].appendChild(search_summ_table) sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) time_slide_table = lsctables.New(lsctables.TimeSlideTable) # Set up time_slide table time_slide_id = lsctables.TimeSlideID(0) for ifo in ifos: time_slide_row = lsctables.TimeSlide() time_slide_row.instrument = ifo time_slide_row.time_slide_id = time_slide_id time_slide_row.offset = 0 time_slide_row.process_id = proc_id time_slide_table.append(time_slide_row) # Set up coinc_definer table coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral-sngl_inspiral coincidences" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) bank_col_names = ["mass1", "mass2", "spin1z", "spin2z"] bank_col_vals = {} for name in bank_col_names: bank_col_vals[name] = self.get_bankfile_array(name) coinc_event_names = ["ifar", "time1", "fap", "stat"] coinc_event_vals = {} for name in coinc_event_names: coinc_event_vals[name] = self.get_coincfile_array(name) sngl_col_names = [ "snr", "chisq", "chisq_dof", "bank_chisq", "bank_chisq_dof", "cont_chisq", "cont_chisq_dof", "end_time", "template_duration", "coa_phase", "sigmasq", ] sngl_col_vals = {} for name in sngl_col_names: sngl_col_vals[name] = self.get_snglfile_array_dict(name) for idx, coinc_idx in enumerate(self.sort_arr): # Set up IDs and mapping values curr_tmplt_id = self.template_id[idx] coinc_id = lsctables.CoincID(idx) # Set up sngls # FIXME: As two-ifo is hardcoded loop over all ifos sngl_combined_mchirp = 0 sngl_combined_mtot = 0 for ifo in ifos: sngl_id = self.trig_id[ifo][idx] event_id = lsctables.SnglInspiralID(sngl_id) sngl = return_empty_sngl() sngl.event_id = event_id sngl.ifo = ifo curr_sngl_file = self.sngl_files[ifo].h5file[ifo] for name in sngl_col_names: val = sngl_col_vals[name][ifo][idx] setattr(sngl, name, val) for name in bank_col_names: val = bank_col_vals[name][idx] setattr(sngl, name, val) sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta(sngl.mass1, sngl.mass2) sngl.mchirp, junk = pnutils.mass1_mass2_to_mchirp_eta(sngl.mass1, sngl.mass2) sngl.eff_distance = (sngl.sigmasq) ** 0.5 / sngl.snr sngl_combined_mchirp += sngl.mchirp sngl_combined_mtot += sngl.mtotal sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = "sngl_inspiral" coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = event_id coinc_event_map_table.append(coinc_map_row) sngl_combined_mchirp = sngl_combined_mchirp / len(ifos) sngl_combined_mtot = sngl_combined_mtot / len(ifos) # Set up coinc inspiral and coinc event tables coinc_event_row = lsctables.Coinc() coinc_inspiral_row = lsctables.CoincInspiral() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ",".join(ifos) coinc_inspiral_row.set_ifos(ifos) coinc_event_row.time_slide_id = time_slide_id coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_combined_mchirp coinc_inspiral_row.mass = sngl_combined_mtot coinc_inspiral_row.set_end(LIGOTimeGPS(coinc_event_vals["time1"][idx])) coinc_inspiral_row.snr = coinc_event_vals["stat"][idx] coinc_inspiral_row.false_alarm_rate = coinc_event_vals["fap"][idx] coinc_inspiral_row.combined_far = 1.0 / coinc_event_vals["ifar"][idx] # Transform to Hz coinc_inspiral_row.combined_far = coinc_inspiral_row.combined_far / YRJUL_SI coinc_event_row.likelihood = 0.0 coinc_inspiral_row.minimum_duration = 0.0 coinc_event_table.append(coinc_event_row) coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_def_table) outdoc.childNodes[0].appendChild(coinc_event_table) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(time_slide_table) outdoc.childNodes[0].appendChild(coinc_inspiral_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) ligolw_utils.write_filename(outdoc, file_name)
def mchirp(self): mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta(self.mass1, self.mass2) return mchirp
def test_get_random_mass(self): # Want to do this for a variety of mass combinations for i in update_mass_parameters(self): curr_min_mass = self.min_total_mass curr_max_mass = self.max_total_mass try: pycbc.tmpltbank.verify_mass_range_options(self, parser=parser) except ValueError: # Some of the inputs are unphysical and will fail. # These cases are known to fail, the inputs are unphysical # 35 has inconsistent total mass and eta restrictions # 38 Component mass, [upper] chirp mass and [lower] eta limits # rule out the entire space. # 41 Same as 38 # 44 Same as 38 # 62 From component mass and total mass limits only total masses # between 7 and 7.5 are possible. This range all has eta # lower than the limit of 0.17. # 65 Same as 38 # 68 Same as 38 # 71 Same as 38 # 80 Same as 62 if i in [35, 38, 41, 44, 62, 65, 68, 71, 80]: continue raise # Check that if the mass limits have changed, it was right to do so # This is not exhaustive, but gets most things if (curr_min_mass is None) or \ not math.isclose(self.min_total_mass, curr_min_mass, rel_tol=1e-06): min_comp_mass = self.min_mass1 + self.min_mass2 min_eta = self.min_mass1 * self.min_mass2 /\ (min_comp_mass * min_comp_mass) min_chirp_mass = min_comp_mass * min_eta**(3. / 5.) if (min_comp_mass is not None) and \ math.isclose(self.min_total_mass, min_comp_mass, rel_tol=1e-06): # Okay, the total mass is changed by the components pass elif (self.min_eta and min_eta < self.min_eta) or \ (self.max_eta and min_eta > self.max_eta): # Okay, not possible from eta pass elif self.min_chirp_mass and \ min_chirp_mass < self.min_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Minimum total mass changed unexpectedly." self.fail(err_msg) if (curr_max_mass is None) or \ not math.isclose(self.max_total_mass, curr_max_mass, rel_tol=1e-06): max_comp_mass = self.max_mass1 + self.max_mass2 max_eta = self.max_mass1 * self.max_mass2 /\ (max_comp_mass * max_comp_mass) max_chirp_mass = max_comp_mass * max_eta**(3. / 5.) if (max_comp_mass is not None) and \ math.isclose(self.max_total_mass, max_comp_mass, rel_tol=1e-06): # Okay, the total mass is changed by the components pass elif (self.min_eta and max_eta < self.min_eta) or\ (self.max_eta and max_eta > self.max_eta): # Okay, not possible from eta pass elif self.max_chirp_mass and \ max_chirp_mass > self.max_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Maximum total mass changed unexpectedly." self.fail(err_msg) massRangeParams = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ ns_bh_boundary_mass=self.ns_bh_boundary_mass) # And again with the nsbh flag massRangeParams2 = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ nsbhFlag=True) mass1, mass2, spin1z, spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams) mass = mass1 + mass2 errMsg = "pycbc.tmpltbank.get_random_mass returns invalid ranges." self.assertTrue(not (mass < self.min_total_mass).any(), msg=errMsg) self.assertTrue(not (mass > self.max_total_mass).any(), msg=errMsg) self.assertTrue(not (mass1 > self.max_mass1 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass1 < self.min_mass1 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass2 > self.max_mass2 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass2 < self.min_mass2 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass1 < mass2).any(), msg=errMsg) # Chirp mass and eta mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(mass1, mass2) if self.max_chirp_mass: self.assertTrue( not (mchirp > self.max_chirp_mass * 1.0001).any(), msg=errMsg) if self.min_chirp_mass: self.assertTrue( not (mchirp < self.min_chirp_mass * 0.9999).any(), msg=errMsg) if self.min_eta: self.assertTrue(not (eta < self.min_eta * 0.9999).any(), msg=errMsg) self.assertTrue(not (eta > self.max_eta * 1.0001).any(), msg=errMsg) nsSpin1 = spin1z[mass1 < self.ns_bh_boundary_mass] nsSpin2 = spin2z[mass2 < self.ns_bh_boundary_mass] bhSpin1 = spin1z[mass1 > self.ns_bh_boundary_mass] bhSpin2 = spin2z[mass2 > self.ns_bh_boundary_mass] self.assertTrue(not (abs(nsSpin1) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(nsSpin2) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin1) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin2) > 0.9).any(), msg=errMsg) # Check that *some* spins are bigger than 0.5 if len(bhSpin1): self.assertTrue((abs(bhSpin1) > 0.5).any(), msg=errMsg) if len(bhSpin2): self.assertTrue((abs(bhSpin2) > 0.5).any(), msg=errMsg) # Check nsbh flag mass1, mass2, spin1z, spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams2) self.assertTrue(not (abs(spin1z) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(spin2z) > 0.5).any(), msg=errMsg) self.assertTrue((abs(spin1z) > 0.5).any(), msg=errMsg)
def eta(self): _, eta = pnutils.mass1_mass2_to_mchirp_eta(self.mass1, self.mass2) return eta
times, strainVal1, strainVal2 = np.loadtxt(datafile, usecols=(0, 1, 2), unpack=True) # run conversion functions for correct PyCBC conventions grav_mass1, grav_mass2 = convert_mass(massFormat, grav_mass1, grav_mass2, total_grav_mass) strainVal1, strainVal2 = convert_strain(strainFormat, strainVal1, strainVal2, total_grav_mass) times = convert_time(timeFormat, times, total_grav_mass) with h5py.File(h5file, 'w') as fd: # Set metadata # still need to add values for love number, radius, lambda, etc. mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta( grav_mass1, grav_mass2) fd.attrs.create('NR_group', 'CSUF_GWPAC_NS') fd.attrs.create('sim_name', 'Deitrich') fd.attrs.create('EOS', 'ALF2') hashtag = hashlib.md5() fd.attrs.create('type', 'BNS') hashtag.update(fd.attrs['type']) fd.attrs.create('hashtag', hashtag.digest()) fd.attrs.create('Format', 1) fd.attrs.create('f_lower_at_1MSUN', f_lower) fd.attrs.create('eta', eta) fd.attrs.create('spin1x', spin1x) fd.attrs.create('spin1y', spin1y) fd.attrs.create('spin1z', spin1z) fd.attrs.create('spin2x', spin2x) fd.attrs.create('spin2y', spin2y)
def __init__(self, ifos, coinc_results): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is define in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. """ # remember if this should be marked as HWINJ self.is_hardware_injection = False if 'HWINJ' in coinc_results: self.is_hardware_injection = True # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/'+pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ','.join(ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_id = 0 for ifo in ifos: names = [n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n] sngl_id += 1 sngl = return_empty_sngl() sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.ifo = ifo for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl.mchirp coinc_inspiral_row.mass = sngl.mtotal coinc_inspiral_row.end_time = sngl.end_time coinc_inspiral_row.end_time_ns = sngl.end_time_ns coinc_inspiral_row.snr = coinc_results['foreground/stat'] far = 1.0 / (YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) self.outdoc = outdoc
def eta(self): mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(self.mass1, self.mass2) return eta
def to_coinc_xml_object(self, file_name): outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) ifos = list(self.sngl_files.keys()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/' + pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id search_summ_table = lsctables.New(lsctables.SearchSummaryTable) coinc_h5file = self.coinc_file.h5file try: start_time = coinc_h5file['segments']['coinc']['start'][:].min() end_time = coinc_h5file['segments']['coinc']['end'][:].max() except KeyError: start_times = [] end_times = [] for ifo_comb in coinc_h5file['segments']: if ifo_comb == 'foreground_veto': continue seg_group = coinc_h5file['segments'][ifo_comb] start_times.append(seg_group['start'][:].min()) end_times.append(seg_group['end'][:].max()) start_time = min(start_times) end_time = max(end_times) num_trigs = len(self.sort_arr) search_summary = return_search_summary(start_time, end_time, num_trigs, ifos) search_summ_table.append(search_summary) outdoc.childNodes[0].appendChild(search_summ_table) sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) time_slide_table = lsctables.New(lsctables.TimeSlideTable) # Set up time_slide table time_slide_id = lsctables.TimeSlideID(0) for ifo in ifos: time_slide_row = lsctables.TimeSlide() time_slide_row.instrument = ifo time_slide_row.time_slide_id = time_slide_id time_slide_row.offset = 0 time_slide_row.process_id = proc_id time_slide_table.append(time_slide_row) # Set up coinc_definer table coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = \ "sngl_inspiral<-->sngl_inspiral coincidences" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) bank_col_names = ['mass1', 'mass2', 'spin1z', 'spin2z'] bank_col_vals = {} for name in bank_col_names: bank_col_vals[name] = self.get_bankfile_array(name) coinc_event_names = ['ifar', 'time', 'fap', 'stat'] coinc_event_vals = {} for name in coinc_event_names: if name == 'time': coinc_event_vals[name] = self.get_end_time() else: coinc_event_vals[name] = self.get_coincfile_array(name) sngl_col_names = [ 'snr', 'chisq', 'chisq_dof', 'bank_chisq', 'bank_chisq_dof', 'cont_chisq', 'cont_chisq_dof', 'end_time', 'template_duration', 'coa_phase', 'sigmasq' ] sngl_col_vals = {} for name in sngl_col_names: sngl_col_vals[name] = self.get_snglfile_array_dict(name) sngl_event_count = 0 for idx in range(len(self.sort_arr)): # Set up IDs and mapping values coinc_id = lsctables.CoincID(idx) # Set up sngls # FIXME: As two-ifo is hardcoded loop over all ifos sngl_combined_mchirp = 0 sngl_combined_mtot = 0 net_snrsq = 0 for ifo in ifos: # If this ifo is not participating in this coincidence then # ignore it and move on. if not sngl_col_vals['snr'][ifo][1][idx]: continue event_id = lsctables.SnglInspiralID(sngl_event_count) sngl_event_count += 1 sngl = return_empty_sngl() sngl.event_id = event_id sngl.ifo = ifo net_snrsq += sngl_col_vals['snr'][ifo][0][idx]**2 for name in sngl_col_names: val = sngl_col_vals[name][ifo][0][idx] if name == 'end_time': sngl.set_end(LIGOTimeGPS(val)) else: setattr(sngl, name, val) for name in bank_col_names: val = bank_col_vals[name][idx] setattr(sngl, name, val) sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_combined_mchirp += sngl.mchirp sngl_combined_mtot += sngl.mtotal sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = event_id coinc_event_map_table.append(coinc_map_row) sngl_combined_mchirp = sngl_combined_mchirp / len(ifos) sngl_combined_mtot = sngl_combined_mtot / len(ifos) # Set up coinc inspiral and coinc event tables coinc_event_row = lsctables.Coinc() coinc_inspiral_row = lsctables.CoincInspiral() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ','.join(ifos) coinc_inspiral_row.set_ifos(ifos) coinc_event_row.time_slide_id = time_slide_id coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_combined_mchirp coinc_inspiral_row.mass = sngl_combined_mtot coinc_inspiral_row.set_end( LIGOTimeGPS(coinc_event_vals['time'][idx])) coinc_inspiral_row.snr = net_snrsq**0.5 coinc_inspiral_row.false_alarm_rate = coinc_event_vals['fap'][idx] coinc_inspiral_row.combined_far = 1. / coinc_event_vals['ifar'][idx] # Transform to Hz coinc_inspiral_row.combined_far = \ coinc_inspiral_row.combined_far / YRJUL_SI coinc_event_row.likelihood = coinc_event_vals['stat'][idx] coinc_inspiral_row.minimum_duration = 0. coinc_event_table.append(coinc_event_row) coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_def_table) outdoc.childNodes[0].appendChild(coinc_event_table) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(time_slide_table) outdoc.childNodes[0].appendChild(coinc_inspiral_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) ligolw_utils.write_filename(outdoc, file_name)
elif ((spin1z != 0) or (spin2z != 0)): simtype = 'aligned-spin' else: spinval = False # calculate the value for mean_anomaly (assuming this hasn't been calculated) # 0 is default for low eccentricity values (<= .001) mean_anom = 0 if (id_eccentricity > .001): # default value for when it hasn't been properly calculated mean_anom = -1 # create all relevant attributes for converted .h5 file # default Format 1 attributes mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta( id_mass_starA, id_mass_starB) hashtag = hashlib.md5() fd.attrs.create('Format', 1) fd.attrs.create('type', 'BNS') fd.attrs.create('name', 'CoRe:' + database_key) fd.attrs.create('alternative-names', simulation_name) fd.attrs.create('NR-group', 'CoRe') fd.attrs.create('NR-code', id_code + ', ' + evolution_code) fd.attrs.create('modification-date', '') fd.attrs.create('point-of-contact-email', '*****@*****.**') fd.attrs.create('simulation-type', simtype) fd.attrs.create('INSPIRE-bibtex-keys', reference_bibkeys) fd.attrs.create('license', 'public') fd.attrs.create('Lmax', lmax) fd.attrs.create('files-in-error-series', '')
def get_params(file): """ Read waveform meta data from hdf5 file """ f = h5py.File(file, "r") # Metadata parameters: params = {} params["eta"] = float(f.attrs["eta"]) params["spin1x"] = float(f.attrs["spin1x"]) params["spin1y"] = float(f.attrs["spin1y"]) params["spin1z"] = float(f.attrs["spin1z"]) params["spin2x"] = float(f.attrs["spin2x"]) params["spin2y"] = float(f.attrs["spin2y"]) params["spin2z"] = float(f.attrs["spin2z"]) params["Mmin30Hz"] = float(f.attrs["f_lower_at_1MSUN"]) / 30.0 mass1, mass2 = pnutils.mtotal_eta_to_mass1_mass2(params["Mmin30Hz"], params["eta"]) params["Mchirpmin30Hz"], _ = pnutils.mass1_mass2_to_mchirp_eta(mass1, mass2) params["q"] = mass1 / mass2 # --- Derived spin configuration params["a1"] = np.linalg.norm([params["spin1x"], params["spin1y"], params["spin1z"]]) params["a2"] = np.linalg.norm([params["spin2x"], params["spin2y"], params["spin2z"]]) params["a1dotL"], vec = nrbu.a_with_L(params["spin1x"], params["spin1y"], params["spin1z"]) params["a1crossL"] = np.linalg.norm(vec) params["a2dotL"], vec = nrbu.a_with_L(params["spin2x"], params["spin2y"], params["spin2z"]) params["a2crossL"] = np.linalg.norm(vec) params["theta_a12"] = nrbu.spin_angle( params["spin1x"], params["spin1y"], params["spin1z"], params["spin2x"], params["spin2y"], params["spin2z"] ) params["SeffdotL"], vec = nrbu.effspin_with_L( params["q"], params["spin1x"], params["spin1y"], params["spin1z"], params["spin2x"], params["spin2y"], params["spin2z"], ) params["SeffcrossL"] = np.linalg.norm(vec) params["SdotL"], params["theta_SdotL"] = nrbu.totspin_dot_L( params["q"], params["spin1x"], params["spin1y"], params["spin1z"], params["spin2x"], params["spin2y"], params["spin2z"], ) params["wavefile"] = os.path.abspath(file) return params
def to_coinc_xml_object(self, file_name): # FIXME: This function will only work with two ifos!! outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) ifos = [ifo for ifo in self.sngl_files.keys()] proc_id = ligolw_process.register_to_xmldoc(outdoc, 'pycbc', {}, ifos=ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/'+pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id search_summ_table = lsctables.New(lsctables.SearchSummaryTable) coinc_h5file = self.coinc_file.h5file start_time = coinc_h5file['segments']['coinc']['start'][:].min() end_time = coinc_h5file['segments']['coinc']['end'][:].max() num_trigs = len(self.sort_arr) search_summary = return_search_summary(start_time, end_time, num_trigs, ifos) search_summ_table.append(search_summary) outdoc.childNodes[0].appendChild(search_summ_table) sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) time_slide_table = lsctables.New(lsctables.TimeSlideTable) # Set up time_slide table time_slide_id = lsctables.TimeSlideID(0) for ifo in ifos: time_slide_row = lsctables.TimeSlide() time_slide_row.instrument = ifo time_slide_row.time_slide_id = time_slide_id time_slide_row.offset = 0 time_slide_row.process_id = proc_id time_slide_table.append(time_slide_row) # Set up coinc_definer table coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincidences" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) bank_col_names = ['mass1', 'mass2', 'spin1z', 'spin2z'] bank_col_vals = {} for name in bank_col_names: bank_col_vals[name] = self.get_bankfile_array(name) coinc_event_names = ['ifar', 'time1', 'fap', 'stat'] coinc_event_vals = {} for name in coinc_event_names: coinc_event_vals[name] = self.get_coincfile_array(name) sngl_col_names = ['snr', 'chisq', 'chisq_dof', 'bank_chisq', 'bank_chisq_dof', 'cont_chisq', 'cont_chisq_dof', 'end_time', 'template_duration', 'coa_phase', 'sigmasq'] sngl_col_vals = {} for name in sngl_col_names: sngl_col_vals[name] = self.get_snglfile_array_dict(name) for idx in xrange(len(self.sort_arr)): # Set up IDs and mapping values coinc_id = lsctables.CoincID(idx) # Set up sngls # FIXME: As two-ifo is hardcoded loop over all ifos sngl_combined_mchirp = 0 sngl_combined_mtot = 0 for ifo in ifos: sngl_id = self.trig_id[ifo][idx] event_id = lsctables.SnglInspiralID(sngl_id) sngl = return_empty_sngl() sngl.event_id = event_id sngl.ifo = ifo for name in sngl_col_names: val = sngl_col_vals[name][ifo][idx] if name == 'end_time': sngl.set_end(LIGOTimeGPS(val)) else: setattr(sngl, name, val) for name in bank_col_names: val = bank_col_vals[name][idx] setattr(sngl, name, val) sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_combined_mchirp += sngl.mchirp sngl_combined_mtot += sngl.mtotal sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = event_id coinc_event_map_table.append(coinc_map_row) sngl_combined_mchirp = sngl_combined_mchirp / len(ifos) sngl_combined_mtot = sngl_combined_mtot / len(ifos) # Set up coinc inspiral and coinc event tables coinc_event_row = lsctables.Coinc() coinc_inspiral_row = lsctables.CoincInspiral() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ','.join(ifos) coinc_inspiral_row.set_ifos(ifos) coinc_event_row.time_slide_id = time_slide_id coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_combined_mchirp coinc_inspiral_row.mass = sngl_combined_mtot coinc_inspiral_row.set_end(\ LIGOTimeGPS(coinc_event_vals['time1'][idx])) coinc_inspiral_row.snr = coinc_event_vals['stat'][idx] coinc_inspiral_row.false_alarm_rate = coinc_event_vals['fap'][idx] coinc_inspiral_row.combined_far = 1./coinc_event_vals['ifar'][idx] # Transform to Hz coinc_inspiral_row.combined_far = \ coinc_inspiral_row.combined_far / YRJUL_SI coinc_event_row.likelihood = 0. coinc_inspiral_row.minimum_duration = 0. coinc_event_table.append(coinc_event_row) coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_def_table) outdoc.childNodes[0].appendChild(coinc_event_table) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(time_slide_table) outdoc.childNodes[0].appendChild(coinc_inspiral_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) ligolw_utils.write_filename(outdoc, file_name)
Hlm = pwave.construct_Hlm(*quadrupole_data[1:]) wavelen = len(Hlm['l=2, m=2']) times = np.arange(0, wavelen * delta_t, delta_t) times_M = times / (lal.MTSUN_SI * total_mass) # GEOMETERIZE HLM (might be already!) see line 241+ of pmns_waveform.py l = 2 with h5py.File(eos + '_' + mass + '.h5', 'w') as fd: # # Set metadata # mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(mass1, mass2) fd.attrs.create('NR_group', 'Bauswein') fd.attrs.create( 'name', 'Bauswein:BNS:%s' % (waveform_data.eos + '_' + waveform_data.mass + '_' + waveform_data.viscosity)) hashtag = hashlib.md5() hashtag.update(fd.attrs['name']) fd.attrs.create('hashtag', hashtag.digest()) fd.attrs.create('f_lower_at_1MSUN', f_lower) fd.attrs.create('eta', eta) fd.attrs.create('LNhatx', 0.0) fd.attrs.create('LNhaty', 0.0) fd.attrs.create('LNhatz', 0.0) fd.attrs.create('lnhatx', 0.0) fd.attrs.create('lnhaty', 0.0)
def test_get_random_mass(self): # Want to do this for a variety of mass combinations for i in update_mass_parameters(self): curr_min_mass = self.min_total_mass curr_max_mass = self.max_total_mass try: pycbc.tmpltbank.verify_mass_range_options(self, parser=parser) except ValueError: # Some of the inputs are unphysical and will fail. # These cases are known to fail, the inputs are unphysical # 35 has inconsistent total mass and eta restrictions # 38 Component mass, [upper] chirp mass and [lower] eta limits # rule out the entire space. # 41 Same as 38 # 44 Same as 38 # 62 From component mass and total mass limits only total masses # between 7 and 7.5 are possible. This range all has eta # lower than the limit of 0.17. # 65 Same as 38 # 68 Same as 38 # 71 Same as 38 # 80 Same as 62 if i in [35, 38, 41, 44, 62, 65, 68, 71, 80]: continue raise # Check that if the mass limits have changed, it was right to do so # This is not exhaustive, but gets most things if not self.min_total_mass == curr_min_mass: min_comp_mass = self.min_mass1 + self.min_mass2 min_eta = self.min_mass1 * self.min_mass2 /\ (min_comp_mass * min_comp_mass) min_chirp_mass = min_comp_mass * min_eta**(3. / 5.) if self.min_total_mass == min_comp_mass: # Okay, the total mass is changed by the components pass elif min_eta < self.min_eta or min_eta > self.max_eta: # Okay, not possible from eta pass elif min_chirp_mass < self.min_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Minimum total mass changed unexpectedly." print(self.min_total_mass, curr_min_mass) print(self.min_mass1, self.min_mass2, min_comp_mass) print(min_eta, self.min_eta, self.max_eta) print(min_chirp_mass, self.min_chirp_mass) self.fail(err_msg) if not self.max_total_mass == curr_max_mass: max_comp_mass = self.max_mass1 + self.max_mass2 max_eta = self.max_mass1 * self.max_mass2 /\ (max_comp_mass * max_comp_mass) max_chirp_mass = max_comp_mass * max_eta**(3. / 5.) if self.max_total_mass == max_comp_mass: # Okay, the total mass is changed by the components pass elif max_eta < self.min_eta or max_eta > self.max_eta: # Okay, not possible from eta pass elif max_chirp_mass > self.max_chirp_mass: # Okay, not possible from chirp mass pass else: err_msg = "Maximum total mass changed unexpectedly." self.fail(err_msg) massRangeParams = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ ns_bh_boundary_mass=self.ns_bh_boundary_mass) # And again with the nsbh flag massRangeParams2 = pycbc.tmpltbank.massRangeParameters(\ self.min_mass1,\ self.max_mass1, self.min_mass2, self.max_mass2,\ maxNSSpinMag=self.max_ns_spin_mag,\ maxBHSpinMag=self.max_bh_spin_mag,\ maxTotMass=self.max_total_mass,\ minTotMass=self.min_total_mass,\ max_chirp_mass=self.max_chirp_mass,\ min_chirp_mass=self.min_chirp_mass,\ maxEta=self.max_eta,\ minEta=self.min_eta,\ nsbhFlag=True) mass1, mass2, spin1z, spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams) mass = mass1 + mass2 errMsg = "pycbc.tmpltbank.get_random_mass returns invalid ranges." self.assertTrue(not (mass < self.min_total_mass).any(), msg=errMsg) self.assertTrue(not (mass > self.max_total_mass).any(), msg=errMsg) self.assertTrue(not (mass1 > self.max_mass1 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass1 < self.min_mass1 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass2 > self.max_mass2 * 1.001).any(), msg=errMsg) self.assertTrue(not (mass2 < self.min_mass2 * 0.999).any(), msg=errMsg) self.assertTrue(not (mass1 < mass2).any(), msg=errMsg) # Chirp mass and eta mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta(mass1, mass2) if self.max_chirp_mass: self.assertTrue( not (mchirp > self.max_chirp_mass * 1.0001).any(), msg=errMsg) if self.min_chirp_mass: self.assertTrue( not (mchirp < self.min_chirp_mass * 0.9999).any(), msg=errMsg) if self.min_eta: self.assertTrue(not (eta < self.min_eta * 0.9999).any(), msg=errMsg) self.assertTrue(not (eta > self.max_eta * 1.0001).any(), msg=errMsg) nsSpin1 = spin1z[mass1 < self.ns_bh_boundary_mass] nsSpin2 = spin2z[mass2 < self.ns_bh_boundary_mass] bhSpin1 = spin1z[mass1 > self.ns_bh_boundary_mass] bhSpin2 = spin2z[mass2 > self.ns_bh_boundary_mass] self.assertTrue(not (abs(nsSpin1) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(nsSpin2) > 0.5).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin1) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(bhSpin2) > 0.9).any(), msg=errMsg) # Check that *some* spins are bigger than 0.5 if len(bhSpin1): self.assertTrue((abs(bhSpin1) > 0.5).any(), msg=errMsg) if len(bhSpin2): self.assertTrue((abs(bhSpin2) > 0.5).any(), msg=errMsg) # This can be used to test the boundaries are all applied visually # FIXME: This would need to be updated for all of the mass limits #pylab.plot(mass1, mass2, 'b.') #pylab.plot([3.0,5.0],[3.0,1.0],'r-') #pylab.plot([1.7216566400945545,1.9921146662296347,3.4433132801891091,4.01175560949798],[1.1477710933963694,1.0066274466204264,2.2955421867927388,1.002938902374495],'mx') #pylab.ylim([0.8,3.0]) #pylab.xlim([1.5,5.0]) #pylab.savefig("masses_%d.png" %(idx,)) # Check nsbh flag mass1, mass2, spin1z, spin2z = \ pycbc.tmpltbank.get_random_mass(100000, massRangeParams2) self.assertTrue(not (abs(spin1z) > 0.9).any(), msg=errMsg) self.assertTrue(not (abs(spin2z) > 0.5).any(), msg=errMsg) self.assertTrue((abs(spin1z) > 0.5).any(), msg=errMsg)
def __init__(self, ifos, coinc_results, **kwargs): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is defined in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. """ self.ifos = ifos followup_ifos = kwargs.get('followup_ifos') or [] self.template_id = coinc_results['foreground/%s/template_id' % self.ifos[0]] # remember if this should be marked as HWINJ self.is_hardware_injection = ('HWINJ' in coinc_results) # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/' + pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(ifos) coinc_event_row.instruments = ','.join(ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # compute SNR time series subthreshold_sngl_time = numpy.mean( [coinc_results['foreground/%s/end_time' % ifo] for ifo in ifos]) self.upload_snr_series = kwargs.get('upload_snr_series') if self.upload_snr_series: self.snr_series = {} self.snr_series_psd = {} htilde = kwargs['bank'][self.template_id] for ifo in ifos + followup_ifos: if ifo in ifos: trig_time = coinc_results['foreground/%s/end_time' % ifo] else: trig_time = subthreshold_sngl_time # NOTE we only check the state/DQ of followup IFOs here. # IFOs producing the coincidence are assumed to also # produce valid SNR series. snr_series, snr_series_psd = compute_followup_snr_series( kwargs['data_readers'][ifo], htilde, trig_time, check_state=(ifo in followup_ifos)) if snr_series is not None: self.snr_series[ifo] = snr_series self.snr_series_psd[ifo] = snr_series_psd # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_populated = None for sngl_id, ifo in enumerate(ifos + followup_ifos): if self.upload_snr_series and ifo not in self.snr_series: # SNR series could not be computed, so skip this continue sngl = return_empty_sngl(nones=True) sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.process_id = proc_id sngl.ifo = ifo names = [ n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n ] for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(lal.LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass if sngl.mass1 and sngl.mass2: sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl_populated = sngl if sngl.snr: sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) if self.upload_snr_series and ifo in self.snr_series: snr_series_to_xml(self.snr_series[ifo], outdoc, sngl.event_id) # for subthreshold detectors, respect BAYESTAR's assumptions and checks bayestar_check_fields = ('mass1 mass2 mtotal mchirp eta spin1x ' 'spin1y spin1z spin2x spin2y spin2z').split() for sngl in sngl_inspiral_table: if sngl.ifo in followup_ifos: for bcf in bayestar_check_fields: setattr(sngl, bcf, getattr(sngl_populated, bcf)) sngl.set_end(lal.LIGOTimeGPS(subthreshold_sngl_time)) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_populated.mchirp coinc_inspiral_row.mass = sngl_populated.mtotal coinc_inspiral_row.end_time = sngl_populated.end_time coinc_inspiral_row.end_time_ns = sngl_populated.end_time_ns coinc_inspiral_row.snr = coinc_results['foreground/stat'] far = 1.0 / (lal.YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) self.outdoc = outdoc self.time = sngl_populated.get_end()
def __init__(self, ifos, coinc_results, **kwargs): """Initialize a ligolw xml representation of a zerolag trigger for upload from pycbc live to gracedb. Parameters ---------- ifos: list of strs A list of the ifos pariticipating in this trigger coinc_results: dict of values A dictionary of values. The format is defined in pycbc/events/coinc.py and matches the on disk representation in the hdf file for this time. psds: dict of FrequencySeries Dictionary providing PSD estimates for all involved detectors. low_frequency_cutoff: float Minimum valid frequency for the PSD estimates. followup_data: dict of dicts, optional Dictionary providing SNR time series for each detector, to be used in sky localization with BAYESTAR. The format should be `followup_data['H1']['snr_series']`. More detectors can be present than given in `ifos`. If so, the extra detectors will only be used for sky localization. channel_names: dict of strings, optional Strain channel names for each detector. Will be recorded in the sngl_inspiral table. """ self.template_id = coinc_results['foreground/%s/template_id' % ifos[0]] # remember if this should be marked as HWINJ self.is_hardware_injection = ('HWINJ' in coinc_results and coinc_results['HWINJ']) if 'followup_data' in kwargs: fud = kwargs['followup_data'] assert len({fud[ifo]['snr_series'].delta_t for ifo in fud}) == 1, \ "delta_t for all ifos do not match" self.snr_series = {ifo: fud[ifo]['snr_series'] for ifo in fud} usable_ifos = fud.keys() followup_ifos = list(set(usable_ifos) - set(ifos)) else: self.snr_series = None usable_ifos = ifos followup_ifos = [] # Set up the bare structure of the xml document outdoc = ligolw.Document() outdoc.appendChild(ligolw.LIGO_LW()) proc_id = ligolw_process.register_to_xmldoc( outdoc, 'pycbc', {}, ifos=usable_ifos, comment='', version=pycbc_version.git_hash, cvs_repository='pycbc/'+pycbc_version.git_branch, cvs_entry_time=pycbc_version.date).process_id # Set up coinc_definer table coinc_def_table = lsctables.New(lsctables.CoincDefTable) coinc_def_id = lsctables.CoincDefID(0) coinc_def_row = lsctables.CoincDef() coinc_def_row.search = "inspiral" coinc_def_row.description = "sngl_inspiral<-->sngl_inspiral coincs" coinc_def_row.coinc_def_id = coinc_def_id coinc_def_row.search_coinc_type = 0 coinc_def_table.append(coinc_def_row) outdoc.childNodes[0].appendChild(coinc_def_table) # Set up coinc inspiral and coinc event tables coinc_id = lsctables.CoincID(0) coinc_event_table = lsctables.New(lsctables.CoincTable) coinc_event_row = lsctables.Coinc() coinc_event_row.coinc_def_id = coinc_def_id coinc_event_row.nevents = len(usable_ifos) coinc_event_row.instruments = ','.join(usable_ifos) coinc_event_row.time_slide_id = lsctables.TimeSlideID(0) coinc_event_row.process_id = proc_id coinc_event_row.coinc_event_id = coinc_id coinc_event_row.likelihood = 0. coinc_event_table.append(coinc_event_row) outdoc.childNodes[0].appendChild(coinc_event_table) # Set up sngls sngl_inspiral_table = lsctables.New(lsctables.SnglInspiralTable) coinc_event_map_table = lsctables.New(lsctables.CoincMapTable) sngl_populated = None network_snrsq = 0 for sngl_id, ifo in enumerate(usable_ifos): sngl = return_empty_sngl(nones=True) sngl.event_id = lsctables.SnglInspiralID(sngl_id) sngl.process_id = proc_id sngl.ifo = ifo names = [n.split('/')[-1] for n in coinc_results if 'foreground/%s' % ifo in n] for name in names: val = coinc_results['foreground/%s/%s' % (ifo, name)] if name == 'end_time': sngl.set_end(lal.LIGOTimeGPS(val)) else: try: setattr(sngl, name, val) except AttributeError: pass if sngl.mass1 and sngl.mass2: sngl.mtotal, sngl.eta = pnutils.mass1_mass2_to_mtotal_eta( sngl.mass1, sngl.mass2) sngl.mchirp, _ = pnutils.mass1_mass2_to_mchirp_eta( sngl.mass1, sngl.mass2) sngl_populated = sngl if sngl.snr: sngl.eff_distance = (sngl.sigmasq)**0.5 / sngl.snr network_snrsq += sngl.snr ** 2.0 if 'channel_names' in kwargs and ifo in kwargs['channel_names']: sngl.channel = kwargs['channel_names'][ifo] sngl_inspiral_table.append(sngl) # Set up coinc_map entry coinc_map_row = lsctables.CoincMap() coinc_map_row.table_name = 'sngl_inspiral' coinc_map_row.coinc_event_id = coinc_id coinc_map_row.event_id = sngl.event_id coinc_event_map_table.append(coinc_map_row) if self.snr_series is not None: snr_series_to_xml(self.snr_series[ifo], outdoc, sngl.event_id) # for subthreshold detectors, respect BAYESTAR's assumptions and checks bayestar_check_fields = ('mass1 mass2 mtotal mchirp eta spin1x ' 'spin1y spin1z spin2x spin2y spin2z').split() subthreshold_sngl_time = numpy.mean( [coinc_results['foreground/{}/end_time'.format(ifo)] for ifo in ifos]) for sngl in sngl_inspiral_table: if sngl.ifo in followup_ifos: for bcf in bayestar_check_fields: setattr(sngl, bcf, getattr(sngl_populated, bcf)) sngl.set_end(lal.LIGOTimeGPS(subthreshold_sngl_time)) outdoc.childNodes[0].appendChild(coinc_event_map_table) outdoc.childNodes[0].appendChild(sngl_inspiral_table) # Set up the coinc inspiral table coinc_inspiral_table = lsctables.New(lsctables.CoincInspiralTable) coinc_inspiral_row = lsctables.CoincInspiral() # This seems to be used as FAP, which should not be in gracedb coinc_inspiral_row.false_alarm_rate = 0 coinc_inspiral_row.minimum_duration = 0. coinc_inspiral_row.set_ifos(usable_ifos) coinc_inspiral_row.coinc_event_id = coinc_id coinc_inspiral_row.mchirp = sngl_populated.mchirp coinc_inspiral_row.mass = sngl_populated.mtotal coinc_inspiral_row.end_time = sngl_populated.end_time coinc_inspiral_row.end_time_ns = sngl_populated.end_time_ns coinc_inspiral_row.snr = network_snrsq ** 0.5 far = 1.0 / (lal.YRJUL_SI * coinc_results['foreground/ifar']) coinc_inspiral_row.combined_far = far coinc_inspiral_table.append(coinc_inspiral_row) outdoc.childNodes[0].appendChild(coinc_inspiral_table) # append the PSDs self.psds = kwargs['psds'] psds_lal = {} for ifo in self.psds: psd = self.psds[ifo] kmin = int(kwargs['low_frequency_cutoff'] / psd.delta_f) fseries = lal.CreateREAL8FrequencySeries( "psd", psd.epoch, kwargs['low_frequency_cutoff'], psd.delta_f, lal.StrainUnit**2 / lal.HertzUnit, len(psd) - kmin) fseries.data.data = psd.numpy()[kmin:] / pycbc.DYN_RANGE_FAC ** 2.0 psds_lal[ifo] = fseries make_psd_xmldoc(psds_lal, outdoc) self.outdoc = outdoc self.time = sngl_populated.get_end()
elif ((spin1z != 0) or (spin2z != 0)): simtype = 'aligned-spin' else: spinval = False # calculate the value for mean_anomaly (assuming this hasn't been calculated) # 0 is default for low eccentricity values (<= .001) mean_anom = 0 if (eccentricity > .001): # default value for when it hasn't been properly calculated mean_anom = -1 # create all relevant attributes for converted .h5 file # default Format 1 attributes mchirp, eta = pnutils.mass1_mass2_to_mchirp_eta( initial_mass1, initial_mass2) hashtag = hashlib.md5() fd.attrs.create('Format', 1) fd.attrs.create('type', 'BBH') fd.attrs.create('name', simulation_name) fd.attrs.create('alternative-names', alternative_names) fd.attrs.create('NR-group', 'SXS') fd.attrs.create('NR-code', 'SpEC') fd.attrs.create('modification-date', '') fd.attrs.create('point-of-contact-email', '') fd.attrs.create('simulation-type', '') fd.attrs.create('INSPIRE-bibtex-keys', '') fd.attrs.create('license', 'public') fd.attrs.create('Lmax', lmax) fd.attrs.create('files-in-error-series', '') fd.attrs.create('comparable-simulation', '')