LAL  7.5.0.1-08ee4f4
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 
20 import numpy
21 import re
22 
23 from .. 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)
31 LAL_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 }
43 LAL_TYPE_FROM_STR = dict((v, k) for k, v in LAL_TYPE_STR.items())
44 LAL_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
48 LAL_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 }
60 NUMPY_TYPE_FROM_LAL = dict((v, k) for k, v in LAL_TYPE_FROM_NUMPY.items())
61 
62 
63 # structure definers
64 SERIES_OPERATIONS = ['create', 'destroy', 'cut', 'resize', 'shrink', 'add']
65 SERIES_TYPES = ['Time', 'Frequency']
66 STRUCT_TYPES = ['Sequence', 'Vector']
67 
68 SERIES_REGEX = re.compile(
69  r'%s(?P<stype>(%s))Series\Z'
70  % (LAL_TYPE_STR_REGEX.pattern, '|'.join(SERIES_TYPES)), re.I)
71 ARRAY_REGEX = re.compile(
72  r'%sArray(?:(?P<dir>(L|V))?)' % LAL_TYPE_STR_REGEX.pattern, re.I)
73 STRUCT_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 
81 def 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 
107 def 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 
148 def 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 
165 def 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 
184 def 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 
230 def 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 
256 def 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.