From 209c5ed1e079f9386e7a167f776bbe4a7d1da02b Mon Sep 17 00:00:00 2001 From: Chad Hanna <chad.hanna@ligo.org> Date: Sun, 24 Mar 2019 13:17:02 -0400 Subject: [PATCH] WIP --- gstlal-ugly/bin/gstlal_inspiral_treebank | 26 +++-- gstlal-ugly/python/metric.py | 51 ++++------ gstlal-ugly/python/tree.py | 122 ++++++++--------------- 3 files changed, 75 insertions(+), 124 deletions(-) diff --git a/gstlal-ugly/bin/gstlal_inspiral_treebank b/gstlal-ugly/bin/gstlal_inspiral_treebank index 3a5f775a5c..0c3d368326 100755 --- a/gstlal-ugly/bin/gstlal_inspiral_treebank +++ b/gstlal-ugly/bin/gstlal_inspiral_treebank @@ -19,12 +19,18 @@ import itertools import numpy -from ligo.lw import ligolw -from ligo.lw import lsctables -from ligo.lw import table -from ligo.lw import utils -from ligo.lw import ilwd -from ligo.lw.utils import process as ligolw_process +#from ligo.lw import ligolw +#from ligo.lw import lsctables +#from ligo.lw import table +#from ligo.lw import utils +#from ligo.lw import ilwd +#from ligo.lw.utils import process as ligolw_process +from glue.ligolw import ligolw +from glue.ligolw import lsctables +from glue.ligolw import table +from glue.ligolw import utils +from glue.ligolw import ilwd +from glue.ligolw.utils import process as ligolw_process from gstlal import metric as metric_module from gstlal import tree # FIXME dont do this @@ -165,7 +171,7 @@ def coord_func(coords, positions = positions): out[pi] = coords[i] return out -if True:#args.mcm2: +if False:#args.mcm2: coord_func = metric_module.M_q_func else: coord_func = coord_func @@ -187,17 +193,17 @@ def trans_M_q(coord_limits): m2limis = [coord_limits[1][0] * 0.9, coord_limits[1][1] * 1.256789] return [Mlimits] + [m2limis] + coord_limits[2:] -if True:#args.mcm2: +if False:#args.mcm2: coord_limits_2 = trans_M_q(coord_limits) if args.min_mc: coord_limits_2[0][0] = max(coord_limits_2[0][0], args.min_mc) if args.max_mc: coord_limits_2[0][1] = min(coord_limits_2[0][1], args.max_mc) print coord_limits_2 - bank = Node(HyperCube(numpy.array(coord_limits_2), mismatch, constraint_func = lambda x: tree.mass_sym_constraint_mc(x, args.max_q, args.max_mtotal, coord_limits[0], coord_limits[1], coord_limits_2[0]), metric = g_ij, singularity = tree.mc_m2_singularity)) + bank = Node(HyperCube(numpy.array(coord_limits_2), mismatch, constraint_func = lambda x: tree.mass_sym_constraint_mc(x, args.max_q, args.max_mtotal, coord_limits[0], coord_limits[1], coord_limits_2[0]), metric = g_ij)) else: coord_limits_2 = coord_limits - bank = Node(HyperCube(numpy.array(coord_limits_2), mismatch, constraint_func = lambda x: tree.mass_sym_constraint(x, args.max_q, args.max_mtotal), metric = g_ij, singularity = tree.m1_m2_singularity)) + bank = Node(HyperCube(numpy.array(coord_limits_2), mismatch, constraint_func = lambda x: tree.mass_sym_constraint(x, args.max_q, args.max_mtotal), metric = g_ij)) if args.verbose: diff --git a/gstlal-ugly/python/metric.py b/gstlal-ugly/python/metric.py index bf40750f6e..63a9584e81 100644 --- a/gstlal-ugly/python/metric.py +++ b/gstlal-ugly/python/metric.py @@ -21,14 +21,15 @@ from lal import series from scipy import integrate import numpy from gstlal import reference_psd -from ligo.lw import utils as ligolw_utils +#from ligo.lw import utils as ligolw_utils +from glue.ligolw import utils as ligolw_utils import itertools import scipy from lal import LIGOTimeGPS import sys import math -DELTA = 2.5e-7#2.0e-7 +DELTA = 2e-7#2.0e-7 EIGEN_DELTA_DET = DELTA # Round a number up to the nearest power of 2 @@ -156,7 +157,6 @@ class Metric(object): self.flow = flow self.fhigh = fhigh self.working_length = int(round(self.duration * 2 * self.fhigh)) + 1 - print self.working_length self.psd = reference_psd.interpolate_psd(series.read_psd_xmldoc(ligolw_utils.load_filename(psd_xml, verbose = True, contenthandler = series.PSDContentHandler)).values()[0], self.df) self.metric_tensor = None self.metric_is_valid = False @@ -301,12 +301,13 @@ class Metric(object): minus_match_minus_1 = self.match_minus_1(w1, wm[j,j], t_factor = self.neg_t_factor) return -0.5 * (plus_match_minus_1 + minus_match_minus_1 - ftt - fjj) / 2 / delta_t / deltas[j] - def __call__(self, center, deltas = None): - + def __call__(self, center):#, deltas = None): + center = numpy.array(center) g = numpy.zeros((len(center), len(center)), dtype=numpy.double) w1 = self.waveform(center) wp = {} wm = {} + deltas = abs(center)**.5 * DELTA + DELTA for i, x in enumerate(deltas): for j, y in enumerate(deltas): dx = numpy.zeros(len(deltas)) @@ -335,41 +336,21 @@ class Metric(object): for i, j in itertools.product(range(len(deltas)), range(len(deltas))): g[i,j] = g[i,j] - g_tj[i] * g_tj[j] / g_tt - #print "before ", g - #g = numpy.array(nearPD(g, nit=3)) - try: - U, S, V = numpy.linalg.svd(g) - except numpy.linalg.linalg.LinAlgError: - newc = center.copy() - newc[0:2] *=0.99 - return self.__call__(newc, deltas) + U, S, V = numpy.linalg.svd(g) + #try: + # U, S, V = numpy.linalg.svd(g) + #except numpy.linalg.linalg.LinAlgError: + # print "svd error" + # newc = center.copy() + # newc[0:2] *=0.99 + # return self.__call__(newc)#, deltas) condition = S < max(S) * EIGEN_DELTA_DET - S[condition] = 0.0 + S[condition] = EIGEN_DELTA_DET g = numpy.dot(U, numpy.dot(numpy.diag(S), V)) det = numpy.product(S[S>0]) eff_dimension = len(S[S>0]) w = S - #try: - # w, v = numpy.linalg.eigh(g) - #except numpy.linalg.linalg.LinAlgError: - # newc = center.copy() - # newc[0:2] -= deltas[0:2] - # return self.__call__(newc, deltas) - #mxw = numpy.max(w) - #assert numpy.all(w > 0) - #if numpy.any(w < 0): - # print w - # return self.__call__(center - deltas, deltas) self.metric_is_valid = True - #w[w<EIGEN_DELTA_DET * mxw] = EIGEN_DELTA_DET * mxw - #det = numpy.product(w) - - #eff_dimension = len(w[w >= EIGEN_DELTA_DET * mxw]) - #w[w<EIGEN_DELTA_METRIC * mxw] = EIGEN_DELTA_METRIC * mxw - #g = numpy.dot(numpy.dot(v, numpy.abs(numpy.diag(w))), v.T) - - #return g, eff_dimension, numpy.product(S[S>0]) - #print "after ", g return g, eff_dimension, det, self.metric_is_valid, w @@ -386,6 +367,8 @@ class Metric(object): delta = x-y return (dot(delta, delta, metric_tensor))**.5 + def volume_element(self, metric_tensor): + return abs(numpy.linalg.det(metric_tensor))**.5 def metric_match(self, metric_tensor, c1, c2): d2 = self.distance(metric_tensor, c1, c2)**2 diff --git a/gstlal-ugly/python/tree.py b/gstlal-ugly/python/tree.py index a0e0adab80..daf185f31b 100644 --- a/gstlal-ugly/python/tree.py +++ b/gstlal-ugly/python/tree.py @@ -98,29 +98,9 @@ def packing_density(n): if n==8: return prefactor * numpy.pi**4 / 384 -def mc_m2_singularity(c): - center = c.copy() - m1, m2 = metric_module.m1_from_mc_m2(center[0], center[1]), center[1] - if .80 < m1 / m2 <= 1.0: - m1 = 0.80 * m2 - elif 1.0 < m1 / m2 <= 1.25: - m2 = 0.80 * m1 - mc = metric_module.mc_from_m1_m2(m1, m2) - center[0] = mc - center[1] = m2 - return center - -def m1_m2_singularity(c): - center = c.copy() - return center - F = 1. - if F*.95 < center[0] / center[1] <= F * 1.05: - center[1] = 0.95 * center[0] - return center - class HyperCube(object): - def __init__(self, boundaries, mismatch, constraint_func = mass_sym_constraint, metric = None, metric_tensor = None, effective_dimension = None, det = None, singularity = None, metric_is_valid = False, eigv = None): + def __init__(self, boundaries, mismatch, constraint_func = mass_sym_constraint, metric = None, metric_tensor = None, effective_dimension = None, det = None, metric_is_valid = False, eigv = None): """ Define a hypercube with boundaries given by boundaries, e.g., @@ -141,24 +121,8 @@ class HyperCube(object): self.center = numpy.array([c[0] + (c[1] - c[0]) / 2. for c in boundaries]) self.deltas = numpy.array([c[1] - c[0] for c in boundaries]) self.metric = metric - # FIXME don't assume m1 m2 and the spin coords are the coordinates we have here. - deltas = DELTA * numpy.ones(len(self.center)) - deltas[0:2] *= self.center[0:2]**.5 - self.singularity = singularity - if self.metric is not None and metric_tensor is None: - #try: - if self.singularity is not None: - center = self.singularity(self.center) - else: - center = self.center - try: - self.metric_tensor, self.effective_dimension, self.det, self.metric_is_valid, self.eigv = self.metric(center, deltas) - except ValueError: - center *= 0.99 - self.metric_tensor, self.effective_dimension, self.det, self.metric_is_valid, self.eigv = self.metric(center, deltas) - # print "metric @", self.center, " failed, trying, ", self.center - self.deltas / 2. - # self.metric_tensor, self.effective_dimension, self.det = self.metric(self.center - self.deltas / 2., deltas) + self.metric_tensor, self.effective_dimension, self.det, self.metric_is_valid, self.eigv = self.metric(self.center) else: self.metric_tensor = metric_tensor self.effective_dimension = effective_dimension @@ -212,9 +176,9 @@ class HyperCube(object): leftbound[dim,1] = self.center[dim] rightbound[dim,0] = self.center[dim] if reuse_metric: - return HyperCube(leftbound, self.__mismatch, self.constraint_func, metric = self.metric, metric_tensor = self.metric_tensor, effective_dimension = self.effective_dimension, det = self.det, singularity = self.singularity, metric_is_valid = self.metric_is_valid, eigv = self.eigv), HyperCube(rightbound, self.__mismatch, self.constraint_func, metric = self.metric, metric_tensor = self.metric_tensor, effective_dimension = self.effective_dimension, det = self.det, singularity = self.singularity, metric_is_valid = self.metric_is_valid, eigv = self.eigv) + return HyperCube(leftbound, self.__mismatch, self.constraint_func, metric = self.metric, metric_tensor = self.metric_tensor, effective_dimension = self.effective_dimension, det = self.det, metric_is_valid = self.metric_is_valid, eigv = self.eigv), HyperCube(rightbound, self.__mismatch, self.constraint_func, metric = self.metric, metric_tensor = self.metric_tensor, effective_dimension = self.effective_dimension, det = self.det, metric_is_valid = self.metric_is_valid, eigv = self.eigv) else: - return HyperCube(leftbound, self.__mismatch, self.constraint_func, metric = self.metric, singularity = self.singularity), HyperCube(rightbound, self.__mismatch, self.constraint_func, metric = self.metric, singularity = self.singularity) + return HyperCube(leftbound, self.__mismatch, self.constraint_func, metric = self.metric), HyperCube(rightbound, self.__mismatch, self.constraint_func, metric = self.metric) def tile(self, mismatch, stochastic = False): self.tiles.append(self.center) @@ -241,8 +205,6 @@ class HyperCube(object): def volume(self, metric_tensor = None): if metric_tensor is None: metric_tensor = self.metric_tensor - #return numpy.product(self.deltas) * numpy.linalg.det(metric_tensor)**.5 - #print "volume ", numpy.product(self.deltas) * self.det**.5 return numpy.product(self.deltas) * self.det**.5 def coord_volume(self): @@ -284,54 +246,54 @@ class Node(object): if vertex not in self.boundary: self.on_boundary = True print "\n\non boundary!!\n\n" - #self.on_boundary = numpy.any((self.cube.center + self.cube.deltas) == (self.boundary.center + self.boundary.deltas)) or numpy.any((self.cube.center - self.cube.deltas) == (self.boundary.center - self.boundary.deltas)) - - def split(self, split_num_templates, mismatch, bifurcation = 0, verbose = True, metric_tol = 0.01, max_coord_vol = float(10)): - size = self.cube.num_tmps_per_side(mismatch) - #if max(self.cube.deltas) / min(self.cube.deltas) > 100.0: - # self.splitdim = numpy.argmax(self.cube.deltas) - #else: - self.splitdim = numpy.argmax(size) - - if not self.parent: - numtmps = float("inf") - par_numtmps = float("inf") - volume_split_condition = False - metric_diff = 1.0 - metric_cond = True - else: - # Get the number of parent templates - par_numtmps = self.parent.cube.num_templates(mismatch) - # get the number of sibling templates - sib_numtmps = self.sibling.cube.num_templates(mismatch) + def split(self, split_num_templates, mismatch, bifurcation = 0, verbose = True, metric_tol = 0.03, max_coord_vol = float(10)): + if self.cube.constraint_func(self.cube.vertices + [self.cube.center]): + size = self.cube.num_tmps_per_side(mismatch) + self.splitdim = numpy.argmax(size) + + if not self.parent: + numtmps = float("inf") + par_numtmps = float("inf") + volume_split_condition = False + metric_diff = 1.0 + metric_cond = True + else: + # Get the number of parent templates + par_numtmps = self.parent.cube.num_templates(mismatch) - # get our number of templates - numtmps = self.cube.num_templates(mismatch) + # get the number of sibling templates + sib_numtmps = self.sibling.cube.num_templates(mismatch) + # get our number of templates + numtmps = self.cube.num_templates(mismatch) - metric_diff = max(abs(self.cube.deltas / self.cube.size - self.sibling.cube.deltas / self.sibling.cube.size) / (self.cube.deltas / self.cube.size)) - #metric_diff = self.cube.metric_tensor - self.sibling.cube.metric_tensor - #metric_diff = numpy.linalg.norm(metric_diff) / numpy.linalg.norm(self.cube.metric_tensor)**.5 / numpy.linalg.norm(self.sibling.cube.metric_tensor)**.5 + #print "self metric:\n", self.cube.metric_tensor + #print "sibling metric:\n", self.sibling.cube.metric_tensor + #print "parent metric:\n", self.parent.cube.metric_tensor - metric_diff2 = max(abs(self.cube.deltas / self.cube.size - self.parent.cube.deltas / self.parent.cube.size) / self.cube.deltas / self.cube.size) - #metric_diff2 = self.cube.metric_tensor - self.parent.cube.metric_tensor - #metric_diff2 = numpy.linalg.norm(metric_diff2) / numpy.linalg.norm(self.cube.metric_tensor)**.5 / numpy.linalg.norm(self.parent.cube.metric_tensor)**.5 + #print self.cube.metric_tensor, self.sibling.cube.metric_tensor, self.parent.cube.metric_tensor + metric_diff = self.cube.metric_tensor - self.sibling.cube.metric_tensor + metric_diff = numpy.linalg.norm(metric_diff) / numpy.linalg.norm(self.cube.metric_tensor)**.5 / numpy.linalg.norm(self.sibling.cube.metric_tensor)**.5 + metric_diff2 = self.cube.metric_tensor - self.parent.cube.metric_tensor + metric_diff2 = numpy.linalg.norm(metric_diff2) / numpy.linalg.norm(self.cube.metric_tensor)**.5 / numpy.linalg.norm(self.parent.cube.metric_tensor)**.5 - metric_diff = max(metric_diff, metric_diff2) - # take the bigger of self, sibling and parent - numtmps = max(max(numtmps, par_numtmps/2.0), sib_numtmps) + #print metric_diff, metric_diff2 - #mts = [(numtmps, self.cube), (sib_numtmps, self.sibling.cube), (par_numtmps / 2., self.parent.cube)] - reuse_metric = self.cube #max(mts)[1] + metric_diff = max(metric_diff, metric_diff2) + #print "metric diff: ", metric_diff, "\n" + # take the bigger of self, sibling and parent + numtmps = max(max(numtmps, par_numtmps/2.0), sib_numtmps) - #if self.cube.constraint_func(self.cube.vertices + [self.cube.center]) and ((numtmps >= split_num_templates) or (metric_diff > metric_tol and numtmps > split_num_templates)) or bifurcation < 2: - tmps_per_side = self.cube.num_tmps_per_side(mismatch) - if self.cube.constraint_func(self.cube.vertices + [self.cube.center]): + reuse_metric = self.cube #max(mts)[1] + + tmps_per_side = self.cube.num_tmps_per_side(mismatch) # NOTE FIXME work out correct max templates per side - if ((numtmps >= split_num_templates) or max(tmps_per_side) > 2 * len(size)**.5 ) or bifurcation < 2: + if (numtmps >= split_num_templates) or bifurcation < 2 or metric_diff > metric_tol: + #print "splitting" bifurcation += 1 - if metric_diff <= metric_tol and (numtmps < 5**(len(size))) and self.cube.coord_volume() < max_coord_vol: + if metric_diff <= metric_tol: + print "reuse metric" self.cube.metric_tensor = reuse_metric.metric_tensor self.cube.effective_dimension = reuse_metric.effective_dimension self.cube.det = reuse_metric.det -- GitLab