18Tools to estimate Nstar and related functions
21from __future__
import division, absolute_import, print_function
31 raise ImportError(
"SWIG wrappings of LAL cannot be imported")
36 raise ImportError(
"SWIG wrappings of LALPulsar cannot be imported")
39def _extract_data_from_prior(prior):
40 """Calculate the input data from the prior
45 For each key in 'Alpha',
'Delta',
'F0',
'F1',
'F2', either a scalar
46 value (
not searched over),
or a pair of the upper
and lower limit.
51 Matrix
with columns being the edges of the uniform bounding box
53 The number of spindowns
55 If true, search includes the sky position
60 keys = ["Alpha",
"Delta",
"F0",
"F1",
"F2"]
61 spindown_keys = keys[3:]
68 for i, key
in enumerate(keys):
69 array_like = isinstance(prior[key], (list, tuple, np.ndarray))
71 raise ValueError(
"Key {}={} not understood".
format(key, prior[key]))
72 elif array_like
and len(prior[key]) == 2:
73 lims.append([prior[key][0], prior[key][1]])
76 elif np.isscalar(prior[key])
or len(prior[key] == 1):
77 scalar_keys.append(key)
79 lims.append([prior[key], 0])
81 unfound_keys.append(key)
83 "Computing Nstar over dimensions {} while {} are scalar and {} unused".
format(
84 lims_keys, scalar_keys, unfound_keys
88 lims_keys = np.array(lims_keys)
95 spindowns = np.sum([np.sum(lims_keys == k)
for k
in spindown_keys])
96 sky = any([key
in lims_keys
for key
in sky_keys])
97 fiducial_freq = np.max(prior[
"F0"])
99 return np.array(p).T, spindowns, sky, fiducial_freq
102def _convert_array_to_gsl_matrix(array):
103 gsl_matrix = lal.gsl_matrix(*array.shape)
104 gsl_matrix.data = array
115 earth_ephem_file="earth00-40-DE405.dat.gz",
116 sun_ephem_file="sun00-40-DE405.dat.gz",
118 """Returns N* estimated from the super-sky metric
120 Nstar is the approximate number of unit-mismatch templates, see
121 https://dcc.ligo.org/P1700455
for further details.
126 Number of semi-coherent segments
128 Reference time
in GPS seconds
129 minStartTime, maxStartTime : int
130 Minimum
and maximum SFT timestamps
132 For each key
in 'Alpha',
'Delta',
'F0',
'F1',
'F2', either a scalar
133 value (
not searched over),
or a pair of the upper
and lower limit.
134 detector_names : list
135 List of detectors to average over, e.g. [
'H1']
140 The estimated approximate number of templates to cover the prior
141 parameter space at a mismatch of unity, assuming the normalised
147 An example
for a directed search where the Nstar can be estimated
from the
148 metric directly. This estimate
is used to define the frequency
and
149 spin-down uncertainty. The calculated estimate using `get_Nstar_estimate`
150 agrees
with this input value.
152 >>>
from lalpulsar
import NstarTools
154 >>> minStartTime = 1000000000
155 >>> duration = 10 * 86400
156 >>> maxStartTime = minStartTime + duration
157 >>> tref = minStartTime + .5*duration
158 >>> detector_names = [
'H1']
165 >>> DeltaF0 = np.sqrt(Nstar) * np.sqrt(3)/(np.pi*duration)
166 >>> DeltaF1 = np.sqrt(Nstar) * np.sqrt(180)/(np.pi*duration**2)
167 >>> prior = {
'F0': [F0-DeltaF0/2., F0+DeltaF0/2],
168 >>>
'F1': [F1-DeltaF1/2., F1+DeltaF1/2],
172 >>>
print NstarTools.get_Nstar_estimate(
173 >>> nsegs, tref, minStartTime, maxStartTime, prior, detector_names)
179 To see detailed information about each set of dimensions Nstar, add the
182 >>> logging.basicConfig(level=logging.DEBUG)
185 detector_names = list(detector_names)
187 in_phys, spindowns, sky, fiducial_freq = _extract_data_from_prior(prior)
188 out_rssky = np.zeros(in_phys.shape)
191 in_phys[2:] = in_phys[2:][::-1]
193 in_phys = _convert_array_to_gsl_matrix(in_phys)
194 out_rssky = _convert_array_to_gsl_matrix(out_rssky)
196 tboundaries = np.linspace(minStartTime, maxStartTime, nsegs + 1)
198 ref_time = lal.LIGOTimeGPS(tref)
199 segments = lal.SegListCreate()
200 for j
in range(len(tboundaries) - 1):
202 lal.LIGOTimeGPS(tboundaries[j]), lal.LIGOTimeGPS(tboundaries[j + 1]), j
204 lal.SegListAppend(segments, seg)
205 detNames = lal.CreateStringVector(*detector_names)
206 detectors = lalpulsar.MultiLALDetector()
207 lalpulsar.ParseMultiLALDetector(detectors, detNames)
208 detector_weights =
None
209 detector_motion = lalpulsar.DETMOTION_SPIN + lalpulsar.DETMOTION_ORBIT
210 ephemeris = lalpulsar.InitBarycenter(earth_ephem_file, sun_ephem_file)
212 SSkyMetric = lalpulsar.ComputeSuperskyMetrics(
213 lalpulsar.SUPERSKY_METRIC_TYPE,
223 except RuntimeError
as e:
224 logging.warning(
"Encountered run-time error {}".
format(e))
225 raise RuntimeError(
"Calculation of the SSkyMetric failed")
232 lalpulsar.ConvertPhysicalToSuperskyPoints(
233 out_rssky, in_phys, SSkyMetric.semi_rssky_transf
237 g = SSkyMetric.semi_rssky_metric.data
239 g[2:, 2:] = g[2:, 2:][::-1, ::-1]
246 parallelepiped = (d[:, 1:].T - d[:, 0]).T
248 labels = np.array([
"Alpha",
"Delta",
"F0",
"F1",
"F2"])[i:]
252 for j
in range(1, len(g) + 1):
253 for idx
in itertools.combinations(np.arange(len(g)), j):
255 dV = np.abs(np.linalg.det(parallelepiped[idx][:, idx]))
256 sqrtdetG = np.sqrt(np.abs(np.linalg.det(g[idx][:, idx])))
257 Nstars[
"".join(labels[idx])] = sqrtdetG * dV
258 logging.debug(pprint.pformat(Nstars))
259 return np.max(Nstars.values())