Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-3a66518
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
utils/series.py
Go to the documentation of this file.
1# Copyright (C) 2013 Duncan Macleod
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 3 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"""Methods to generate LAL Time- and FrequencySeries objects in python
18"""
19
20import numpy
21import re
22
23from .. import lal
24
25__author__ = "Duncan Macleod <duncan.macleod@ligo.org>"
26
27# -----------------------------------------------------------------------------
28# utility constants
29
30# map LAL type codes to strings (for function factory)
31LAL_TYPE_STR = {
32 lal.I2_TYPE_CODE: 'INT2',
33 lal.I4_TYPE_CODE: 'INT4',
34 lal.I8_TYPE_CODE: 'INT8',
35 lal.U2_TYPE_CODE: 'UINT2',
36 lal.U4_TYPE_CODE: 'UINT4',
37 lal.U8_TYPE_CODE: 'UINT8',
38 lal.S_TYPE_CODE: 'REAL4',
39 lal.D_TYPE_CODE: 'REAL8',
40 lal.C_TYPE_CODE: 'COMPLEX8',
41 lal.Z_TYPE_CODE: 'COMPLEX16',
42}
43LAL_TYPE_FROM_STR = dict((v, k) for k, v in LAL_TYPE_STR.items())
44LAL_TYPE_STR_REGEX = re.compile(
45 '(?P<dtype>(%s))' % ('|'.join(LAL_TYPE_FROM_STR.keys())), re.I)
46
47# map numpy dtypes to LAL type codes
48LAL_TYPE_FROM_NUMPY = {
49 numpy.int16: lal.I2_TYPE_CODE,
50 numpy.int32: lal.I4_TYPE_CODE,
51 numpy.int64: lal.I8_TYPE_CODE,
52 numpy.uint16: lal.U2_TYPE_CODE,
53 numpy.uint32: lal.U4_TYPE_CODE,
54 numpy.uint64: lal.U8_TYPE_CODE,
55 numpy.float32: lal.S_TYPE_CODE,
56 numpy.float64: lal.D_TYPE_CODE,
57 numpy.complex64: lal.C_TYPE_CODE,
58 numpy.complex128: lal.Z_TYPE_CODE,
59}
60NUMPY_TYPE_FROM_LAL = dict((v, k) for k, v in LAL_TYPE_FROM_NUMPY.items())
61
62
63# structure definers
64SERIES_OPERATIONS = ['create', 'destroy', 'cut', 'resize', 'shrink', 'add']
65SERIES_TYPES = ['Time', 'Frequency']
66STRUCT_TYPES = ['Sequence', 'Vector']
67
68SERIES_REGEX = re.compile(
69 r'%s(?P<stype>(%s))Series\Z'
70 % (LAL_TYPE_STR_REGEX.pattern, '|'.join(SERIES_TYPES)), re.I)
71ARRAY_REGEX = re.compile(
72 r'%sArray(?:(?P<dir>(L|V))?)' % LAL_TYPE_STR_REGEX.pattern, re.I)
73STRUCT_REGEX = re.compile(
74 r'%s(?P<struct>(%s))\Z'
75 % (LAL_TYPE_STR_REGEX.pattern, '|'.join(STRUCT_TYPES)), re.I)
76
77
78# -----------------------------------------------------------------------------
79# utility methods
80
81def func_factory(operation, dtype):
82 """Returns the LAL function to perform the given operation for the
83 relevant data type.
84
85 Example::
86
87 >>> create = func_factory('create', 'real8timeseries')
88 >>> create
89 lal.CreateREAL8TimeSeries
90 >>> ts = create(name, epoch, f0, deltaT, sampleUnits, length)
91 >>> func_factory('resize', ts)
92 lal.ResizeREAL8TimeSeries
93 """
94 # verify operation
95 try:
96 SERIES_OPERATIONS.index(operation.lower())
97 except ValueError as e:
98 e.args("Operation '%s' not understood for LAL series. "
99 "Please select one of: %s"
100 % (operation, ", ".join(SERIES_OPERATIONS)),)
101 raise e
102 # verify data type
103 struct = get_struct_name(dtype)
104 return getattr(lal, ''.join([operation.title(), struct]))
105
106
107def get_struct_name(series):
108 """Format a structure name into the understood type for LAL
109
110 Example::
111
112 >>> get_struct_name('real8timeseries')
113 'REAL8TimeSeries'
114 """
115 # get name of object
116 if isinstance(series, str):
117 typestr = series
118 else:
119 typestr = type(series).__name__
120
121 # attempt to match as a series type
122 try:
123 match = SERIES_REGEX.match(typestr).groupdict()
124 except AttributeError:
125 pass
126 else:
127 return '%s%sSeries' % (match['dtype'].upper(), match['stype'].title())
128
129 # attempt to match as an array (with optional dimension)
130 try:
131 match = ARRAY_REGEX.match(typestr).groupdict()
132 except AttributeError:
133 pass
134 else:
135 return '%sArray%s' % (match['dtype'].upper(),
136 match['dir'] and match['dir'].upper() or '')
137
138 # attempt to match as a structure
139 try:
140 match = STRUCT_REGEX.match(typestr).groupdict()
141 except AttributeError:
142 raise ValueError(
143 "Input %s cannot be parsed into LAL struct name" % series)
144 else:
145 return '%s%s' % (match['dtype'].upper(), match['struct'].title())
146
147
148def get_series_type(series):
149 """Find the LAL type enum for this series
150
151 @param series
152 a LAL series object (e.g. REAL8TimeSeries)
153
154 @returns the LAL type enum (integer) for the series
155 """
156 try:
157 match = STRUCT_REGEX.match(type(series).__name__).groupdict()
158 except AttributeError:
159 raise ValueError("Data type for series type %r unknown."
160 % type(series).__name__)
161 else:
162 return get_lal_type(match['dtype'].upper())
163
164
165def get_lal_type_str(datatype):
166 """Return the LAL type str for the given `datatype`
167
168 @param datatype
169 a dtype representation, normally a string, or a python/numpy type
170 object
171
172 @returns the LAL type str for the given datatype
173
174 Example::
175
176 >>> get_lal_type_str('uint32')
177 'UINT4'
178 >>> get_lal_type_str(float)
179 'REAL8'
180 """
181 return LAL_TYPE_STR[get_lal_type(datatype)]
182
183
184def get_lal_type(datatype):
185 """Return the LAL type enum for the given `datatype`
186
187 @param datatype
188 a dtype representation, normally a string, or a python/numpy type
189 object
190
191 @returns the LAL type enum (integer) for the given datatype
192
193 Example::
194
195 >>> get_lal_type('uint32')
196 34
197 >>> get_lal_type(float)
198 11
199 """
200 # parse a LAL type enum
201 try:
202 LAL_TYPE_STR[datatype]
203 except KeyError:
204 pass
205 else:
206 return datatype
207 # map a LAL type string
208 try:
209 return LAL_TYPE_FROM_STR[datatype]
210 except KeyError:
211 pass
212 # test again for 'real4' or 'real8' (lower-case)
213 # can't do this with others because they match numpy names
214 if re.match(r'real(4|8)\Z', str(datatype), re.I):
215 return LAL_TYPE_FROM_STR[datatype.upper()]
216 # format as a numpy data type and parse
217 try:
218 dtype = numpy.dtype(datatype).type
219 except TypeError:
220 pass
221 else:
222 try:
223 return LAL_TYPE_FROM_NUMPY[dtype]
224 except KeyError as e:
225 e.args = ('LAL has no support for numpy.%s' % dtype.__name__,)
226 raise
227 raise ValueError("Cannot interpret datatype %r" % datatype)
228
229
230def get_numpy_type(datatype):
231 """Return the numpy type for the given `datatype`
232
233 @param datatype
234 a dtype representation, normally a LAL type enum (int),
235 a LAL type string, or a python/numpy type object
236
237 @returns the numpy type corresponding to the given datatype
238
239 Example::
240
241 >>> get_numpy_type(float)
242 numpy.float64
243 >>> get_numpy_type('REAL8')
244 numpy.float64
245 >>> get_numpy_type(11)
246 numpy.float64
247 """
248 try:
249 return NUMPY_TYPE_FROM_LAL[get_lal_type(datatype)]
250 except KeyError as e:
251 e.args('numpy has no support for %s'
252 % get_lal_type(str(get_lal_type_str(datatype))),)
253 raise
254
255
256def duplicate(series):
257 """
258 Duplicate a TimeSeries or FrequencySeries.
259
260 Arguments:
261
262 series : [ TimeSeries | FrequencySeries ]
263 input series to duplicate
264 """
265 create = func_factory('create', series)
266 stype = series.__class__.__name__
267 if stype.endswith('FrequencySeries'):
268 out = create(series.name, series.epoch, series.f0, series.deltaF,
269 series.sampleUnits, series.data.length)
270 elif stype.endswith('TimeSeries'):
271 out = create(series.name, series.epoch, series.f0, series.deltaT,
272 series.sampleUnits, series.data.length)
273 else:
274 raise NotImplementedError("A duplicator for the %s has not been "
275 "implemented: here's your chance!" % series)
276 out.data.data = series.data.data
277 return out
def get_series_type(series)
Find the LAL type enum for this series.
def get_numpy_type(datatype)
Return the numpy type for the given datatype
def get_lal_type_str(datatype)
Return the LAL type str for the given datatype
def func_factory(operation, dtype)
Returns the LAL function to perform the given operation for the relevant data type.
Definition: utils/series.py:93
def get_lal_type(datatype)
Return the LAL type enum for the given datatype
def duplicate(series)
Duplicate a TimeSeries or FrequencySeries.
def get_struct_name(series)
Format a structure name into the understood type for LAL.