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/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
- )