Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALBurst 2.0.7.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Macros Modules Pages
offsetvector.py
Go to the documentation of this file.
1# Copyright (C) 2010--2013,2015,2016,2018 Kipp Cannon
2#
3# This program is free software; you can redistribute it and/or modify it
4# under the terms of the GNU General Public License as published by the
5# Free Software Foundation; either version 2 of the License, or (at your
6# option) any later version.
7#
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11# Public License for more details.
12#
13# You should have received a copy of the GNU General Public License along
14# with this program; if not, write to the Free Software Foundation, Inc.,
15# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
17
18#
19# =============================================================================
20#
21# Preamble
22#
23# =============================================================================
24#
25
26
27import itertools
28
29
30__author__ = "Kipp Cannon <kipp.cannon@ligo.org>"
31from .git_version import date as __date__
32from .git_version import version as __version__
33
34
35#
36# =============================================================================
37#
38# Offset Vector
39#
40# =============================================================================
41#
42
43
44class offsetvector(dict):
45 """
46 Subclass of the dict built-in type for storing mappings of
47 instrument to time offset.
48
49 Examples:
50
51 >>> x = offsetvector({"H1": 0, "L1": 10, "V1": 20})
52 >>> x["H1"]
53 0
54 >>> not any(x.values()) # check for "zero-lag"
55 False
56 """
57 @property
58 def refkey(self):
59 """
60 = min(self)
61
62 Raises ValueError if the offsetvector is empty.
63 """
64 # min() emits ValueError when the list is empty, but it
65 # might also emit a ValueError if the comparison operations
66 # inside it fail, so we can't simply wrap it in a
67 # try/except pair or we might mask genuine failures
68 if not self:
69 raise ValueError("offsetvector is empty")
70 return min(self)
71
72 @property
73 def deltas(self):
74 """
75 Dictionary of relative offsets. The keys in the result are
76 pairs of keys from the offset vector, (a, b), and the
77 values are the relative offsets, (offset[b] - offset[a]).
78 Raises ValueError if the offsetvector is empty (WARNING:
79 this behaviour might change in the future).
80
81 Example:
82
83 >>> x = offsetvector({"H1": 0, "L1": 10, "V1": 20})
84 >>> assert x.deltas == {('H1', 'L1'): 10, ('H1', 'V1'): 20, ('H1', 'H1'): 0}
85 >>> y = offsetvector({'H1': 100, 'L1': 110, 'V1': 120})
86 >>> y.deltas == x.deltas
87 True
88
89 Note that the result always includes a "dummy" entry,
90 giving the relative offset of self.refkey with respect to
91 itself, which is always 0.
92
93 See also .fromdeltas().
94
95 BUGS: I think the keys in each tuple should be reversed.
96 I can't remember why I put them in the way they are.
97 Expect them to change in the future.
98 """
99 # FIXME: instead of raising ValueError when the
100 # offsetvector is empty this should return an empty
101 # dictionary. the inverse, .fromdeltas() accepts
102 # empty dictionaries
103 # NOTE: the arithmetic used to construct the offsets
104 # *must* match the arithmetic used by
105 # time_slide_component_vectors() so that the results of the
106 # two functions can be compared to each other without worry
107 # of floating-point round off confusing things.
108 refkey = self.refkey
109 refoffset = self[refkey]
110 return dict(((refkey, key), self[key] - refoffset) for key in self)
111
112 def __str__(self, compact = False):
113 """
114 Return a human-readable string representation of an offset
115 vector.
116
117 Example:
118
119 >>> a = offsetvector({"H1": -10.1234567, "L1": 0.125})
120 >>> str(a)
121 'H1 = -10.1234567 s, L1 = +0.125 s'
122 >>> a.__str__(compact = True)
123 'H1=-10.123,L1=0.125'
124 """
125 if compact:
126 return ",".join(("%s=%.5g" % x) for x in sorted(self.items()))
127 return ", ".join(("%s = %+.16g s" % x) for x in sorted(self.items()))
128
129 def __repr__(self):
130 """
131 Return a string representation of the offset vector.
132 Running eval() on the result reconstructs the offsetvector.
133
134 Example:
135
136 >>> a = offsetvector({"H1": -10.1234567, "L1": 0.1})
137 >>> b = eval(repr(a))
138 >>> b == a
139 True
140 >>> b is a
141 False
142 >>> c = offsetvector({"H1": -10.1234567})
143 >>> repr(c)
144 "offsetvector({'H1': -10.1234567})"
145 """
146 return "%s(%s)" % (self.__class__.__name__, dict.__repr__(self))
147
148 def __abs__(self):
149 """
150 Returns max(offset) - min(offset).
151
152 Example:
153
154 >>> abs(offsetvector({"H1": 0.0, "H2": 0.0, "L1": 0.0}))
155 0.0
156 >>> abs(offsetvector({"H1": 10.0, "H2": 10.0, "L1": 10.0}))
157 0.0
158 >>> abs(offsetvector({'H1': 10.0, 'L1': 0.0, 'V1': -10.0}))
159 20.0
160 """
161 return max(self.values()) - min(self.values())
162
163 def contains(self, other):
164 """
165 Returns True if offset vector other can be found in self,
166 False otherwise. An offset vector is "found in" another
167 offset vector if the latter contains all of the former's
168 instruments and the relative offsets among those
169 instruments are equal (the absolute offsets need not be).
170
171 Example:
172
173 >>> a = offsetvector({"H1": 10, "L1": 20, "V1": 30})
174 >>> b = offsetvector({"H1": 20, "V1": 40})
175 >>> a.contains(b)
176 True
177
178 Note the distinction between this and the "in" operator:
179
180 >>> "H1" in a
181 True
182 """
183 return offsetvector((key, offset) for key, offset in self.items() if key in other).deltas == other.deltas
184
185 def normalize(self, **kwargs):
186 """
187 Adjust the offsetvector so that a particular instrument has
188 the desired offset. All other instruments have their
189 offsets adjusted so that the relative offsets are
190 preserved. The instrument to noramlize, and the offset one
191 wishes it to have, are provided as a key-word argument.
192 The return value is the time slide dictionary, which is
193 modified in place.
194
195 If more than one key-word argument is provided the keys are
196 sorted and considered in order until a key is found that is
197 in the offset vector. The offset vector is normalized to
198 that value. This function is a no-op if no key-word
199 argument is found that applies.
200
201 Example:
202
203 >>> a = offsetvector({"H1": -10, "H2": -10, "L1": -10})
204 >>> assert a.normalize(L1 = 0) == offsetvector({'H2': 0, 'H1': 0, 'L1': 0})
205 >>> a = offsetvector({"H1": -10, "H2": -10})
206 >>> assert a.normalize(L1 = 0, H2 = 5) == offsetvector({'H2': 5, 'H1': 5})
207 """
208 # FIXME: should it be performed in place? if it should
209 # be, the should there be no return value?
210 for key, offset in sorted(kwargs.items()):
211 if key in self:
212 delta = offset - self[key]
213 for key in self.keys():
214 self[key] += delta
215 break
216 return self
217
218 @classmethod
219 def fromdeltas(cls, deltas):
220 """
221 Construct an offsetvector from a dictionary of offset
222 deltas as returned by the .deltas attribute.
223
224 Example:
225
226 >>> x = offsetvector({"H1": 0, "L1": 10, "V1": 20})
227 >>> y = offsetvector.fromdeltas(x.deltas)
228 >>> y == x
229 True
230
231 See also .deltas, .fromkeys()
232 """
233 return cls((key, value) for (refkey, key), value in deltas.items())
234
235
236#
237# =============================================================================
238#
239# Utilities
240#
241# =============================================================================
242#
243
244
245def component_offsetvectors(offsetvectors, n):
246 """
247 Given an iterable of offset vectors, return the shortest list of
248 the unique n-instrument offset vectors from which all the vectors
249 in the input iterable can be constructed. This can be used to
250 determine the minimal set of n-instrument coincs required to
251 construct all of the coincs for all of the requested instrument and
252 offset combinations in a set of offset vectors.
253
254 It is assumed that the coincs for the vector {"H1": 0, "H2": 10,
255 "L1": 20} can be constructed from the coincs for the vectors {"H1":
256 0, "H2": 10} and {"H2": 0, "L1": 10}, that is only the relative
257 offsets are significant in determining if two events are
258 coincident, not the absolute offsets.
259 """
260 #
261 # collect unique instrument set / deltas combinations
262 #
263
264 delta_sets = {}
265 for vect in offsetvectors:
266 for instruments in itertools.combinations(sorted(vect), n):
267 # NOTE: the arithmetic used to construct the
268 # offsets *must* match the arithmetic used by
269 # offsetvector.deltas so that the results of the
270 # two can be compared to each other without worry
271 # of floating-point round off confusing things.
272 delta_sets.setdefault(instruments, set()).add(tuple(vect[instrument] - vect[instruments[0]] for instrument in instruments))
273
274 #
275 # translate into a list of normalized n-instrument offset vectors
276 #
277
278 return [offsetvector(zip(instruments, deltas)) for instruments, delta_set in delta_sets.items() for deltas in delta_set]
static double max(double a, double b)
Definition: EPFilters.c:43
static double min(double a, double b)
Definition: EPFilters.c:42
Subclass of the dict built-in type for storing mappings of instrument to time offset.
Definition: offsetvector.py:56
def __abs__(self)
Returns max(offset) - min(offset).
def normalize(self, **kwargs)
Adjust the offsetvector so that a particular instrument has the desired offset.
def __str__(self, compact=False)
Return a human-readable string representation of an offset vector.
def fromdeltas(cls, deltas)
Construct an offsetvector from a dictionary of offset deltas as returned by the .deltas attribute.
def contains(self, other)
Returns True if offset vector other can be found in self, False otherwise.
def __repr__(self)
Return a string representation of the offset vector.
def deltas(self)
Dictionary of relative offsets.
Definition: offsetvector.py:98
def component_offsetvectors(offsetvectors, n)
Given an iterable of offset vectors, return the shortest list of the unique n-instrument offset vecto...