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/_framecpp.py
DELETED
|
@@ -1,739 +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 frameCPP
|
|
20
|
-
|
|
21
|
-
This module is where all constants and variables that require
|
|
22
|
-
frameCPP should go, as opposed to functions which can import
|
|
23
|
-
the necessary objects at runtime.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
from enum import IntEnum
|
|
27
|
-
|
|
28
|
-
from LDAStools import frameCPP
|
|
29
|
-
|
|
30
|
-
from ..utils.enum import NumpyTypeEnum
|
|
31
|
-
|
|
32
|
-
_FrVect = frameCPP.FrVect
|
|
33
|
-
|
|
34
|
-
# -- detectors ----------------------------------------------------------------
|
|
35
|
-
|
|
36
|
-
DetectorLocation = IntEnum(
|
|
37
|
-
"DetectorLocation",
|
|
38
|
-
{key[18:]: val for key, val in vars(frameCPP).items() if
|
|
39
|
-
key.startswith("DETECTOR_LOCATION_")},
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# -- type mapping -------------------------------------------------------------
|
|
44
|
-
|
|
45
|
-
class FrVectType(IntEnum, NumpyTypeEnum):
|
|
46
|
-
INT8 = _FrVect.FR_VECT_C
|
|
47
|
-
INT16 = _FrVect.FR_VECT_2S
|
|
48
|
-
INT32 = _FrVect.FR_VECT_4S
|
|
49
|
-
INT64 = _FrVect.FR_VECT_8S
|
|
50
|
-
FLOAT32 = _FrVect.FR_VECT_4R
|
|
51
|
-
FLOAT64 = _FrVect.FR_VECT_8R
|
|
52
|
-
COMPLEX64 = _FrVect.FR_VECT_8C
|
|
53
|
-
COMPLEX128 = _FrVect.FR_VECT_16C
|
|
54
|
-
BYTES = _FrVect.FR_VECT_STRING
|
|
55
|
-
UINT8 = _FrVect.FR_VECT_1U
|
|
56
|
-
UINT16 = _FrVect.FR_VECT_2U
|
|
57
|
-
UINT32 = _FrVect.FR_VECT_4U
|
|
58
|
-
UINT64 = _FrVect.FR_VECT_8U
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# -- compression types --------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
try:
|
|
64
|
-
_FrVect.ZERO_SUPPRESS
|
|
65
|
-
except AttributeError: # python-ldas-tools-framecpp < 3.0.0
|
|
66
|
-
class Compression(IntEnum):
|
|
67
|
-
RAW = _FrVect.RAW
|
|
68
|
-
GZIP = _FrVect.GZIP
|
|
69
|
-
DIFF_GZIP = _FrVect.DIFF_GZIP
|
|
70
|
-
ZERO_SUPPRESS_WORD_2 = _FrVect.ZERO_SUPPRESS_WORD_2
|
|
71
|
-
ZERO_SUPPRESS_WORD_4 = _FrVect.ZERO_SUPPRESS_WORD_4
|
|
72
|
-
ZERO_SUPPRESS_WORD_8 = _FrVect.ZERO_SUPPRESS_WORD_8
|
|
73
|
-
ZERO_SUPPRESS_OTHERWISE_GZIP = _FrVect.ZERO_SUPPRESS_OTHERWISE_GZIP
|
|
74
|
-
else:
|
|
75
|
-
class Compression(IntEnum):
|
|
76
|
-
RAW = _FrVect.RAW
|
|
77
|
-
BIGENDIAN_RAW = _FrVect.BIGENDIAN_RAW
|
|
78
|
-
LITTLEENDIAN_RAW = _FrVect.LITTLEENDIAN_RAW
|
|
79
|
-
GZIP = _FrVect.GZIP
|
|
80
|
-
BIGENDIAN_GZIP = _FrVect.BIGENDIAN_GZIP
|
|
81
|
-
LITTLEENDIAN_GZIP = _FrVect.LITTLEENDIAN_GZIP
|
|
82
|
-
DIFF_GZIP = _FrVect.DIFF_GZIP
|
|
83
|
-
BIGENDIAN_DIFF_GZIP = _FrVect.BIGENDIAN_DIFF_GZIP
|
|
84
|
-
LITTLEENDIAN_DIFF_GZIP = _FrVect.LITTLEENDIAN_DIFF_GZIP
|
|
85
|
-
ZERO_SUPPRESS = _FrVect.ZERO_SUPPRESS
|
|
86
|
-
BIGENDIAN_ZERO_SUPPRESS = _FrVect.BIGENDIAN_ZERO_SUPPRESS
|
|
87
|
-
LITTLEENDIAN_ZERO_SUPPRESS = _FrVect.LITTLEENDIAN_ZERO_SUPPRESS
|
|
88
|
-
ZERO_SUPPRESS_OTHERWISE_GZIP = _FrVect.ZERO_SUPPRESS_OTHERWISE_GZIP
|
|
89
|
-
|
|
90
|
-
# compression level is '6' for all GZip compressions, otherwise 0 (none)
|
|
91
|
-
DefaultCompressionLevel = IntEnum(
|
|
92
|
-
"DefaultCompressionLevel",
|
|
93
|
-
{k: 6 if "GZIP" in k else 0 for k in Compression.__members__},
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
# -- Proc data types ----------------------------------------------------------
|
|
98
|
-
|
|
99
|
-
class FrProcDataType(IntEnum):
|
|
100
|
-
UNKNOWN = frameCPP.FrProcData.UNKNOWN_TYPE
|
|
101
|
-
TIME_SERIES = frameCPP.FrProcData.TIME_SERIES
|
|
102
|
-
FREQUENCY_SERIES = frameCPP.FrProcData.FREQUENCY_SERIES
|
|
103
|
-
OTHER_1D_SERIES_DATA = frameCPP.FrProcData.OTHER_1D_SERIES_DATA
|
|
104
|
-
TIME_FREQUENCY = frameCPP.FrProcData.TIME_FREQUENCY
|
|
105
|
-
WAVELETS = frameCPP.FrProcData.WAVELETS
|
|
106
|
-
MULTI_DIMENSIONAL = frameCPP.FrProcData.MULTI_DIMENSIONAL
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
class FrProcDataSubType(IntEnum):
|
|
110
|
-
UNKNOWN = frameCPP.FrProcData.UNKNOWN_SUB_TYPE
|
|
111
|
-
DFT = frameCPP.FrProcData.DFT
|
|
112
|
-
AMPLITUDE_SPECTRAL_DENSITY = frameCPP.FrProcData.AMPLITUDE_SPECTRAL_DENSITY
|
|
113
|
-
POWER_SPECTRAL_DENSITY = frameCPP.FrProcData.POWER_SPECTRAL_DENSITY
|
|
114
|
-
CROSS_SPECTRAL_DENSITY = frameCPP.FrProcData.CROSS_SPECTRAL_DENSITY
|
|
115
|
-
COHERENCE = frameCPP.FrProcData.COHERENCE
|
|
116
|
-
TRANSFER_FUNCTION = frameCPP.FrProcData.TRANSFER_FUNCTION
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# -- functions ----------------------------------------------------------------
|
|
120
|
-
|
|
121
|
-
def open_gwf(filename, mode='r'):
|
|
122
|
-
"""Open a filename for reading or writing GWF format data
|
|
123
|
-
|
|
124
|
-
Parameters
|
|
125
|
-
----------
|
|
126
|
-
filename : `str`
|
|
127
|
-
the path to read from, or write to
|
|
128
|
-
|
|
129
|
-
mode : `str`, optional
|
|
130
|
-
either ``'r'`` (read) or ``'w'`` (write)
|
|
131
|
-
|
|
132
|
-
Returns
|
|
133
|
-
-------
|
|
134
|
-
`LDAStools.frameCPP.IFrameFStream`
|
|
135
|
-
the input frame stream (if `mode='r'`), or
|
|
136
|
-
`LDAStools.frameCPP.IFrameFStream`
|
|
137
|
-
the output frame stream (if `mode='w'`)
|
|
138
|
-
"""
|
|
139
|
-
if mode not in ('r', 'w'):
|
|
140
|
-
raise ValueError("mode must be either 'r' or 'w'")
|
|
141
|
-
from LDAStools import frameCPP
|
|
142
|
-
filename = file_path(filename)
|
|
143
|
-
if mode == 'r':
|
|
144
|
-
return frameCPP.IFrameFStream(str(filename))
|
|
145
|
-
return frameCPP.OFrameFStream(str(filename))
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
def write_frames(filename, frames, compression='GZIP', compression_level=None):
|
|
149
|
-
"""Write a list of frame objects to a file
|
|
150
|
-
|
|
151
|
-
**Requires:** |LDAStools.frameCPP|_
|
|
152
|
-
|
|
153
|
-
Parameters
|
|
154
|
-
----------
|
|
155
|
-
filename : `str`
|
|
156
|
-
path to write into
|
|
157
|
-
|
|
158
|
-
frames : `list` of `LDAStools.frameCPP.FrameH`
|
|
159
|
-
list of frames to write into file
|
|
160
|
-
|
|
161
|
-
compression : `int`, `str`, optional
|
|
162
|
-
name of compresion algorithm to use, or its endian-appropriate
|
|
163
|
-
ID, choose from
|
|
164
|
-
|
|
165
|
-
- ``'RAW'``
|
|
166
|
-
- ``'GZIP'``
|
|
167
|
-
- ``'DIFF_GZIP'``
|
|
168
|
-
- ``'ZERO_SUPPRESS'``
|
|
169
|
-
- ``'ZERO_SUPPRESS_OTHERWISE_GZIP'``
|
|
170
|
-
|
|
171
|
-
compression_level : `int`, optional
|
|
172
|
-
compression level for given method, default is ``6`` for GZIP-based
|
|
173
|
-
methods, otherwise ``0``
|
|
174
|
-
"""
|
|
175
|
-
from LDAStools import frameCPP
|
|
176
|
-
from ._framecpp import (Compression, DefaultCompressionLevel)
|
|
177
|
-
|
|
178
|
-
# handle compression arguments
|
|
179
|
-
if not isinstance(compression, int):
|
|
180
|
-
compression = Compression[compression]
|
|
181
|
-
if compression_level is None:
|
|
182
|
-
compression_level = DefaultCompressionLevel[compression.name]
|
|
183
|
-
|
|
184
|
-
# open stream
|
|
185
|
-
stream = open_gwf(filename, 'w')
|
|
186
|
-
|
|
187
|
-
# write frames one-by-one
|
|
188
|
-
if isinstance(frames, frameCPP.FrameH):
|
|
189
|
-
frames = [frames]
|
|
190
|
-
for frame in frames:
|
|
191
|
-
stream.WriteFrame(frame, int(compression), int(compression_level))
|
|
192
|
-
# stream auto-closes (apparently)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def create_frame(time=0, duration=None, name='gwpy', run=-1, ifos=None):
|
|
196
|
-
"""Create a new :class:`~LDAStools.frameCPP.FrameH`
|
|
197
|
-
|
|
198
|
-
**Requires:** |LDAStools.frameCPP|_
|
|
199
|
-
|
|
200
|
-
Parameters
|
|
201
|
-
----------
|
|
202
|
-
time : `float`, optional
|
|
203
|
-
frame start time in GPS seconds
|
|
204
|
-
|
|
205
|
-
duration : `float`, optional
|
|
206
|
-
frame length in seconds
|
|
207
|
-
|
|
208
|
-
name : `str`, optional
|
|
209
|
-
name of project or other experiment description
|
|
210
|
-
|
|
211
|
-
run : `int`, optional
|
|
212
|
-
run number (number < 0 reserved for simulated data); monotonic for
|
|
213
|
-
experimental runs
|
|
214
|
-
|
|
215
|
-
ifos : `list`, optional
|
|
216
|
-
list of interferometer prefices (e.g. ``'L1'``) associated with this
|
|
217
|
-
frame
|
|
218
|
-
|
|
219
|
-
Returns
|
|
220
|
-
-------
|
|
221
|
-
frame : :class:`~LDAStools.frameCPP.FrameH`
|
|
222
|
-
the newly created frame header
|
|
223
|
-
"""
|
|
224
|
-
from LDAStools import frameCPP
|
|
225
|
-
from ._framecpp import DetectorLocation
|
|
226
|
-
|
|
227
|
-
# create frame
|
|
228
|
-
frame = frameCPP.FrameH()
|
|
229
|
-
|
|
230
|
-
# add timing
|
|
231
|
-
gps = to_gps(time)
|
|
232
|
-
gps = frameCPP.GPSTime(gps.gpsSeconds, gps.gpsNanoSeconds)
|
|
233
|
-
frame.SetGTime(gps)
|
|
234
|
-
if duration is not None:
|
|
235
|
-
frame.SetDt(float(duration))
|
|
236
|
-
|
|
237
|
-
# add FrDetectors
|
|
238
|
-
for prefix in ifos or []:
|
|
239
|
-
frame.AppendFrDetector(
|
|
240
|
-
frameCPP.GetDetector(DetectorLocation[prefix], gps),
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
# add descriptions
|
|
244
|
-
frame.SetName(name)
|
|
245
|
-
frame.SetRun(run)
|
|
246
|
-
|
|
247
|
-
return frame
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def create_fradcdata(series, frame_epoch=0,
|
|
251
|
-
channelgroup=0, channelid=0, nbits=16):
|
|
252
|
-
"""Create a `~frameCPP.FrAdcData` from a `~gwpy.types.Series`
|
|
253
|
-
|
|
254
|
-
.. note::
|
|
255
|
-
|
|
256
|
-
Currently this method is restricted to 1-dimensional arrays.
|
|
257
|
-
|
|
258
|
-
Parameters
|
|
259
|
-
----------
|
|
260
|
-
series : `~gwpy.types.Series`
|
|
261
|
-
the input data array to store
|
|
262
|
-
|
|
263
|
-
frame_epoch : `float`, `int`, optional
|
|
264
|
-
the GPS start epoch of the `Frame` that will contain this
|
|
265
|
-
data structure
|
|
266
|
-
|
|
267
|
-
Returns
|
|
268
|
-
-------
|
|
269
|
-
frdata : `~frameCPP.FrAdcData`
|
|
270
|
-
the newly created data structure
|
|
271
|
-
|
|
272
|
-
Notes
|
|
273
|
-
-----
|
|
274
|
-
See Table 10 (§4.3.2.4) of LIGO-T970130 for more details
|
|
275
|
-
"""
|
|
276
|
-
from LDAStools import frameCPP
|
|
277
|
-
|
|
278
|
-
# assert correct type
|
|
279
|
-
if not series.xunit.is_equivalent('s') or series.ndim != 1:
|
|
280
|
-
raise TypeError("only 1-dimensional timeseries data can be "
|
|
281
|
-
"written as FrAdcData")
|
|
282
|
-
|
|
283
|
-
frdata = frameCPP.FrAdcData(
|
|
284
|
-
_series_name(series),
|
|
285
|
-
channelgroup,
|
|
286
|
-
channelid,
|
|
287
|
-
nbits,
|
|
288
|
-
(1 / series.dx.to('s')).value
|
|
289
|
-
)
|
|
290
|
-
frdata.SetTimeOffset(
|
|
291
|
-
float(to_gps(series.x0.value) - to_gps(frame_epoch)),
|
|
292
|
-
)
|
|
293
|
-
return frdata
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
def _get_series_trange(series):
|
|
297
|
-
if series.xunit.is_equivalent('s'):
|
|
298
|
-
return abs(series.xspan)
|
|
299
|
-
return 0
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
def _get_series_frange(series):
|
|
303
|
-
if series.xunit.is_equivalent('Hz'): # FrequencySeries
|
|
304
|
-
return abs(series.xspan)
|
|
305
|
-
elif series.ndim == 2 and series.yunit.is_equivalent('Hz'): # Spectrogram
|
|
306
|
-
return abs(series.yspan)
|
|
307
|
-
return 0
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
def create_frprocdata(series, frame_epoch=0, comment=None,
|
|
311
|
-
type=None, subtype=None, trange=None,
|
|
312
|
-
fshift=0, phase=0, frange=None, bandwidth=0):
|
|
313
|
-
"""Create a `~frameCPP.FrAdcData` from a `~gwpy.types.Series`
|
|
314
|
-
|
|
315
|
-
.. note::
|
|
316
|
-
|
|
317
|
-
Currently this method is restricted to 1-dimensional arrays.
|
|
318
|
-
|
|
319
|
-
Parameters
|
|
320
|
-
----------
|
|
321
|
-
series : `~gwpy.types.Series`
|
|
322
|
-
the input data array to store
|
|
323
|
-
|
|
324
|
-
frame_epoch : `float`, `int`, optional
|
|
325
|
-
the GPS start epoch of the `Frame` that will contain this
|
|
326
|
-
data structure
|
|
327
|
-
|
|
328
|
-
comment : `str`, optional
|
|
329
|
-
comment
|
|
330
|
-
|
|
331
|
-
type : `int`, `str`, optional
|
|
332
|
-
type of data object
|
|
333
|
-
|
|
334
|
-
subtype : `int`, `str`, optional
|
|
335
|
-
subtype for f-Series
|
|
336
|
-
|
|
337
|
-
trange : `float`, optional
|
|
338
|
-
duration of sampled data
|
|
339
|
-
|
|
340
|
-
fshift : `float`, optional
|
|
341
|
-
frequency in the original data that corresponds to 0 Hz in the
|
|
342
|
-
heterodyned series
|
|
343
|
-
|
|
344
|
-
phase : `float`, optional
|
|
345
|
-
phase of the heterodyning signal at start of dataset
|
|
346
|
-
|
|
347
|
-
frange : `float`, optional
|
|
348
|
-
frequency range
|
|
349
|
-
|
|
350
|
-
bandwidth : `float, optional
|
|
351
|
-
reoslution bandwidth
|
|
352
|
-
|
|
353
|
-
Returns
|
|
354
|
-
-------
|
|
355
|
-
frdata : `~frameCPP.FrAdcData`
|
|
356
|
-
the newly created data structure
|
|
357
|
-
|
|
358
|
-
Notes
|
|
359
|
-
-----
|
|
360
|
-
See Table 17 (§4.3.2.11) of LIGO-T970130 for more details
|
|
361
|
-
"""
|
|
362
|
-
from LDAStools import frameCPP
|
|
363
|
-
|
|
364
|
-
# format auxiliary data
|
|
365
|
-
if trange is None:
|
|
366
|
-
trange = _get_series_trange(series)
|
|
367
|
-
if frange is None:
|
|
368
|
-
frange = _get_series_frange(series)
|
|
369
|
-
|
|
370
|
-
return frameCPP.FrProcData(
|
|
371
|
-
_series_name(series),
|
|
372
|
-
str(comment or series.name),
|
|
373
|
-
_get_frprocdata_type(series, type),
|
|
374
|
-
_get_frprocdata_subtype(series, subtype),
|
|
375
|
-
float(to_gps(series.x0.value) - to_gps(frame_epoch)),
|
|
376
|
-
trange,
|
|
377
|
-
fshift,
|
|
378
|
-
phase,
|
|
379
|
-
frange,
|
|
380
|
-
bandwidth,
|
|
381
|
-
)
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
def create_frsimdata(series, frame_epoch=0, comment=None, fshift=0, phase=0):
|
|
385
|
-
"""Create a `~frameCPP.FrAdcData` from a `~gwpy.types.Series`
|
|
386
|
-
|
|
387
|
-
.. note::
|
|
388
|
-
|
|
389
|
-
Currently this method is restricted to 1-dimensional arrays.
|
|
390
|
-
|
|
391
|
-
Parameters
|
|
392
|
-
----------
|
|
393
|
-
series : `~gwpy.types.Series`
|
|
394
|
-
the input data array to store
|
|
395
|
-
|
|
396
|
-
frame_epoch : `float`, `int`, optional
|
|
397
|
-
the GPS start epoch of the `Frame` that will contain this
|
|
398
|
-
data structure
|
|
399
|
-
|
|
400
|
-
fshift : `float`, optional
|
|
401
|
-
frequency in the original data that corresponds to 0 Hz in the
|
|
402
|
-
heterodyned series
|
|
403
|
-
|
|
404
|
-
phase : `float`, optional
|
|
405
|
-
phase of the heterodyning signal at start of dataset
|
|
406
|
-
|
|
407
|
-
Returns
|
|
408
|
-
-------
|
|
409
|
-
frdata : `~frameCPP.FrSimData`
|
|
410
|
-
the newly created data structure
|
|
411
|
-
|
|
412
|
-
Notes
|
|
413
|
-
-----
|
|
414
|
-
See Table 20 (§4.3.2.14) of LIGO-T970130 for more details
|
|
415
|
-
"""
|
|
416
|
-
from LDAStools import frameCPP
|
|
417
|
-
|
|
418
|
-
# assert correct type
|
|
419
|
-
if not series.xunit.is_equivalent('s'):
|
|
420
|
-
raise TypeError("only timeseries data can be written as FrSimData")
|
|
421
|
-
|
|
422
|
-
return frameCPP.FrSimData(
|
|
423
|
-
_series_name(series),
|
|
424
|
-
str(comment or series.name),
|
|
425
|
-
(1 / series.dx.to('s')).value,
|
|
426
|
-
float(to_gps(series.x0.value) - to_gps(frame_epoch)),
|
|
427
|
-
fshift,
|
|
428
|
-
phase,
|
|
429
|
-
)
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
def create_frvect(series):
|
|
433
|
-
"""Create a `~frameCPP.FrVect` from a `~gwpy.types.Series`
|
|
434
|
-
|
|
435
|
-
.. note::
|
|
436
|
-
|
|
437
|
-
Currently this method is restricted to 1-dimensional arrays.
|
|
438
|
-
|
|
439
|
-
Parameters
|
|
440
|
-
----------
|
|
441
|
-
series : `~gwpy.types.Series`
|
|
442
|
-
the input data array to store
|
|
443
|
-
|
|
444
|
-
Returns
|
|
445
|
-
-------
|
|
446
|
-
frvect : `~frameCPP.FrVect`
|
|
447
|
-
the newly created data vector
|
|
448
|
-
"""
|
|
449
|
-
from LDAStools import frameCPP
|
|
450
|
-
from ._framecpp import FrVectType
|
|
451
|
-
|
|
452
|
-
# create dimensions
|
|
453
|
-
dims = frameCPP.Dimension(
|
|
454
|
-
series.shape[0], # num elements
|
|
455
|
-
series.dx.value, # step size
|
|
456
|
-
str(series.dx.unit), # unit
|
|
457
|
-
0, # starting value
|
|
458
|
-
)
|
|
459
|
-
|
|
460
|
-
# create FrVect
|
|
461
|
-
vect = frameCPP.FrVect(
|
|
462
|
-
_series_name(series), # name
|
|
463
|
-
int(FrVectType.find(series.dtype)), # data type enum
|
|
464
|
-
series.ndim, # num dimensions
|
|
465
|
-
dims, # dimension object
|
|
466
|
-
str(series.unit), # unit
|
|
467
|
-
)
|
|
468
|
-
|
|
469
|
-
# populate FrVect
|
|
470
|
-
vect.GetDataArray()[:] = numpy.require(series.value, requirements=['C'])
|
|
471
|
-
|
|
472
|
-
return vect
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
# -- utilities ----------------------------------------------------------------
|
|
476
|
-
|
|
477
|
-
def num_channels(framefile):
|
|
478
|
-
"""Find the total number of channels in this framefile
|
|
479
|
-
|
|
480
|
-
**Requires:** |LDAStools.frameCPP|_
|
|
481
|
-
|
|
482
|
-
Parameters
|
|
483
|
-
----------
|
|
484
|
-
framefile : `str`
|
|
485
|
-
path to GWF-format file on disk
|
|
486
|
-
|
|
487
|
-
Returns
|
|
488
|
-
-------
|
|
489
|
-
n : `int`
|
|
490
|
-
the total number of channels found in the table of contents for this
|
|
491
|
-
file
|
|
492
|
-
"""
|
|
493
|
-
return len(get_channel_names(framefile))
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
def get_channel_type(channel, framefile):
|
|
497
|
-
"""Find the channel type in a given GWF file
|
|
498
|
-
|
|
499
|
-
**Requires:** |LDAStools.frameCPP|_
|
|
500
|
-
|
|
501
|
-
Parameters
|
|
502
|
-
----------
|
|
503
|
-
channel : `str`, `~gwpy.detector.Channel`
|
|
504
|
-
name of data channel to find
|
|
505
|
-
|
|
506
|
-
framefile : `str`
|
|
507
|
-
path of GWF file in which to search
|
|
508
|
-
|
|
509
|
-
Returns
|
|
510
|
-
-------
|
|
511
|
-
ctype : `str`
|
|
512
|
-
the type of the channel ('adc', 'sim', or 'proc')
|
|
513
|
-
|
|
514
|
-
Raises
|
|
515
|
-
------
|
|
516
|
-
ValueError
|
|
517
|
-
if the channel is not found in the table-of-contents
|
|
518
|
-
"""
|
|
519
|
-
channel = str(channel)
|
|
520
|
-
for name, type_ in _iter_channels(framefile):
|
|
521
|
-
if channel == name:
|
|
522
|
-
return type_
|
|
523
|
-
raise ValueError(
|
|
524
|
-
f"'{channel}' not found in table-of-contents for {framefile}",
|
|
525
|
-
)
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
def channel_in_frame(channel, framefile):
|
|
529
|
-
"""Determine whether a channel is stored in this framefile
|
|
530
|
-
|
|
531
|
-
**Requires:** |LDAStools.frameCPP|_
|
|
532
|
-
|
|
533
|
-
Parameters
|
|
534
|
-
----------
|
|
535
|
-
channel : `str`
|
|
536
|
-
name of channel to find
|
|
537
|
-
|
|
538
|
-
framefile : `str`
|
|
539
|
-
path of GWF file to test
|
|
540
|
-
|
|
541
|
-
Returns
|
|
542
|
-
-------
|
|
543
|
-
inframe : `bool`
|
|
544
|
-
whether this channel is included in the table of contents for
|
|
545
|
-
the given framefile
|
|
546
|
-
"""
|
|
547
|
-
return str(channel) in iter_channel_names(framefile)
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
def iter_channel_names(framefile):
|
|
551
|
-
"""Iterate over the names of channels found in a GWF file.
|
|
552
|
-
|
|
553
|
-
Parameters
|
|
554
|
-
----------
|
|
555
|
-
framefile : `str`
|
|
556
|
-
path of GWF file to read
|
|
557
|
-
|
|
558
|
-
Returns
|
|
559
|
-
-------
|
|
560
|
-
channels : `generator`
|
|
561
|
-
an iterator that will loop over the names of channels as read from
|
|
562
|
-
the table of contents of the given GWF file
|
|
563
|
-
"""
|
|
564
|
-
for name, _ in _iter_channels(framefile):
|
|
565
|
-
yield name
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
def get_channel_names(framefile):
|
|
569
|
-
"""Return a list of all channel names found in a GWF file
|
|
570
|
-
|
|
571
|
-
This method just returns
|
|
572
|
-
|
|
573
|
-
>>> list(iter_channel_names(framefile))
|
|
574
|
-
|
|
575
|
-
Parameters
|
|
576
|
-
----------
|
|
577
|
-
framefile : `str`
|
|
578
|
-
path of GWF file to read
|
|
579
|
-
|
|
580
|
-
Returns
|
|
581
|
-
-------
|
|
582
|
-
channels : `list` of `str`
|
|
583
|
-
a `list` of channel names as read from the table of contents of
|
|
584
|
-
the given GWF file
|
|
585
|
-
"""
|
|
586
|
-
return list(iter_channel_names(framefile))
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
@_gwf_library_function
|
|
590
|
-
def iter_channels(framefile):
|
|
591
|
-
"""Yields the name and type of each channel in a GWF file.
|
|
592
|
-
|
|
593
|
-
Parameters
|
|
594
|
-
----------
|
|
595
|
-
framefile : `str`
|
|
596
|
-
path of GWF file, or open file stream, to read
|
|
597
|
-
"""
|
|
598
|
-
pass # decorator does the work
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
def data_segments(paths, channel, warn=True):
|
|
602
|
-
"""Returns the segments containing data for a channel
|
|
603
|
-
|
|
604
|
-
A frame is considered to contain data if a valid FrData structure
|
|
605
|
-
(of any type) exists for the channel in that frame. No checks
|
|
606
|
-
are directly made against the underlying FrVect structures.
|
|
607
|
-
|
|
608
|
-
Parameters
|
|
609
|
-
----------
|
|
610
|
-
paths : `list` of `str`
|
|
611
|
-
a list of GWF file paths
|
|
612
|
-
|
|
613
|
-
channel : `str`
|
|
614
|
-
the name to check in each frame
|
|
615
|
-
|
|
616
|
-
warn : `bool`, optional
|
|
617
|
-
emit a `UserWarning` when a channel is not found in a frame
|
|
618
|
-
|
|
619
|
-
Returns
|
|
620
|
-
-------
|
|
621
|
-
segments : `~gwpy.segments.SegmentList`
|
|
622
|
-
the list of segments containing data
|
|
623
|
-
"""
|
|
624
|
-
segments = SegmentList()
|
|
625
|
-
for path in paths:
|
|
626
|
-
segments.extend(_gwf_channel_segments(path, channel, warn=warn))
|
|
627
|
-
return segments.coalesce()
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
def _gwf_channel_segments(path, channel, warn=True):
|
|
631
|
-
"""Yields the segments containing data for ``channel`` in this GWF path
|
|
632
|
-
"""
|
|
633
|
-
stream = open_gwf(path)
|
|
634
|
-
# get segments for frames
|
|
635
|
-
toc = stream.GetTOC()
|
|
636
|
-
secs = toc.GetGTimeS()
|
|
637
|
-
nano = toc.GetGTimeN()
|
|
638
|
-
dur = toc.GetDt()
|
|
639
|
-
|
|
640
|
-
readers = [getattr(stream, f"ReadFr{type_.title()}Data") for
|
|
641
|
-
type_ in ("proc", "sim", "adc")]
|
|
642
|
-
|
|
643
|
-
# for each segment, try and read the data for this channel
|
|
644
|
-
for i, (s, ns, dt) in enumerate(zip(secs, nano, dur)):
|
|
645
|
-
for read in readers:
|
|
646
|
-
try:
|
|
647
|
-
read(i, channel)
|
|
648
|
-
except (IndexError, ValueError):
|
|
649
|
-
continue
|
|
650
|
-
readers = [read] # use this one from now on
|
|
651
|
-
epoch = LIGOTimeGPS(s, ns)
|
|
652
|
-
yield Segment(epoch, epoch + dt)
|
|
653
|
-
break
|
|
654
|
-
else: # none of the readers worked for this channel, warn
|
|
655
|
-
if warn:
|
|
656
|
-
warnings.warn(
|
|
657
|
-
f"'{channel}' not found in frame {i} of {path}",
|
|
658
|
-
)
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
def _get_type(type_, enum):
|
|
662
|
-
"""Handle a type string, or just return an `int`
|
|
663
|
-
|
|
664
|
-
Only to be called in relation to FrProcDataType and FrProcDataSubType
|
|
665
|
-
"""
|
|
666
|
-
if isinstance(type_, int):
|
|
667
|
-
return type_
|
|
668
|
-
return enum[str(type_).upper()]
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
def _get_frprocdata_type(series, type_):
|
|
672
|
-
"""Determine the appropriate `FrProcDataType` for this series
|
|
673
|
-
|
|
674
|
-
Notes
|
|
675
|
-
-----
|
|
676
|
-
See Table 17 (§4.3.2.11) of LIGO-T970130 for more details
|
|
677
|
-
"""
|
|
678
|
-
from ._framecpp import FrProcDataType
|
|
679
|
-
|
|
680
|
-
if type_ is not None: # format user value
|
|
681
|
-
return _get_type(type_, FrProcDataType)
|
|
682
|
-
|
|
683
|
-
if series.ndim == 1 and series.xunit.is_equivalent("s"):
|
|
684
|
-
type_ = FrProcDataType.TIME_SERIES
|
|
685
|
-
elif series.ndim == 1 and series.xunit.is_equivalent("Hz"):
|
|
686
|
-
type_ = FrProcDataType.FREQUENCY_SERIES
|
|
687
|
-
elif series.ndim == 1:
|
|
688
|
-
type_ = FrProcDataType.OTHER_1D_SERIES_DATA
|
|
689
|
-
elif (
|
|
690
|
-
series.ndim == 2
|
|
691
|
-
and series.xunit.is_equivalent("s")
|
|
692
|
-
and series.yunit.is_equivalent("Hz")
|
|
693
|
-
):
|
|
694
|
-
type_ = FrProcDataType.TIME_FREQUENCY
|
|
695
|
-
elif series.ndim > 2:
|
|
696
|
-
type_ = FrProcDataType.MULTI_DIMENSIONAL
|
|
697
|
-
else:
|
|
698
|
-
type_ = FrProcDataType.UNKNOWN
|
|
699
|
-
|
|
700
|
-
return type_
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
def _get_frprocdata_subtype(series, subtype):
|
|
704
|
-
"""Determine the appropriate `FrProcDataSubType` for this series
|
|
705
|
-
|
|
706
|
-
Notes
|
|
707
|
-
-----
|
|
708
|
-
See Table 17 (§4.3.2.11) of LIGO-T970130 for more details
|
|
709
|
-
"""
|
|
710
|
-
from ._framecpp import FrProcDataSubType
|
|
711
|
-
|
|
712
|
-
if subtype is not None: # format user value
|
|
713
|
-
return _get_type(subtype, FrProcDataSubType)
|
|
714
|
-
|
|
715
|
-
if series.unit == 'coherence':
|
|
716
|
-
return FrProcDataSubType.COHERENCE
|
|
717
|
-
return FrProcDataSubType.UNKNOWN
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
def _series_name(series):
|
|
721
|
-
"""Returns the 'name' of a `Series` that should be written to GWF
|
|
722
|
-
|
|
723
|
-
This is basically `series.name or str(series.channel) or ""`
|
|
724
|
-
|
|
725
|
-
Parameters
|
|
726
|
-
----------
|
|
727
|
-
series : `gwpy.types.Series`
|
|
728
|
-
the input series that will be written
|
|
729
|
-
|
|
730
|
-
Returns
|
|
731
|
-
-------
|
|
732
|
-
name : `str`
|
|
733
|
-
the name to use when storing this series
|
|
734
|
-
"""
|
|
735
|
-
return (
|
|
736
|
-
series.name
|
|
737
|
-
or str(series.channel or "")
|
|
738
|
-
or None
|
|
739
|
-
)
|