def _det_tc(detector_name, ra, dec, tc, ref_frame='geocentric'): """Returns the coalescence time of a signal in the given detector. Parameters ---------- detector_name : string The name of the detector, e.g., 'H1'. ra : float The right ascension of the signal, in radians. dec : float The declination of the signal, in radians. tc : float The GPS time of the coalescence of the signal in the `ref_frame`. ref_frame : {'geocentric', string} The reference frame that the given coalescence time is defined in. May specify 'geocentric', or a detector name; default is 'geocentric'. Returns ------- float : The GPS time of the coalescence in detector `detector_name`. """ if ref_frame == detector_name: return tc detector = Detector(detector_name) if ref_frame == 'geocentric': return tc + detector.time_delay_from_earth_center(ra, dec, tc) else: other = Detector(ref_frame) return tc + detector.time_delay_from_detector(other, ra, dec, tc)
def get_gate_times(self): """Gets the time to apply a gate based on the current sky position. If the parameter ``gatefunc`` is set to ``'hmeco'``, the gate times will be calculated based on the hybrid MECO of the given set of parameters; see ``get_gate_times_hmeco`` for details. Otherwise, the gate times will just be retrieved from the ``t_gate_start`` and ``t_gate_end`` parameters. .. warning:: Since the normalization of the likelihood is currently not being calculated, it is recommended that you do not use ``gatefunc``, instead using fixed gate times. Returns ------- dict : Dictionary of detector names -> (gate start, gate width) """ params = self.current_params try: gatefunc = self.current_params['gatefunc'] except KeyError: gatefunc = None if gatefunc == 'hmeco': return self.get_gate_times_hmeco() # gate input for ringdown analysis which consideres a start time # and an end time gatestart = params['t_gate_start'] gateend = params['t_gate_end'] # we'll need the sky location for determining time shifts ra = self.current_params['ra'] dec = self.current_params['dec'] gatetimes = {} for det in self._invpsds: thisdet = Detector(det) # account for the time delay between the waveforms of the # different detectors gatestartdelay = gatestart + thisdet.time_delay_from_earth_center( ra, dec, gatestart) gateenddelay = gateend + thisdet.time_delay_from_earth_center( ra, dec, gateend) dgatedelay = gateenddelay - gatestartdelay gatetimes[det] = (gatestartdelay, dgatedelay) return gatetimes
def batch_project( detector: Detector, extrinsics: Union[np.recarray, Dict[str, np.ndarray]], waveforms: np.ndarray, static_args: Dict[str, Union[str,float]], sample_frequencies: Optional[np.ndarray]=None, distance_scale: bool=False, time_shift: bool=False, ): # get frequency bins (we handle numpy arrays rather than PyCBC arrays with .sample_frequencies attributes) if sample_frequencies is None: sample_frequencies = get_sample_frequencies( f_final=static_args['f_final'], delta_f=static_args['delta_f'] ) # check waveform matrix inputs assert waveforms.shape[1] == 2, "2nd dim in waveforms must be plus and cross polarizations." assert waveforms.shape[0] == len(extrinsics), "waveform batch and extrinsics length must match." if distance_scale: # scale waveform amplitude according to sample d_L parameter scale = static_args.get('distance', 1000) / extrinsics['distance'] # default d_L = 1 waveforms = np.array(waveforms) * scale[:, None, None] # calculate antenna pattern given arrays of extrinsic parameters fp, fc = detector.antenna_pattern( extrinsics['ra'], extrinsics['dec'], extrinsics['psi'], static_args.get('ref_time', 0.) ) # batch project projections = fp[:, None]*waveforms[:, 0, :] + fc[:, None]*waveforms[:, 1, :] # if distance_scale: # # scale waveform amplitude according to sample d_L parameter # scale = static_args.get('distance', 1000) / extrinsics['distance'] # default d_L = 1 # projections *= scale[:, None] if time_shift: assert waveforms.shape[-1] == sample_frequencies.shape[0], "delta_f and fd_length do not match." # calculate geocentric time for the given detector dt = detector.time_delay_from_earth_center(extrinsics['ra'], extrinsics['dec'], static_args.get('ref_time', 0.)) # Calculate time shift due to sampled t_c parameters dt += extrinsics['time'] - static_args.get('ref_time', 0.) # default ref t_c = 0 dt = dt.astype(match_precision(sample_frequencies, real=True)) shift = np.exp(- 2j * np.pi * dt[:, None] * sample_frequencies[None, :]) projections *= shift return projections
def project_onto_detector( detector: Detector, sample: Union[np.recarray, Dict[str, float]], hp: Union[np.ndarray, FrequencySeries], hc: Union[np.ndarray, FrequencySeries], static_args: Dict[str, Union[str, float]], sample_frequencies: Optional[np.ndarray]=None, as_pycbc: bool=True, time_shift: bool=False, ) -> Union[np.ndarray, FrequencySeries]: """Takes a plus and cross waveform polarization (i.e. generated by intrinsic parameters) and projects them onto a specified interferometer using a PyCBC.detector.Detector. """ # input handling assert type(hp) == type(hc), "Plus and cross waveform types must match." if isinstance(hp, FrequencySeries): assert np.all(hp.sample_frequencies == hc.sample_frequencies), "FrequencySeries.sample_frequencies do not match." sample_frequencies = hp.sample_frequencies assert sample_frequencies is not None, "Waveforms not FrequencySeries type or frequency series array not provided." # project intrinsic waveform onto detector fp, fc = detector.antenna_pattern(sample['ra'], sample['dec'], sample['psi'], static_args.get('ref_time', 0.)) h = fp*hp + fc*hc # scale waveform amplitude according to ratio to reference distance h *= static_args.get('distance', 1) / sample['distance'] # default d_L = 1 if time_shift: # Calculate time shift at detector and add to geocentric time dt = detector.time_delay_from_earth_center(sample['ra'], sample['dec'], static_args.get('ref_time', 0.)) dt += sample['time'] - static_args.get('ref_time', 0.) # default ref t_c = 0 dt = dt.astype(match_precision(sample_frequencies)) h *= np.exp(- 2j * np.pi * dt * sample_frequencies).astype(match_precision(h, real=False)) # output desired type if isinstance(h, FrequencySeries): if as_pycbc: return h else: return h.data else: if as_pycbc: return FrequencySeries(h, delta_f=static_args['delta_f'], copy=False) else: return h