def test_antenna_pattern(self): vals = zip(self.ra, self.dec, self.pol, self.time) for ifo in self.d: fp = [] fc = [] for ra1, dec1, pol1, time1 in vals: gmst = lal.GreenwichMeanSiderealTime(time1) fp1, fc1 = tuple( lal.ComputeDetAMResponse(ifo.response, ra1, dec1, pol1, gmst)) fp.append(fp1) fc.append(fc1) fp2, fc2 = ifo.antenna_pattern(self.ra, self.dec, self.pol, self.time) fp = numpy.array(fp) fc = numpy.array(fc) diff1 = fp - fp2 diff2 = fc - fc2 diff = abs(numpy.concatenate([diff1, diff2])) tolerance = 1e-4 print("Max antenna diff:", ifo.name, diff.max()) self.assertLess(diff.max(), tolerance)
def makeplot(options): fig = figure.Figure() FigureCanvasAgg(fig) fig.set_size_inches(6.5, 6.5 / ((1 + math.sqrt(5)) / 2)) axes = fig.gca() axes.grid(True) xvals = numpy.arange(0.0, 401.0, 1.0, "Float64") * math.pi / 200.0 for instrument in options.instrument: yvals = [ plus**2.0 + cross**2.0 for (plus, cross) in map( lambda t: lal.ComputeDetAMResponse( lal.cached_detector_by_prefix[instrument].response, options .right_ascension, options.declination, 0.0, t), xvals) ] axes.plot(xvals, yvals) axes.set_xlim([0.0, 2.0 * math.pi]) axes.set_xticks(numpy.arange(9) * math.pi / 4) axes.set_xticklabels([ r"0", r"$\pi/4$", r"$\pi/2$", r"$3\pi/4$", r"$\pi$", r"$5\pi/4$", r"$3\pi/2$", r"$7\pi/4$", r"$2\pi$" ]) axes.legend([r"\verb|%s|" % ins for ins in options.instrument]) axes.set_xlabel("Greenwich Mean Sidereal Time (rad)") axes.set_ylabel(r"$F_{+}^{2} + F_{\times}^{2}$") axes.set_title( r"Detector Response by Sidereal Time for Source at R.A.\ %g rad, Dec.\ %g rad" % (options.right_ascension, options.declination)) return fig
def get_delta_D_rss(pt,coinc): """ compute the rms difference in the ratio of the difference of the squares of Deff to the sum of the squares of Deff between the measured values and a "marginalized" effective distance this is just the squared Deff integrated over inclination and polarization which is proportional to (F+^2 + Fx^2)^(-1) """ latitude,longitude = pt gmst = {} D_marg_sq = {} F_plus = {} F_cross = {} for ifo in coinc.ifo_list: gmst[ifo] = date.XLALGreenwichMeanSiderealTime(coinc.gps[ifo]) F_plus[ifo], F_cross[ifo] = lal.ComputeDetAMResponse(detector_responses[ifo],\ longitude,latitude,0,gmst[ifo]) D_marg_sq[ifo] = 1/(F_plus[ifo]*F_plus[ifo]+F_cross[ifo]*F_cross[ifo]) delta_D = {} effD_diff = 0.0 effD_sum = 0.0 Dmarg_diff = 0.0 Dmarg_sum = 0.0 delta_D_rss = 0.0 for ifos in coinc.ifo_coincs: effD_diff = coinc.eff_distances[ifos[0]] * coinc.eff_distances[ifos[0]]\ - coinc.eff_distances[ifos[1]] * coinc.eff_distances[ifos[1]] effD_sum = coinc.eff_distances[ifos[0]] * coinc.eff_distances[ifos[0]]\ + coinc.eff_distances[ifos[1]] * coinc.eff_distances[ifos[1]] Dmarg_diff = D_marg_sq[ifos[0]] - D_marg_sq[ifos[1]] Dmarg_sum = D_marg_sq[ifos[0]] + D_marg_sq[ifos[1]] delta_D[ifos[0]+ifos[1]] = (effD_diff/effD_sum) - (Dmarg_diff/Dmarg_sum) delta_D_rss += delta_D[ifos[0]+ifos[1]]*delta_D[ifos[0]+ifos[1]] return sqrt(delta_D_rss)
def magnitude_b(burst): gmst = lal.GreenwichMeanSiderealTime(burst.peak) fplus, fcross = lal.ComputeDetAMResponse( lal.cached_detector_by_prefix[burst.ifo].response, SimBurstUtils.MW_CENTER_J2000_RA_RAD, SimBurstUtils.MW_CENTER_J2000_DEC_RAD, 0.0, gmst) return (burst.ms_hrss**2.0 / (fplus**2.0 + fcross**2.0))**0.5
def delay_and_amplitude_correct(event, ra, dec): # retrieve station metadata detector = lal.cached_detector_by_prefix[event.ifo] # delay-correct the event to the geocentre delay = lal.TimeDelayFromEarthCenter(detector.location, ra, dec, event.peak) event.peak -= delay event.period = event.period.shift(-delay) try: event.ms_peak -= delay except AttributeError: pass try: event.ms_period = event.ms_period.shift(-delay) except AttributeError: pass # amplitude-correct the event using the polarization-averaged # antenna response fp, fc = lal.ComputeDetAMResponse( detector.response, ra, dec, 0, lal.GreenwichMeanSiderealTime(event.peak)) mean_response = math.sqrt(fp**2 + fc**2) event.amplitude /= mean_response event.ms_hrss /= mean_response # done return event
def getDetResp(detector, ra, dec, time=0., psi=0.): # Set time gmst = lal.GreenwichMeanSiderealTime(lal.LIGOTimeGPS(time)) #Get Detector Responses det_response = lal.CachedDetectors[det_index[detector]].response # Get Fplus, Fcross fplus, fcross = lal.ComputeDetAMResponse(det_response, ra, dec, psi, gmst) return fplus, fcross
def calculate_sensitivity(self, event): """ Calculate the sensitivity of the detector to an event :param event: object, containing ra, dec, psi, gmst """ self.f_plus, self.f_cross = lal.ComputeDetAMResponse(self.response, event.ra, event.dec, event.psi, event.gmst)
def antenna_pattern(self, right_ascension, declination, polarization, t_gps): """Return the detector response. """ gmst = lal.GreenwichMeanSiderealTime(t_gps) return tuple( lal.ComputeDetAMResponse(self.response, right_ascension, declination, polarization, gmst))
def calculate_mirror_sensitivity(self, event): """ Calculate the sensitivity of the detector to an event, in its mirror sky location :param event: object, containing mirror_ra, mirror_dec, psi, gmst """ self.mirror_f_plus, self.mirror_f_cross = \ lal.ComputeDetAMResponse(self.response, event.mirror_ra, event.mirror_dec, event.psi, event.gmst)
def antenna_pattern(self, skypoints, time=None, psi=0): """ Compute antenna response of a detector for a list of skypoints skypoints: Skypoint object or list of Skypoint objects time: time date when to compute the antenna pattern (default: None) psi: optional polarization angle (default: 0) This function uses XLALComputeDetAMResponse() that takes equatorial coordinates (RA and dec) and the Greenwich Mean Sidereal Time (GMST) to define the sky location. If the skypoints are given in the equatorial coordinate system, the antenna pattern is computed at the provided time if not None, otherwise it is computed at the reference time of the coordinate system of the skypoints. If the skypoints are given in the geographic coordinate system, they are mapped to fiducial equatorial coordinate system with GMST = 0 hr (REFDATE_GMST_ZERO). """ if not isinstance(skypoints, list): skypoints = [skypoints] f = [] for p in skypoints: assert isinstance(p, Skypoint), "Requires Skypoint objects" assert p.coordsystem.is_valid(), "Unsupported coordinate system" # XLALComputeDetAMResponse() requires equatorial coordinates. # We transform the points with Earth-fixed coordsystem ('geographic') # to the fiducial equatorial coordinates system with GMST = 0 hr. if p.coordsystem.name == 'geographic': assert time is None, \ 'time cannot be forced for skypoints in the geographic coordinate system' p = p.transformed_to(FIDUCIAL_EQUATORIAL_COORDSYS_GMST_ZERO) gmst_rad = lal.GreenwichMeanSiderealTime( p.coordsystem.ref_time) else: gmst_rad = lal.GreenwichMeanSiderealTime(time if time is not None else \ p.coordsystem.ref_time) # XLALComputeDetAMResponse() takes equatorial coordinates (RA and dec) # and gmst to define a sky location f.append(lal.ComputeDetAMResponse(self.descriptor.response, \ *p.coords(fmt='lonlat',unit='radians'), \ psi, gmst_rad)) f = numpy.squeeze(numpy.array(f)) if f.ndim == 1: return tuple(f) # fplus, fcross else: return f[:, 0], f[:, 1] # fplus, fcross
def complex_antenna_factor(det, RA, DEC, psi, tref): """ Function to compute the complex-valued antenna pattern function: F+ + i Fx 'det' is a detector prefix string (e.g. 'H1') 'RA' and 'DEC' are right ascension and declination (in radians) 'psi' is the polarization angle 'tref' is the reference GPS time """ detector = lalsim.DetectorPrefixToLALDetector(det) Fp, Fc = lal.ComputeDetAMResponse(detector.response, RA, DEC, psi, lal.GreenwichMeanSiderealTime(tref)) return Fp + 1j * Fc
def find_eff_d(dlum, alpha, delta, pol, iota, T_inj): d_eff_dict = {} # calculate and set detector-specific columns for det_site, det in detectors.iteritems(): d_eff_dict[det_site] = [] for i in range(len(dlum)): fp, fc = lal.ComputeDetAMResponse(det.response, alpha[i], delta[i], pol[i], T_inj[i]) cosi = np.cos(iota[i]) deff = dlum[i] * ((0.5 * (1.0 + cosi**2) * fp)**2 + (cosi * fc)**2)**-0.5 d_eff_dict[det_site].append(deff) d_eff_dict[det_site] = np.array(d_eff_dict[det_site]) return d_eff_dict
def hrss_in_instrument(sim, instrument, offsetvector): """ Given an injection and an instrument, compute and return the h_rss of the injection as should be observed in the instrument. That is, project the waveform onto the instrument, and return the root integrated strain squared. """ # FIXME: this function is really only correct for sine-Gaussian # injections. that's OK because I only quote sensitivities in # units of hrss when discussing sine-Gaussians. # # the problem is the following. first, # # h = F+ h+ + Fx hx # # so # # h^{2} = F+^2 h+^2 + Fx^2 hx^2 + 2 F+ Fx h+ hx # # which means to calculate the hrss in the instrument you need to # know: mean-square h in the + polarization, mean-square h in the # x polarization, and the correlation between the polarizations <h+ # hx>. these could be recorded in the sim_burst table, but they # aren't at present. # semimajor and semiminor axes of polarization ellipse a = 1.0 / math.sqrt(2.0 - sim.pol_ellipse_e**2) b = a * math.sqrt(1.0 - sim.pol_ellipse_e**2) # hrss in plus and cross polarizations hplusrss = sim.hrss * (a * math.cos(sim.pol_ellipse_angle) - b * math.sin(sim.pol_ellipse_angle)) hcrossrss = sim.hrss * (b * math.cos(sim.pol_ellipse_angle) + a * math.sin(sim.pol_ellipse_angle)) # antenna response factors fplus, fcross = lal.ComputeDetAMResponse( lal.cached_detector_by_prefix[instrument].response, sim.ra, sim.dec, sim.psi, lal.GreenwichMeanSiderealTime( sim.time_at_instrument(instrument, offsetvector))) # hrss in detector return math.sqrt((fplus * hplusrss)**2 + (fcross * hcrossrss)**2)
def string_amplitude_in_instrument(sim, instrument, offsetvector): """ Given a string cusp injection and an instrument, compute and return the amplitude of the injection as should be observed in the instrument. """ assert sim.waveform == "StringCusp" # antenna response factors fplus, fcross = lal.ComputeDetAMResponse( lal.cached_detector_by_prefix[instrument].response, sim.ra, sim.dec, sim.psi, lal.GreenwichMeanSiderealTime( sim.time_at_instrument(instrument, offsetvector))) # amplitude in detector return fplus * sim.amplitude
def get_detector_response(ra, dec, psi, detector_tag, gmst=0): detMap = { 'H1': lal.LALDetectorIndexLHODIFF, 'H2': lal.LALDetectorIndexLHODIFF, 'L1': lal.LALDetectorIndexLLODIFF, 'G1': lal.LALDetectorIndexGEO600DIFF, 'V1': lal.LALDetectorIndexVIRGODIFF, 'T1': lal.LALDetectorIndexTAMA300DIFF, 'AL1': lal.LALDetectorIndexLLODIFF, 'AH1': lal.LALDetectorIndexLHODIFF, 'AV1': lal.LALDetectorIndexVIRGODIFF } detector = detMap[detector_tag] # get detector detval = lal.CachedDetectors[detector] # get its response Tensor response = detval.response # get plus and cross polarization response return lal.ComputeDetAMResponse(response, ra, dec, psi, gmst)
def __Fcross(self, detector, RA, Dec, psi, gmst): """ Computes the 'plus' antenna pattern Parameters ---------- detector : str name of detector in network (eg 'H1', 'L1') RA,Dec : float sky location of the event in radians psi : float source polarisation in radians gmst : float Greenwich Mean Sidereal Time in seconds Returns ------- float F_x antenna response """ detector = lalsim.DetectorPrefixToLALDetector(detector) return lal.ComputeDetAMResponse(detector.response, RA, Dec, psi, gmst)[1]
def response(gpsTime, rightAscension, declination, inclination, polarization, unit, det): """ response( gpsTime, rightAscension, declination, inclination, polarization, unit, detector ) Calculates the antenna factors for a detector 'detector' (e.g. 'H1') at a given gps time (as integer) for a given sky location (rightAscension, declination) in some unit (degree/radians). This computation also takes into account a specific inclination and polarization. The returned values are: (f-plus, f-cross, f-average, q-value). Example: antenna.response( 854378604.780, 11.089, 42.308, 0, 0, 'radians', 'H1' ) """ # check the input arguments if unit == 'radians': ra_rad = rightAscension de_rad = declination psi_rad = polarization iota_rad = inclination elif unit == 'degree': ra_rad = rightAscension / 180.0 * pi de_rad = declination / 180.0 * pi psi_rad = polarization / 180.0 * pi iota_rad = inclination / 180.0 * pi else: raise ValueError, "Unknown unit %s" % unit # calculate GMST if the GPS time gps = lal.LIGOTimeGPS(gpsTime) gmst_rad = lal.GreenwichMeanSiderealTime(gps) # create detector-name map detMap = { 'H1': 'LHO_4k', 'H2': 'LHO_2k', 'L1': 'LLO_4k', 'G1': 'GEO_600', 'V1': 'VIRGO', 'T1': 'TAMA_300' } try: detector = detMap[det] except KeyError: raise ValueError, "ERROR. Key %s is not a valid detector name."\ % (det) # get detector if detector not in inject.cached_detector.keys(): raise ValueError, "%s is not a cached detector. "\ "Cached detectors are: %s" \ % (det, inject.cached_detector.keys()) # get the correct response data response = inject.cached_detector[detector].response # actual computation of antenna factors f_plus, f_cross = lal.ComputeDetAMResponse(response, ra_rad, de_rad, psi_rad, gmst_rad) f_ave = sqrt((f_plus * f_plus + f_cross * f_cross) / 2.0) ci = cos(iota_rad) cc = ci * ci # calculate q-value, e.g. ratio of effective to real distance # ref: Duncans PhD, eq. (4.3) on page 57 f_q = sqrt(f_plus * f_plus * (1 + cc) * (1 + cc) / 4.0 + f_cross * f_cross * cc) # output return f_plus, f_cross, f_ave, f_q
spin1z=sim_inspiral.spin1z, spin2x=sim_inspiral.spin2x, spin2y=sim_inspiral.spin2y, spin2z=sim_inspiral.spin2z, f_min=f_low) W = [filter.signal_psd_series(H, psds[ifo]) for ifo in opts.detector] signal_models = [timing.SignalModel(_) for _ in W] # Get SNR=1 horizon distances for each detector. horizons = np.asarray([ signal_model.get_horizon_distance() for signal_model in signal_models ]) # Get antenna factors for each detector. Fplus, Fcross = np.asarray([ lal.ComputeDetAMResponse(response, ra, dec, psi, gmst) for response in responses ]).T # Compute TOAs at each detector. toas = np.asarray([ lal.TimeDelayFromEarthCenter(location, ra, dec, epoch) for location in locations ]) # Compute SNR in each detector. snrs = (0.5 * (1 + u2) * Fplus + 1j * u * Fcross) * horizons / DL abs_snrs = np.abs(snrs) arg_snrs = np.angle(snrs)
import lal #Python code to convert gpstime to GMST and to find beam pattern functions. # Install lalsuite by typing "pip install lalsuite" in command line #To run the script just do 'python lal-gmst-beam-pattern.py' timeToUse = 1126259462.41302 #GPStime IFO_l = lal.CachedDetectors[lal.LALDetectorIndexLLODIFF] #Livingston IFO_h = lal.CachedDetectors[lal.LALDetectorIndexLHODIFF] #Handoford fancy_time = lal.lal.LIGOTimeGPS(timeToUse) #Nothing important #print fancy_time gmst = lal.GreenwichMeanSiderealTime(fancy_time) #converts gpstime to gmst print gmst RA = 1.123 #right-ascension dec = -0.012 #declination #change the RA and dec to the numbers from the posteior files (the ones I use here are just random...) psi = 1.57 #polarization F_plus_l, F_cross_l = lal.ComputeDetAMResponse( IFO_l.response, RA, dec, psi, gmst) #beam pattern for Livingston F_plus_h, F_cross_h = lal.ComputeDetAMResponse(IFO_h.response, RA, dec, psi, gmst) #beam pattern for Hanford print F_plus_h, F_cross_h print F_plus_l, F_cross_l
def simulate_snr(ra, dec, psi, inc, distance, epoch, gmst, H, S, response, location, measurement_error='zero-noise'): from scipy.interpolate import interp1d from ..bayestar import filter from ..bayestar.interpolation import interpolate_max duration = 0.1 # Calculate whitened template autocorrelation sequence. HS = filter.signal_psd_series(H, S) n = len(HS.data.data) acor, sample_rate = filter.autocorrelation(HS, duration) # Calculate time, amplitude, and phase. u = np.cos(inc) u2 = np.square(u) signal_model = filter.SignalModel(HS) horizon = signal_model.get_horizon_distance() Fplus, Fcross = lal.ComputeDetAMResponse(response, ra, dec, psi, gmst) toa = lal.TimeDelayFromEarthCenter(location, ra, dec, epoch) z = (0.5 * (1 + u2) * Fplus + 1j * u * Fcross) * horizon / distance # Calculate complex autocorrelation sequence. snr_series = z * np.concatenate((acor[:0:-1].conj(), acor)) # If requested, add noise. if measurement_error == 'gaussian-noise': sigmasq = 4 * np.sum(HS.deltaF * np.abs(HS.data.data)) amp = 4 * n * HS.deltaF**0.5 * np.sqrt(HS.data.data / sigmasq) N = lal.CreateCOMPLEX16FrequencySeries('', HS.epoch, HS.f0, HS.deltaF, HS.sampleUnits, n) N.data.data = amp * (np.random.randn(n) + 1j * np.random.randn(n)) noise_term, sample_rate_2 = filter.autocorrelation(N, 2 * duration - 1 / sample_rate, normalize=False) assert sample_rate == sample_rate_2 snr_series += noise_term # Shift SNR series to the nearest sample. int_samples, frac_samples = divmod( (1e-9 * epoch.gpsNanoSeconds + toa) * sample_rate, 1) if frac_samples > 0.5: int_samples += 1 frac_samples -= 1 epoch = lal.LIGOTimeGPS(epoch.gpsSeconds, 0) n = len(acor) - 1 mprime = np.arange(-n, n + 1) m = mprime + frac_samples re, im = (interp1d(m, x, kind='cubic', bounds_error=False, fill_value=0)(mprime) for x in (snr_series.real, snr_series.imag)) snr_series = re + 1j * im # Find the trigger values. i_nearest = np.argmax(np.abs( snr_series[n - n // 2:n + n // 2 + 1])) + n - n // 2 i_interp, z_interp = interpolate_max(i_nearest, snr_series, n // 2, method='lanczos') toa = epoch + (int_samples + i_interp - n) / sample_rate snr = np.abs(z_interp) phase = np.angle(z_interp) # Shift and truncate the SNR time series. epoch += (int_samples + i_nearest - n - n // 2) / sample_rate snr_series = snr_series[(i_nearest - n // 2):(i_nearest + n // 2 + 1)] tseries = lal.CreateCOMPLEX8TimeSeries('snr', epoch, 0, 1 / sample_rate, lal.DimensionlessUnit, len(snr_series)) tseries.data.data = snr_series return horizon, snr, phase, toa, tseries
def test_bayestar_signal_amplitude_model(ra, dec, inclination, polarization, epoch, instrument): """Test BAYESTAR signal amplitude model against LAL injection code.""" detector = lalsimulation.DetectorPrefixToLALDetector(instrument) epoch = lal.LIGOTimeGPS(epoch) gmst = lal.GreenwichMeanSiderealTime(epoch) exp_i_twopsi = np.exp(2j * polarization) u = np.cos(inclination) u2 = np.square(u) F = get_complex_antenna(detector.response, ra, dec, gmst) result = signal_amplitude_model(F, exp_i_twopsi, u, u2) abs_expected = 1 / get_eff_dist(detector, ra, dec, inclination, polarization, epoch, gmst) # This is the *really* slow way of working out the signal amplitude: # generate a frequency-domain waveform and inject it. params = lal.CreateDict() lalsimulation.SimInspiralWaveformParamsInsertPNPhaseOrder( params, lalsimulation.PNORDER_NEWTONIAN) lalsimulation.SimInspiralWaveformParamsInsertPNAmplitudeOrder( params, lalsimulation.PNORDER_NEWTONIAN) # Calculate antenna factors Fplus, Fcross = lal.ComputeDetAMResponse(detector.response, ra, dec, polarization, gmst) # Check that the way I compute the antenna factors matches F = get_complex_antenna(detector.response, ra, dec, gmst) F *= np.exp(-2j * polarization) assert F.real == approx(Fplus, abs=4 * np.finfo(np.float64).eps) assert F.imag == approx(Fcross, abs=4 * np.finfo(np.float64).eps) # "Template" waveform with inclination angle of zero Htemplate, Hcross = lalsimulation.SimInspiralFD(1.4 * lal.MSUN_SI, 1.4 * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 100, 101, 100, params, lalsimulation.TaylorF2) # Discard any non-quadrature phase component of "template" Htemplate.data.data += 1j * Hcross.data.data # Normalize "template" h = np.sum( np.square(Htemplate.data.data.real) + np.square(Htemplate.data.data.imag)) h = 2 / h Htemplate.data.data *= h # "Signal" waveform with requested inclination angle Hsignal, Hcross = lalsimulation.SimInspiralFD( 1.4 * lal.MSUN_SI, 1.4 * lal.MSUN_SI, 0, 0, 0, 0, 0, 0, 1, inclination, 0, 0, 0, 0, 1, 100, 101, 100, params, lalsimulation.TaylorF2) # Project "signal" using antenna factors Hsignal.data.data = Fplus * Hsignal.data.data + Fcross * Hcross.data.data # Work out complex amplitude by comparing with "template" waveform expected = np.sum(Htemplate.data.data.conj() * Hsignal.data.data) assert abs(expected) == approx(abs_expected, abs=1.5 * np.finfo(np.float32).eps) assert abs(result) == approx(abs_expected, abs=1.5 * np.finfo(np.float32).eps) assert result.real == approx(expected.real, abs=4 * np.finfo(np.float32).eps) assert result.imag == approx(expected.imag, abs=4 * np.finfo(np.float32).eps)
def get_complex_antenna(response, ra, dec, gmst): Fplus, Fcross = lal.ComputeDetAMResponse(response, ra, dec, 0, gmst) return Fplus + 1j * Fcross