gwpy 3.0.6__py3-none-any.whl → 3.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gwpy might be problematic. Click here for more details.
- gwpy/_version.py +2 -2
- {gwpy-3.0.6.dist-info → gwpy-3.0.7.dist-info}/METADATA +1 -1
- {gwpy-3.0.6.dist-info → gwpy-3.0.7.dist-info}/RECORD +7 -11
- gwpy/io/gwf/__init__.py +0 -768
- gwpy/io/gwf/_framecpp.py +0 -739
- gwpy/io/gwf/_lalframe.py +0 -86
- gwpy/timeseries/io/gwf/lalframe2.py +0 -582
- {gwpy-3.0.6.dist-info → gwpy-3.0.7.dist-info}/LICENSE +0 -0
- {gwpy-3.0.6.dist-info → gwpy-3.0.7.dist-info}/WHEEL +0 -0
- {gwpy-3.0.6.dist-info → gwpy-3.0.7.dist-info}/entry_points.txt +0 -0
- {gwpy-3.0.6.dist-info → gwpy-3.0.7.dist-info}/top_level.txt +0 -0
gwpy/io/gwf/_lalframe.py
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# Copyright (C) Duncan Macleod (2014-2020)
|
|
3
|
-
#
|
|
4
|
-
# This file is part of GWpy.
|
|
5
|
-
#
|
|
6
|
-
# GWpy is free software: you can redistribute it and/or modify
|
|
7
|
-
# it under the terms of the GNU General Public License as published by
|
|
8
|
-
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
-
# (at your option) any later version.
|
|
10
|
-
#
|
|
11
|
-
# GWpy is distributed in the hope that it will be useful,
|
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
-
# GNU General Public License for more details.
|
|
15
|
-
#
|
|
16
|
-
# You should have received a copy of the GNU General Public License
|
|
17
|
-
# along with GWpy. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
-
|
|
19
|
-
"""GWF I/O utilities for LALFrame.
|
|
20
|
-
|
|
21
|
-
This module provides the LALFrame implementation of the functions
|
|
22
|
-
that make up the `gwpy.io.gwf` module API.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
from enum import IntEnum
|
|
26
|
-
|
|
27
|
-
import lalframe
|
|
28
|
-
|
|
29
|
-
from ...utils.enum import NumpyTypeEnum
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
# -- type mapping -------------------------------------------------------------
|
|
33
|
-
|
|
34
|
-
class FrVectType(IntEnum, NumpyTypeEnum):
|
|
35
|
-
INT8 = lalframe.FRAMEU_FR_VECT_C
|
|
36
|
-
INT16 = lalframe.FRAMEU_FR_VECT_2S
|
|
37
|
-
INT32 = lalframe.FRAMEU_FR_VECT_4S
|
|
38
|
-
INT64 = lalframe.FRAMEU_FR_VECT_8S
|
|
39
|
-
FLOAT32 = lalframe.FRAMEU_FR_VECT_4R
|
|
40
|
-
FLOAT64 = lalframe.FRAMEU_FR_VECT_8R
|
|
41
|
-
COMPLEX64 = lalframe.FRAMEU_FR_VECT_8C
|
|
42
|
-
COMPLEX128 = lalframe.FRAMEU_FR_VECT_16C
|
|
43
|
-
BYTES = lalframe.FRAMEU_FR_VECT_STRING
|
|
44
|
-
UINT8 = lalframe.FRAMEU_FR_VECT_1U
|
|
45
|
-
UINT16 = lalframe.FRAMEU_FR_VECT_2U
|
|
46
|
-
UINT32 = lalframe.FRAMEU_FR_VECT_4U
|
|
47
|
-
UINT64 = lalframe.FRAMEU_FR_VECT_8U
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def _lalframe_proctype(type_):
|
|
51
|
-
return getattr(lalframe, f"FRAMEU_FR_PROC_TYPE_{type_.upper()}")
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class FrProcDataType(IntEnum):
|
|
55
|
-
UNKNOWN = _lalframe_proctype("UNKNOWN")
|
|
56
|
-
TIME_SERIES = _lalframe_proctype("TIME_SERIES")
|
|
57
|
-
FREQUENCY_SERIES = _lalframe_proctype("FREQUENCY_SERIES")
|
|
58
|
-
OTHER_1D_SERIES_DATA = _lalframe_proctype("OTHER_1D_SERIES_DATA")
|
|
59
|
-
TIME_FREQUENCY = _lalframe_proctype("TIME_FREQUENCY")
|
|
60
|
-
WAVELETS = _lalframe_proctype("WAVELETS")
|
|
61
|
-
MULTI_DIMENSIONAL = _lalframe_proctype("MULTI_DIMENSIONAL")
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def _lalframe_proc_subtype(type_):
|
|
65
|
-
return getattr(lalframe, f"FRAMEU_FR_PROC_SUB_TYPE_{type_.upper()}")
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class FrProcDataSubType(IntEnum):
|
|
69
|
-
UNKNOWN = _lalframe_proc_subtype("UNKNOWN")
|
|
70
|
-
DFT = _lalframe_proc_subtype("DFT")
|
|
71
|
-
AMPLITUDE_SPECTRAL_DENSITY = _lalframe_proc_subtype("AMPLITUDE_SPECTRAL_DENSITY")
|
|
72
|
-
POWER_SPECTRAL_DENSITY = _lalframe_proc_subtype("POWER_SPECTRAL_DENSITY")
|
|
73
|
-
CROSS_SPECTRAL_DENSITY = _lalframe_proc_subtype("CROSS_SPECTRAL_DENSITY")
|
|
74
|
-
COHERENCE = _lalframe_proc_subtype("COHERENCE")
|
|
75
|
-
TRANSFER_FUNCTION = _lalframe_proc_subtype("TRANSFER_FUNCTION")
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def _iter_channels(framefile):
|
|
79
|
-
if not isinstance(framefile, lalframe.FrameUFrFile):
|
|
80
|
-
framefile = lalframe.FrameUFrFileOpen(framefile, "r")
|
|
81
|
-
toc = lalframe.FrameUFrTOCRead(framefile)
|
|
82
|
-
for type_ in ('sim', 'proc', 'adc'):
|
|
83
|
-
nchan = getattr(lalframe, f"FrameUFrTOCQuery{type_.title()}N")(toc)
|
|
84
|
-
get_name = getattr(lalframe, f"FrameUFrTOCQuery{type_.title()}Name")
|
|
85
|
-
for i in range(nchan):
|
|
86
|
-
yield get_name(toc, i), type_
|
|
@@ -1,582 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# Copyright (C) Duncan Macleod (2014-2020)
|
|
3
|
-
#
|
|
4
|
-
# This file is part of GWpy.
|
|
5
|
-
#
|
|
6
|
-
# GWpy is free software: you can redistribute it and/or modify
|
|
7
|
-
# it under the terms of the GNU General Public License as published by
|
|
8
|
-
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
-
# (at your option) any later version.
|
|
10
|
-
#
|
|
11
|
-
# GWpy is distributed in the hope that it will be useful,
|
|
12
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
-
# GNU General Public License for more details.
|
|
15
|
-
#
|
|
16
|
-
# You should have received a copy of the GNU General Public License
|
|
17
|
-
# along with GWpy. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
-
|
|
19
|
-
"""Read data from gravitational-wave frame (GWF) files using
|
|
20
|
-
|LDAStools.frameCPP|__.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import re
|
|
24
|
-
from math import ceil
|
|
25
|
-
|
|
26
|
-
import lalframe
|
|
27
|
-
|
|
28
|
-
import numpy
|
|
29
|
-
|
|
30
|
-
from ....io.utils import file_list
|
|
31
|
-
from ....segments import Segment
|
|
32
|
-
from ....time import (LIGOTimeGPS, to_gps)
|
|
33
|
-
from ... import TimeSeries
|
|
34
|
-
from ...core import _dynamic_scaled
|
|
35
|
-
|
|
36
|
-
from . import channel_dict_kwarg
|
|
37
|
-
|
|
38
|
-
__author__ = 'Duncan Macleod <duncan.macleod@ligo.org>'
|
|
39
|
-
|
|
40
|
-
FRAME_LIBRARY = 'LDAStools.frameCPP'
|
|
41
|
-
|
|
42
|
-
# error regexs
|
|
43
|
-
FRERR_NO_FRAME_AT_NUM = re.compile(
|
|
44
|
-
r'\ARequest for frame (?P<frnum>\d+) exceeds the range of '
|
|
45
|
-
r'0 through (?P<nframes>\d+)\Z',
|
|
46
|
-
)
|
|
47
|
-
FRERR_NO_CHANNEL_OF_TYPE = re.compile(
|
|
48
|
-
r'\ANo Fr(Adc|Proc|Sim)Data structures with the name ',
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class _Skip(ValueError):
|
|
53
|
-
"""Error denoting that the contents of a given structure aren't required
|
|
54
|
-
"""
|
|
55
|
-
pass
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# -- read ---------------------------------------------------------------------
|
|
59
|
-
|
|
60
|
-
def read(source, channels, start=None, end=None, scaled=None, type=None,
|
|
61
|
-
series_class=TimeSeries):
|
|
62
|
-
# pylint: disable=redefined-builtin
|
|
63
|
-
"""Read a dict of series from one or more GWF files
|
|
64
|
-
|
|
65
|
-
Parameters
|
|
66
|
-
----------
|
|
67
|
-
source : `str`, `list`
|
|
68
|
-
Source of data, any of the following:
|
|
69
|
-
|
|
70
|
-
- `str` path of single data file,
|
|
71
|
-
- `str` path of cache file,
|
|
72
|
-
- `list` of paths.
|
|
73
|
-
|
|
74
|
-
channels : `~gwpy.detector.ChannelList`, `list`
|
|
75
|
-
a list of channels to read from the source.
|
|
76
|
-
|
|
77
|
-
start : `~gwpy.time.LIGOTimeGPS`, `float`, `str` optional
|
|
78
|
-
GPS start time of required data, anything parseable by
|
|
79
|
-
:func:`~gwpy.time.to_gps` is fine.
|
|
80
|
-
|
|
81
|
-
end : `~gwpy.time.LIGOTimeGPS`, `float`, `str`, optional
|
|
82
|
-
GPS end time of required data, anything parseable by
|
|
83
|
-
:func:`~gwpy.time.to_gps` is fine.
|
|
84
|
-
|
|
85
|
-
scaled : `bool`, optional
|
|
86
|
-
apply slope and bias calibration to ADC data.
|
|
87
|
-
|
|
88
|
-
type : `dict`, optional
|
|
89
|
-
a `dict` of ``(name, channel-type)`` pairs, where ``channel-type``
|
|
90
|
-
can be one of ``'adc'``, ``'proc'``, or ``'sim'``.
|
|
91
|
-
|
|
92
|
-
series_class : `type`, optional
|
|
93
|
-
the `Series` sub-type to return.
|
|
94
|
-
|
|
95
|
-
Returns
|
|
96
|
-
-------
|
|
97
|
-
data : `~gwpy.timeseries.TimeSeriesDict` or similar
|
|
98
|
-
a dict of ``(channel, series)`` pairs read from the GWF source(s).
|
|
99
|
-
"""
|
|
100
|
-
# parse input source
|
|
101
|
-
source = file_list(source)
|
|
102
|
-
|
|
103
|
-
# parse type
|
|
104
|
-
ctype = channel_dict_kwarg(type, channels, (str,))
|
|
105
|
-
|
|
106
|
-
# read each individually and append
|
|
107
|
-
out = series_class.DictClass()
|
|
108
|
-
for i, file_ in enumerate(source):
|
|
109
|
-
if i == 1: # force data into fresh memory so that append works
|
|
110
|
-
for name in out:
|
|
111
|
-
out[name] = numpy.require(out[name], requirements=['O'])
|
|
112
|
-
# read frame
|
|
113
|
-
out.append(read_gwf(file_, channels, start=start, end=end, ctype=ctype,
|
|
114
|
-
scaled=scaled, series_class=series_class),
|
|
115
|
-
copy=False)
|
|
116
|
-
return out
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def read_gwf(filename, channels, start=None, end=None, scaled=None,
|
|
120
|
-
ctype=None, series_class=TimeSeries):
|
|
121
|
-
"""Read a dict of series data from a single GWF file
|
|
122
|
-
|
|
123
|
-
Parameters
|
|
124
|
-
----------
|
|
125
|
-
filename : `str`
|
|
126
|
-
the GWF path from which to read
|
|
127
|
-
|
|
128
|
-
channels : `~gwpy.detector.ChannelList`, `list`
|
|
129
|
-
a list of channels to read from the source.
|
|
130
|
-
|
|
131
|
-
start : `~gwpy.time.LIGOTimeGPS`, `float`, `str` optional
|
|
132
|
-
GPS start time of required data, anything parseable by
|
|
133
|
-
:func:`~gwpy.time.to_gps` is fine.
|
|
134
|
-
|
|
135
|
-
end : `~gwpy.time.LIGOTimeGPS`, `float`, `str`, optional
|
|
136
|
-
GPS end time of required data, anything parseable by
|
|
137
|
-
:func:`~gwpy.time.to_gps` is fine.
|
|
138
|
-
|
|
139
|
-
scaled : `bool`, optional
|
|
140
|
-
apply slope and bias calibration to ADC data.
|
|
141
|
-
|
|
142
|
-
type : `dict`, optional
|
|
143
|
-
a `dict` of ``(name, channel-type)`` pairs, where ``channel-type``
|
|
144
|
-
can be one of ``'adc'``, ``'proc'``, or ``'sim'``.
|
|
145
|
-
|
|
146
|
-
series_class : `type`, optional
|
|
147
|
-
the `Series` sub-type to return.
|
|
148
|
-
|
|
149
|
-
Returns
|
|
150
|
-
-------
|
|
151
|
-
data : `~gwpy.timeseries.TimeSeriesDict` or similar
|
|
152
|
-
a dict of ``(channel, series)`` pairs read from the GWF file.
|
|
153
|
-
"""
|
|
154
|
-
# parse kwargs
|
|
155
|
-
if not start:
|
|
156
|
-
start = 0
|
|
157
|
-
if not end:
|
|
158
|
-
end = 0
|
|
159
|
-
span = Segment(start, end)
|
|
160
|
-
|
|
161
|
-
# open file
|
|
162
|
-
file = lalframe.FrameUFrFileOpen(filename, "r")
|
|
163
|
-
toc = lalframe.FrameUFrTOCRead(file)
|
|
164
|
-
nframes = lalframe.FrameUFrTOCQueryNFrame(toc)
|
|
165
|
-
|
|
166
|
-
# find channels
|
|
167
|
-
out = series_class.DictClass()
|
|
168
|
-
|
|
169
|
-
# loop over frames in GWF
|
|
170
|
-
i = 0
|
|
171
|
-
while True:
|
|
172
|
-
this = i
|
|
173
|
-
i += 1
|
|
174
|
-
|
|
175
|
-
# read frame
|
|
176
|
-
try:
|
|
177
|
-
frame = stream.ReadFrameNSubset(this, 0)
|
|
178
|
-
except IndexError:
|
|
179
|
-
if this >= nframes:
|
|
180
|
-
break
|
|
181
|
-
raise
|
|
182
|
-
|
|
183
|
-
# check whether we need this frame at all
|
|
184
|
-
if not _need_frame(frame, start, end):
|
|
185
|
-
continue
|
|
186
|
-
|
|
187
|
-
# get epoch for this frame
|
|
188
|
-
epoch = LIGOTimeGPS(*frame.GetGTime())
|
|
189
|
-
|
|
190
|
-
# and read all the channels
|
|
191
|
-
for channel in channels:
|
|
192
|
-
_scaled = _dynamic_scaled(scaled, channel)
|
|
193
|
-
try:
|
|
194
|
-
new = _read_channel(stream, this, str(channel),
|
|
195
|
-
ctype.get(channel, None),
|
|
196
|
-
epoch, start, end, scaled=_scaled,
|
|
197
|
-
series_class=series_class)
|
|
198
|
-
except _Skip: # don't need this frame for this channel
|
|
199
|
-
continue
|
|
200
|
-
try:
|
|
201
|
-
out[channel].append(new)
|
|
202
|
-
except KeyError:
|
|
203
|
-
out[channel] = numpy.require(new, requirements=['O'])
|
|
204
|
-
|
|
205
|
-
# if we have all of the data we want, stop now
|
|
206
|
-
if all(span in out[channel].span for channel in out):
|
|
207
|
-
break
|
|
208
|
-
|
|
209
|
-
# if any channels weren't read, something went wrong
|
|
210
|
-
for channel in channels:
|
|
211
|
-
if channel not in out:
|
|
212
|
-
msg = "Failed to read {0!r} from {1!r}".format(
|
|
213
|
-
str(channel), filename)
|
|
214
|
-
if start or end:
|
|
215
|
-
msg += ' for {0}'.format(span)
|
|
216
|
-
raise ValueError(msg)
|
|
217
|
-
|
|
218
|
-
return out
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def _read_channel(stream, num, name, ctype, epoch, start, end,
|
|
222
|
-
scaled=True, series_class=TimeSeries):
|
|
223
|
-
"""Read a channel from a specific frame in a stream
|
|
224
|
-
"""
|
|
225
|
-
data = _get_frdata(stream, num, name, ctype=ctype)
|
|
226
|
-
return read_frdata(data, epoch, start, end,
|
|
227
|
-
scaled=scaled, series_class=series_class)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def _get_frdata(stream, num, name, ctype=None):
|
|
231
|
-
"""Brute force-ish method to return the FrData structure for a channel
|
|
232
|
-
|
|
233
|
-
This saves on pulling the channel type from the TOC
|
|
234
|
-
"""
|
|
235
|
-
ctypes = (ctype,) if ctype else ('adc', 'proc', 'sim')
|
|
236
|
-
for ctype in ctypes:
|
|
237
|
-
_reader = getattr(stream, 'ReadFr{0}Data'.format(ctype.title()))
|
|
238
|
-
try:
|
|
239
|
-
return _reader(num, name)
|
|
240
|
-
except IndexError as exc:
|
|
241
|
-
if FRERR_NO_CHANNEL_OF_TYPE.match(str(exc)):
|
|
242
|
-
continue
|
|
243
|
-
raise
|
|
244
|
-
raise ValueError("no Fr{{Adc,Proc,Sim}}Data structures with the "
|
|
245
|
-
"name {0}".format(name))
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
def _need_frame(frame, start, end):
|
|
249
|
-
frstart = LIGOTimeGPS(*frame.GetGTime())
|
|
250
|
-
if end and frstart >= end:
|
|
251
|
-
return False
|
|
252
|
-
|
|
253
|
-
frend = frstart + frame.GetDt()
|
|
254
|
-
if start and frend <= start:
|
|
255
|
-
return False
|
|
256
|
-
|
|
257
|
-
return True
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
def read_frdata(frdata, epoch, start, end, scaled=True,
|
|
261
|
-
series_class=TimeSeries):
|
|
262
|
-
"""Read a series from an `FrData` structure
|
|
263
|
-
|
|
264
|
-
Parameters
|
|
265
|
-
----------
|
|
266
|
-
frdata : `LDAStools.frameCPP.FrAdcData` or similar
|
|
267
|
-
the data structure to read
|
|
268
|
-
|
|
269
|
-
epoch : `float`
|
|
270
|
-
the GPS start time of the containing frame
|
|
271
|
-
(`LDAStools.frameCPP.FrameH.GTime`)
|
|
272
|
-
|
|
273
|
-
start : `float`
|
|
274
|
-
the GPS start time of the user request
|
|
275
|
-
|
|
276
|
-
end : `float`
|
|
277
|
-
the GPS end time of the user request
|
|
278
|
-
|
|
279
|
-
scaled : `bool`, optional
|
|
280
|
-
apply slope and bias calibration to ADC data.
|
|
281
|
-
|
|
282
|
-
series_class : `type`, optional
|
|
283
|
-
the `Series` sub-type to return.
|
|
284
|
-
|
|
285
|
-
Returns
|
|
286
|
-
-------
|
|
287
|
-
series : `~gwpy.timeseries.TimeSeriesBase`
|
|
288
|
-
the formatted data series
|
|
289
|
-
|
|
290
|
-
Raises
|
|
291
|
-
------
|
|
292
|
-
_Skip
|
|
293
|
-
if this data structure doesn't overlap with the requested
|
|
294
|
-
``[start, end)`` interval.
|
|
295
|
-
"""
|
|
296
|
-
datastart = epoch + frdata.GetTimeOffset()
|
|
297
|
-
|
|
298
|
-
# check overlap with user-requested span
|
|
299
|
-
if end and datastart >= end:
|
|
300
|
-
raise _Skip()
|
|
301
|
-
|
|
302
|
-
# get scaling
|
|
303
|
-
try:
|
|
304
|
-
slope = frdata.GetSlope()
|
|
305
|
-
bias = frdata.GetBias()
|
|
306
|
-
except AttributeError: # not FrAdcData
|
|
307
|
-
slope = None
|
|
308
|
-
bias = None
|
|
309
|
-
else:
|
|
310
|
-
# workaround https://git.ligo.org/ldastools/LDAS_Tools/-/issues/114
|
|
311
|
-
# by forcing the default slope to 1.
|
|
312
|
-
if bias == slope == 0.:
|
|
313
|
-
slope = 1.
|
|
314
|
-
null_scaling = slope == 1. and bias == 0.
|
|
315
|
-
|
|
316
|
-
out = None
|
|
317
|
-
for j in range(frdata.data.size()):
|
|
318
|
-
# we use range(frdata.data.size()) to avoid segfault
|
|
319
|
-
# related to iterating directly over frdata.data
|
|
320
|
-
try:
|
|
321
|
-
new = read_frvect(frdata.data[j], datastart, start, end,
|
|
322
|
-
name=frdata.GetName(),
|
|
323
|
-
series_class=series_class)
|
|
324
|
-
except _Skip:
|
|
325
|
-
continue
|
|
326
|
-
|
|
327
|
-
# apply scaling for ADC channels
|
|
328
|
-
if scaled and slope is not None:
|
|
329
|
-
rtype = numpy.result_type(new, slope, bias)
|
|
330
|
-
typechange = not numpy.can_cast(
|
|
331
|
-
rtype,
|
|
332
|
-
new.dtype,
|
|
333
|
-
casting='same_kind',
|
|
334
|
-
)
|
|
335
|
-
# only apply scaling if interesting _or_ if it would lead to a
|
|
336
|
-
# type change, otherwise we are unnecessarily duplicating memory
|
|
337
|
-
if typechange:
|
|
338
|
-
new = new * slope + bias
|
|
339
|
-
elif not null_scaling:
|
|
340
|
-
new *= slope
|
|
341
|
-
new += bias
|
|
342
|
-
elif slope is not None:
|
|
343
|
-
# user has deliberately disabled the ADC calibration, so
|
|
344
|
-
# the stored engineering unit is not valid, revert to 'counts':
|
|
345
|
-
new.override_unit('count')
|
|
346
|
-
|
|
347
|
-
if out is None:
|
|
348
|
-
out = new
|
|
349
|
-
else:
|
|
350
|
-
out.append(new)
|
|
351
|
-
return out
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
def read_frvect(vect, epoch, start, end, name=None, series_class=TimeSeries):
|
|
355
|
-
"""Read an array from an `FrVect` structure
|
|
356
|
-
|
|
357
|
-
Parameters
|
|
358
|
-
----------
|
|
359
|
-
vect : `LDASTools.frameCPP.FrVect`
|
|
360
|
-
the frame vector structur to read
|
|
361
|
-
|
|
362
|
-
start : `float`
|
|
363
|
-
the GPS start time of the request
|
|
364
|
-
|
|
365
|
-
end : `float`
|
|
366
|
-
the GPS end time of the request
|
|
367
|
-
|
|
368
|
-
epoch : `float`
|
|
369
|
-
the GPS start time of the containing `FrData` structure
|
|
370
|
-
|
|
371
|
-
name : `str`, optional
|
|
372
|
-
the name of the output `series_class`; this is also used
|
|
373
|
-
to ignore ``FrVect`` structures containing other information
|
|
374
|
-
|
|
375
|
-
series_class : `type`, optional
|
|
376
|
-
the `Series` sub-type to return.
|
|
377
|
-
|
|
378
|
-
Returns
|
|
379
|
-
-------
|
|
380
|
-
series : `~gwpy.timeseries.TimeSeriesBase`
|
|
381
|
-
the formatted data series
|
|
382
|
-
|
|
383
|
-
Raises
|
|
384
|
-
------
|
|
385
|
-
_Skip
|
|
386
|
-
if this vect doesn't overlap with the requested
|
|
387
|
-
``[start, end)`` interval, or the name doesn't match.
|
|
388
|
-
"""
|
|
389
|
-
# only read FrVect with matching name (or no name set)
|
|
390
|
-
# frame spec allows for arbitrary other FrVects
|
|
391
|
-
# to hold other information
|
|
392
|
-
if vect.GetName() and name and vect.GetName() != name:
|
|
393
|
-
raise _Skip()
|
|
394
|
-
|
|
395
|
-
# get array
|
|
396
|
-
arr = vect.GetDataArray()
|
|
397
|
-
nsamp = arr.size
|
|
398
|
-
|
|
399
|
-
# and dimensions
|
|
400
|
-
dim = vect.GetDim(0)
|
|
401
|
-
dx = dim.dx
|
|
402
|
-
x0 = dim.startX
|
|
403
|
-
|
|
404
|
-
# start and end GPS times of this FrVect
|
|
405
|
-
dimstart = epoch + x0
|
|
406
|
-
dimend = dimstart + nsamp * dx
|
|
407
|
-
|
|
408
|
-
# index of first required sample
|
|
409
|
-
nxstart = int(max(0., float(start-dimstart)) / dx)
|
|
410
|
-
|
|
411
|
-
# requested start time is after this frame, skip
|
|
412
|
-
if nxstart >= nsamp:
|
|
413
|
-
raise _Skip()
|
|
414
|
-
|
|
415
|
-
# index of end sample
|
|
416
|
-
if end:
|
|
417
|
-
nxend = int(nsamp - ceil(max(0., float(dimend-end)) / dx))
|
|
418
|
-
else:
|
|
419
|
-
nxend = None
|
|
420
|
-
|
|
421
|
-
if nxstart or nxend:
|
|
422
|
-
arr = arr[nxstart:nxend]
|
|
423
|
-
|
|
424
|
-
# -- cast as a series
|
|
425
|
-
|
|
426
|
-
# get unit
|
|
427
|
-
unit = vect.GetUnitY() or None
|
|
428
|
-
|
|
429
|
-
# create array
|
|
430
|
-
series = series_class(arr, t0=dimstart+nxstart*dx, dt=dx, name=name,
|
|
431
|
-
channel=name, unit=unit, copy=False)
|
|
432
|
-
|
|
433
|
-
# add information to channel
|
|
434
|
-
series.channel.sample_rate = series.sample_rate.value
|
|
435
|
-
series.channel.unit = unit
|
|
436
|
-
series.channel.dtype = series.dtype
|
|
437
|
-
|
|
438
|
-
return series
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
# -- write --------------------------------------------------------------------
|
|
442
|
-
|
|
443
|
-
def write(tsdict, outfile,
|
|
444
|
-
start=None, end=None,
|
|
445
|
-
type=None,
|
|
446
|
-
name='gwpy', run=0,
|
|
447
|
-
compression='GZIP', compression_level=None):
|
|
448
|
-
"""Write data to a GWF file using the frameCPP API
|
|
449
|
-
|
|
450
|
-
Parameters
|
|
451
|
-
----------
|
|
452
|
-
tsdict : `TimeSeriesDict`
|
|
453
|
-
dict of data to write
|
|
454
|
-
|
|
455
|
-
outfile : `str`
|
|
456
|
-
the file name of the target output file
|
|
457
|
-
|
|
458
|
-
start : `float`, optional
|
|
459
|
-
the GPS start time of the file
|
|
460
|
-
|
|
461
|
-
end : `float`, optional
|
|
462
|
-
the GPS end time of the file
|
|
463
|
-
|
|
464
|
-
type : `str`, optional
|
|
465
|
-
the type of the channel, one of 'adc', 'proc', 'sim', default
|
|
466
|
-
is 'proc' unless stored in the channel structure
|
|
467
|
-
|
|
468
|
-
name : `str`, optional
|
|
469
|
-
the name of each frame
|
|
470
|
-
|
|
471
|
-
run : `int`, optional
|
|
472
|
-
the FrameH run number
|
|
473
|
-
|
|
474
|
-
compression : `int`, `str`, optional
|
|
475
|
-
name of compresion algorithm to use, or its endian-appropriate
|
|
476
|
-
ID, choose from
|
|
477
|
-
|
|
478
|
-
- ``'RAW'``
|
|
479
|
-
- ``'GZIP'``
|
|
480
|
-
- ``'DIFF_GZIP'``
|
|
481
|
-
- ``'ZERO_SUPPRESS_WORD_2'``
|
|
482
|
-
- ``'ZERO_SUPPRESS_WORD_4'``
|
|
483
|
-
- ``'ZERO_SUPPRESS_WORD_8'``
|
|
484
|
-
- ``'ZERO_SUPPRESS_OTHERWISE_GZIP'``
|
|
485
|
-
|
|
486
|
-
compression_level : `int`, optional
|
|
487
|
-
compression level for given method, default is ``6`` for GZIP-based
|
|
488
|
-
methods, otherwise ``0``
|
|
489
|
-
"""
|
|
490
|
-
# set frame header metadata
|
|
491
|
-
if not start or not end:
|
|
492
|
-
starts, ends = zip(*(ts.span for ts in tsdict.values()))
|
|
493
|
-
start = to_gps(start or min(starts))
|
|
494
|
-
end = to_gps(end or max(ends))
|
|
495
|
-
duration = end - start
|
|
496
|
-
ifos = {
|
|
497
|
-
ts.channel.ifo for ts in tsdict.values() if (
|
|
498
|
-
ts.channel
|
|
499
|
-
and ts.channel.ifo
|
|
500
|
-
and ts.channel.ifo in io_framecpp.DetectorLocation.__members__
|
|
501
|
-
)
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
# create frame
|
|
505
|
-
frame = io_gwf.create_frame(
|
|
506
|
-
time=start,
|
|
507
|
-
duration=duration,
|
|
508
|
-
name=name,
|
|
509
|
-
run=run,
|
|
510
|
-
ifos=ifos,
|
|
511
|
-
)
|
|
512
|
-
|
|
513
|
-
# append channels
|
|
514
|
-
for i, key in enumerate(tsdict):
|
|
515
|
-
ctype = (
|
|
516
|
-
type
|
|
517
|
-
or getattr(tsdict[key].channel, "_ctype", "proc").lower()
|
|
518
|
-
or "proc"
|
|
519
|
-
)
|
|
520
|
-
if ctype == 'adc':
|
|
521
|
-
kw = {"channelid": i}
|
|
522
|
-
else:
|
|
523
|
-
kw = {}
|
|
524
|
-
_append_to_frame(frame, tsdict[key].crop(start, end), type=ctype, **kw)
|
|
525
|
-
|
|
526
|
-
# write frame to file
|
|
527
|
-
io_gwf.write_frames(
|
|
528
|
-
outfile,
|
|
529
|
-
[frame],
|
|
530
|
-
compression=compression,
|
|
531
|
-
compression_level=compression_level,
|
|
532
|
-
)
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
def _append_to_frame(frame, timeseries, type='proc', **kwargs):
|
|
536
|
-
# pylint: disable=redefined-builtin
|
|
537
|
-
"""Append data from a `TimeSeries` to a `~frameCPP.FrameH`
|
|
538
|
-
|
|
539
|
-
Parameters
|
|
540
|
-
----------
|
|
541
|
-
frame : `~frameCPP.FrameH`
|
|
542
|
-
frame object to append to
|
|
543
|
-
|
|
544
|
-
timeseries : `TimeSeries`
|
|
545
|
-
the timeseries to append
|
|
546
|
-
|
|
547
|
-
type : `str`
|
|
548
|
-
the type of the channel, one of 'adc', 'proc', 'sim'
|
|
549
|
-
|
|
550
|
-
**kwargs
|
|
551
|
-
other keyword arguments are passed to the relevant
|
|
552
|
-
`create_xxx` function
|
|
553
|
-
|
|
554
|
-
See also
|
|
555
|
-
--------
|
|
556
|
-
gwpy.io.gwf.create_fradcdata
|
|
557
|
-
gwpy.io.gwf.create_frprocdata
|
|
558
|
-
gwpy.io.gwf_create_frsimdata
|
|
559
|
-
for details of the data structure creation, and associated available
|
|
560
|
-
arguments
|
|
561
|
-
"""
|
|
562
|
-
epoch = LIGOTimeGPS(*frame.GetGTime())
|
|
563
|
-
|
|
564
|
-
# create the data container
|
|
565
|
-
if type.lower() == 'adc':
|
|
566
|
-
create = io_gwf.create_fradcdata
|
|
567
|
-
append = frame.AppendFrAdcData
|
|
568
|
-
elif type.lower() == 'proc':
|
|
569
|
-
create = io_gwf.create_frprocdata
|
|
570
|
-
append = frame.AppendFrProcData
|
|
571
|
-
elif type.lower() == 'sim':
|
|
572
|
-
create = io_gwf.create_frsimdata
|
|
573
|
-
append = frame.AppendFrSimData
|
|
574
|
-
else:
|
|
575
|
-
raise RuntimeError("Invalid channel type {!r}, please select one of "
|
|
576
|
-
"'adc, 'proc', or 'sim'".format(type))
|
|
577
|
-
frdata = create(timeseries, frame_epoch=epoch, **kwargs)
|
|
578
|
-
|
|
579
|
-
# append an FrVect
|
|
580
|
-
frdata.AppendData(io_gwf.create_frvect(timeseries))
|
|
581
|
-
append(frdata)
|
|
582
|
-
return frdata
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|