From 83bfb64e60c0b5efc99b350aaa28a91fbd93e975 Mon Sep 17 00:00:00 2001
From: Chad Hanna <crh184@psu.edu>
Date: Thu, 18 May 2017 12:34:15 -0400
Subject: [PATCH] metric.py: put in proper t spacing

---
 gstlal-ugly/python/metric.py | 67 +++++++++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 17 deletions(-)

diff --git a/gstlal-ugly/python/metric.py b/gstlal-ugly/python/metric.py
index eb8937e86f..8b79b2c0f0 100644
--- a/gstlal-ugly/python/metric.py
+++ b/gstlal-ugly/python/metric.py
@@ -25,6 +25,18 @@ import itertools
 import scipy
 from lal import LIGOTimeGPS
 import sys
+import math
+
+# Round a number up to the nearest power of 2
+def ceil_pow_2(x):
+	x = int(math.ceil(x))
+	x -= 1
+	n = 1
+	while n and (x & (x + 1)):
+		x |= x >> n
+		n *= 2
+	return x + 1
+
 
 def add_quadrature_phase(fseries, n):
 	"""
@@ -110,10 +122,15 @@ class Metric(object):
 		self.metric_tensor = None
 		self.metric_is_valid = False
 		self.revplan = lal.CreateReverseCOMPLEX16FFTPlan(self.working_length, 1)
-		# 3 microsecond offset
-		self.delta_t = 3e-6
-		self.t_factor = numpy.exp(-2j * numpy.pi * (numpy.arange(self.working_length) * self.df - self.fhigh) * self.delta_t)
-		self.neg_t_factor = numpy.exp(-2j * numpy.pi * (numpy.arange(self.working_length) * self.df - self.fhigh) * (-self.delta_t))
+		#FIXME
+		self.delta_t = {}
+		self.t_factor = {}
+		self.neg_t_factor = {}
+		for t in numpy.array([1.,2.,4.,8.,16.,32.,64.,128.,256.,512.,1024]):
+			self.delta_t[t] = 5e-6 * 1 * t # 1 M time spacing
+			print self.delta_t[t]
+			self.t_factor[t] = numpy.exp(-2j * numpy.pi * (numpy.arange(self.working_length) * self.df - self.fhigh) * self.delta_t[t])
+			self.neg_t_factor[t] = numpy.exp(-2j * numpy.pi * (numpy.arange(self.working_length) * self.df - self.fhigh) * (-self.delta_t[t]))
 		self.tseries = lal.CreateCOMPLEX16TimeSeries(
 			name = "workspace",
 			epoch = 0,
@@ -179,18 +196,16 @@ class Metric(object):
 			return None
 		return fseries
 
-	def match(self, w1, w2, dt = None):
+	def match(self, w1, w2, t_factor = None):
 		def norm(w):
 			n = numpy.real((numpy.conj(w) * w).sum())**.5
 			return n
 
 		try:
-			if dt is None:
+			if t_factor is None:
 				self.w1w2.data.data[:] = numpy.conj(w1.data.data) * w2.data.data
-			elif dt == "neg":
-				self.w1w2.data.data[:] = numpy.conj(w1.data.data) * w2.data.data * self.neg_t_factor
-			elif dt == "pos":
-				self.w1w2.data.data[:] = numpy.conj(w1.data.data) * w2.data.data * self.t_factor
+			else:
+				self.w1w2.data.data[:] = numpy.conj(w1.data.data) * w2.data.data * t_factor
 			m = numpy.real(numpy.abs(self.w1w2.data.data[:].sum())) / norm(w1.data.data) / norm(w2.data.data)
 			if m > 1.0000001:
 				raise ValueError("Match is greater than 1 : %f" % m)
@@ -231,10 +246,13 @@ class Metric(object):
 
 	def __set_tt_metric_tensor_component(self, center, w1):
 
-		minus_match = self.match(w1, w1, dt = "neg")
-		plus_match = self.match(w1, w1, dt = "pos")
-		d2mbydx2 = (plus_match + minus_match - 2.0) / self.delta_t**2
-		return -0.5 * d2mbydx2, self.delta_t
+		# FIXME FIXME assumes m1 and m2 are first coords
+		M = center[0] + center[1]
+		ix = ceil_pow_2(M)
+		minus_match = self.match(w1, w1, t_factor = self.neg_t_factor[ix])
+		plus_match = self.match(w1, w1, t_factor = self.t_factor[ix])
+		d2mbydx2 = (plus_match + minus_match - 2.0) / self.delta_t[ix]**2
+		return -0.5 * d2mbydx2, self.delta_t[ix]
 
 	def __set_offdiagonal_metric_tensor_component(self, (i,j), center, deltas, g, w1):
 		# evaluate symmetrically
@@ -261,6 +279,9 @@ class Metric(object):
 		return None
 
 	def __set_offdiagonal_time_metric_tensor_component(self, j, center, deltas, g, g_tt, delta_t, w1):
+		# FIXME FIXME assumes m1 and m2 are first coords
+		M = center[0] + center[1]
+		ix = ceil_pow_2(M)
 		# make the vector to solve for the metric by choosing
 		# either a principle axis or a bisector depending on if
 		# this is a diagonal component or not
@@ -270,8 +291,8 @@ class Metric(object):
 		ftt = -2 * g_tt * delta_t**2 + 2.0
 
 		# Second order
-		plus_match = self.match(w1, self.waveform(center+x), dt="pos")
-		minus_match = self.match(w1, self.waveform(center-x), dt="neg")
+		plus_match = self.match(w1, self.waveform(center+x), t_factor = self.t_factor[ix])
+		minus_match = self.match(w1, self.waveform(center-x), t_factor = self.neg_t_factor[ix])
 		return -0.5 * (plus_match + minus_match - ftt - fjj + 2.0) / 2 / delta_t / deltas[j]
 
 	def __call__(self, center, deltas = None, thresh = 1. * numpy.finfo(numpy.float32).eps):
@@ -323,4 +344,16 @@ class Metric(object):
 
 
 	def explicit_match(self, c1, c2):
-		return self.match(self.waveform(c1), self.waveform(c2))
+		def fftmatch(w1, w2):
+			def norm(w):
+				n = numpy.real((numpy.conj(w) * w).sum())**.5 / self.duration**.5
+				return n
+
+			self.w1w2.data.data[:] = numpy.conj(w1.data.data) * w2.data.data
+			lal.COMPLEX16FreqTimeFFT(self.tseries, self.w1w2, self.revplan)
+			m = numpy.real(numpy.abs(numpy.array(self.tseries.data.data)).max()) / norm(w1.data.data) / norm(w2.data.data)
+			if m > 1.0000001:
+				raise ValueError("Match is greater than 1 : %f" % m)
+			return m
+
+		return fftmatch(self.waveform(c1), self.waveform(c2))
-- 
GitLab