18__doc__ =
"""Gravitational wave datasource utilities, including abstractions for storing the required
19information needed to connect to data sources. The main elements of the included API are:
21 1. DataSourceInfo class for storing necessary information to connect to datasource
22 2. Useful constants to help configuring a DataSourceInfo, like the Detector and DataSource classes
23 3. Pipeline building utilities
24 4. Command-line utilities for parsing and converting values into DataSource Info
36from pathlib
import Path
40from typing
import Union, Dict
43from lal
import LIGOTimeGPS
44from ligo
import segments
45from ligo.lw
import utils
as ligolw_utils
46from ligo.lw.utils
import segments
as ligolw_segments
49gi.require_version(
'Gst',
'1.0')
50from gi.repository
import GObject
51from gi.repository
import Gst
55 if tuple(map(int, bottle.__version__.split(
"."))) < (0, 13):
64 from gstlal
import bottle
65from gstlal
import datafind
66from gstlal
import pipeparts
67from gstlal.utilities
import admin
72DEFAULT_BLOCK_SIZE = 16384 * 8 * 512
81 """Enumeration of available detectors
92 """Enumeration of available data sources
94 TODO: include descriptions of the options
99 FrameXMIT =
'framexmit'
112 DataSource.FrameXMIT,
120KNOWN_LIVE_DATASOURCES = [
121 DataSource.FrameXMIT,
125DEFAULT_SHARED_MEMORY_PARTITION = {
126 Detector.H1.value:
"LHO_Data",
127 Detector.L1.value:
"LLO_Data",
128 Detector.V1.value:
"VIRGO_Data"
130DEFAULT_SHARED_MEMORY_DIR = {
131 Detector.H1.value:
"/dev/shm/kafka/H1_Data",
132 Detector.L1.value:
"/dev/shm/kafka/L1_Data",
133 Detector.V1.value:
"/dev/shm/kafka/V1_Data"
136DEFAULT_STATE_CHANNEL = {detector.value:
"LLD-DQ_VECTOR" for detector
in Detector}
137DEFAULT_DQ_CHANNEL = {detector.value:
"DMT-DQ_VECTOR" for detector
in Detector}
138DEFAULT_FRAMXMIT_ADDR = {
139 Detector.H1.value: (
"224.3.2.1", 7096),
140 Detector.L1.value: (
"224.3.2.2", 7097),
141 Detector.V1.value: (
"224.3.2.3", 7098),
143DEFAULT_STATE_VECTOR_ON_OFF = {
144 Detector.H1.value: [0x7, 0x160],
145 Detector.H2.value: [0x7, 0x160],
146 Detector.L1.value: [0x7, 0x160],
147 Detector.V1.value: [0x67, 0x100]
149DEFAULT_DQ_VECTOR_ON_OFF = {
150 Detector.H1.value: [0x7, 0x0],
151 Detector.H2.value: [0x7, 0x0],
152 Detector.L1.value: [0x7, 0x0],
153 Detector.V1.value: [0x7, 0x0]
156HostInfo = collections.namedtuple(
'DataFindServerInfo',
'host port')
160 """Enumeration of available datafind servers"""
161 GeneralProp = HostInfo(
'datafind.ligo.org', 443)
165 """Error subclass for configuration errors"""
174 """A pythonic representation of a datasource with configured settings necessary for usage in pipelines
177 def __init__(self, data_source: Union[str, DataSource], channel_name: Dict[Detector, str],
178 gps_start_time: Union[int, LIGOTimeGPS] =
None, gps_end_time: Union[int, LIGOTimeGPS] =
None,
179 shared_memory_partition: Dict[Detector, str] =
None, shared_memory_dir: Dict[Detector, str] =
None,
180 frame_segments_name: str =
None, state_vector_on_bits: Dict[Detector, str] =
None,
181 state_vector_off_bits: Dict[Detector, str] =
None, dq_vector_on_bits: str =
None, dq_vector_off_bits: str =
None, frame_cache: Union[str, Path] =
None,
182 injections: Union[str, Path] =
None, nds_host: str =
None, nds_port: int =
None, nds_channel_type: str =
'online', shared_memory_assumed_duration: int = 4,
183 shared_memory_block_size: int = 4096, frame_segments_file: Union[str, Path] =
None, block_size: int = DEFAULT_BLOCK_SIZE, frame_type: Dict[Detector, str] =
None,
184 data_find_server: Union[str
or DataFindServer] =
None, framexmit_addr: str =
None, framexmit_iface: str =
None,
185 state_channel_name: Dict[Detector, str] =
None, dq_channel_name: Dict[Detector, str] =
None,
186 idq_channel_name: Dict[Detector, str] =
None,
187 idq_state_channel_name: Dict[Detector, str] =
None):
188 """Create a DataSource information object that contains the necessary details to produce GStreamer elements
189 for loading gravitational wave data from a variety of possible sources.
193 str or DataSource, the data source from [frames|framexmit|lvshm|nds|silence|white] which to download data
195 int or LIGOTimeGPS, the start time of the segment to analyze in GPS seconds. Required unless data_source=lvshm
197 int or LIGOTimeGPS, the end time of the segment to analyze in GPS seconds. Required unless data_source=lvshm
199 Dict[Detector, str] or Dict[Detector, HostInfo], the name of the channels to process per detector
201 Dict[Detector, str] or Dict[Detector, HostInfo], the address of the framexmit service.
203 str, the multicast interface address of the framexmit service.
205 Dict[Detector, str], the name of the state vector channel. This channel will be used to control the flow of data via the on/off bits.
207 Dict[Detector, str], the name of the data quality channel. This channel will be used to control the flow of data via the on/off bits.
209 Dict[Detector, str], the name of the idq channel. This channel will be used to create the idq_series information.
210 idq_state_channel_name:
211 Dict[Detector, str], the name of the idq state channel. This channel will be used to gate the idq_series information created by idq_channel_name.
212 shared_memory_partition:
213 Dict[Detector, str], the name of the shared memory partition for a given detector.
215 Dict[Detector, str], the name of the shared memory directory for a given detector.
217 str, the name of the segments to extract from the segment tables. Required iff frame_segments_file is given
218 state_vector_on_bits:
219 Dict[Detector, str], default None, the state vector on bits to process (optional). The default is 0x7 for all detectors. Override with {Detector:bits} Only
220 currently has meaning for online (lvshm) data.
221 state_vector_off_bits:
222 Dict[Detector, str], default None, the state vector on bits to process (optional). The default is 0x160 for all detectors. Override with {Detector:bits} Only
223 currently has meaning for online (lvshm) data.
225 Dict[Detector, str], default None, the dq vector on bits to process (optional). The default is 0x7 for all detectors. Override with {Detector:bits} Only
226 currently has meaning for online (lvshm) data.
228 Dict[Detector, str], default None, the dq vector off bits to process (optional). The default is 0x160 for all detectors. Override with {Detector:bits} Only
229 currently has meaning for online (lvshm) data.
231 str or Path, the name of the LAL cache listing the LIGO-Virgo .gwf frame files
233 str or Path, default None, the name of the LIGO light-weight XML file from which to load injections (optional)
235 str, the NDS server address. only used if data_source=nds
237 int, the NDS server port. only used if data_source=nds
239 str, default 'online', the NDS channel type. Only used if data_source=nds
240 shared_memory_assumed_duration:
241 int, default 4, the assumed span of files in seconds. Default = 4.
242 shared_memory_block_size:
243 int, default 4096, the byte size to read per buffer.
245 str or Path, the name of the LIGO light-weight XML file from which to load frame segments. Optional iff data_source=frames
247 int, default 16384 * 8 * 512 (512 seconds of double precision data at 16384 Hz), Data block size to read in bytes. This parameter is only used if
248 data_source is one of {white, silence, AdvVirgo, LIGO, AdvLIGO, nds}.
250 Dict[Detector, str], default None, a dictionary setting the frame type (string) for each detector, e.g. {Detector.H1: 'H1_GWOSC_O2_16KHZ_R1'}. Used with data_source='frames'.
252 str, default None, the data find server for LIGO data discovery. Used with data_source=frames.
254 self.
data_source = data_source.name
if isinstance(data_source, DataSourceInfo)
else data_source
256 self.
frame_cache = frame_cache.as_posix()
if isinstance(frame_cache, Path)
else frame_cache
257 self.
frame_type = {}
if frame_type
is None else frame_type
258 self.
data_find_server =
'{}:{:d}'.format(data_find_server.host, data_find_server.port)
if isinstance(data_find_server, HostInfo)
else data_find_server
259 self.
gps_start_time = gps_start_time.gpsSeconds
if isinstance(gps_start_time, LIGOTimeGPS)
else gps_start_time
260 self.
gps_end_time = gps_end_time.gpsSeconds
if isinstance(gps_end_time, LIGOTimeGPS)
else gps_end_time
261 self.
injections = injections.as_posix()
if isinstance(injections, Path)
else injections
262 self.
channel_name = {}
if channel_name
is None else channel_name
270 self.
idq_channel_name = {}
if idq_channel_name
is None else idq_channel_name
283 if state_channel_name:
292 if shared_memory_partition:
295 if shared_memory_dir:
314 self.
seg = segments.segment(start, end)
319 if self.
seg is not None:
323 self.
frame_segments = segments.segmentlistdict((detector, seglist & segments.segmentlist([self.
seg]))
for detector, seglist
in self.
frame_segments.items())
330 _frame_cache = datafind.load_frame_cache(start, end, frame_type_dict, host=self.
data_find_server)
332 self.
_frame_cache_fileobj = tempfile.NamedTemporaryFile(suffix=
".cache", dir=os.getenv(
"_CONDOR_SCRATCH_DIR", tempfile.gettempdir()))
335 for cacheentry
in _frame_cache:
336 print(str(cacheentry), file=f)
342 """Validation of configuration"""
349 raise DataSourceConfigError(
"frame_cache or frame_type must be specified when using data_source='frames'")
365 raise DataSourceConfigError(
"Can only specify --idq-channel-name if --idq-state-channel-name is given")
367 raise DataSourceConfigError(
"Can only specify --idq-state-channel-name if --idq-channel-name is given")
384 except ValueError
as e:
388 except ValueError
as e:
395 """Construct a DataSourceInfo object from an optparer.OptionParser
399 Values, with all of the arguments defined in append_options
402 DataSourceInfo object
404 channel_dict = parse_list_to_dict(options.channel_name)
405 frame_type = parse_list_to_dict(options.frame_type)
406 shared_memory_part = parse_list_to_dict(options.shared_memory_partition)
407 shared_memory_dir = parse_list_to_dict(options.shared_memory_dir)
408 state_channel_name = parse_list_to_dict(options.state_channel_name)
409 dq_channel_name = parse_list_to_dict(options.dq_channel_name)
410 idq_channel_name = parse_list_to_dict(options.idq_channel_name)
411 idq_state_channel_name = parse_list_to_dict(options.idq_state_channel_name)
412 state_vector_on_bits = parse_list_to_dict(options.state_vector_on_bits, value_transform=parse_int)
413 state_vector_off_bits = parse_list_to_dict(options.state_vector_off_bits, value_transform=parse_int)
414 dq_vector_on_bits = parse_list_to_dict(options.dq_vector_on_bits, value_transform=parse_int)
415 dq_vector_off_bits = parse_list_to_dict(options.dq_vector_off_bits, value_transform=parse_int)
418 block_size=options.block_size,
419 frame_cache=options.frame_cache,
420 frame_type=frame_type,
421 data_find_server=options.data_find_server,
422 gps_start_time=options.gps_start_time,
423 gps_end_time=options.gps_end_time,
424 injections=options.injection_file,
425 channel_name=channel_dict,
426 nds_host=options.nds_host
if options.data_source == DataSource.NDS
else None,
427 nds_port=options.nds_port
if options.data_source == DataSource.NDS
else None,
428 nds_channel_type=options.nds_channel_type
if options.data_source == DataSource.NDS
else None,
429 framexmit_addr=options.framexmit_addr,
430 framexmit_iface=options.framexmit_iface,
431 state_channel_name=state_channel_name,
432 dq_channel_name=dq_channel_name,
433 idq_channel_name=idq_channel_name,
434 idq_state_channel_name=idq_state_channel_name,
435 shared_memory_partition=shared_memory_part,
436 shared_memory_assumed_duration=options.shared_memory_assumed_duration,
437 shared_memory_block_size=options.shared_memory_block_size,
438 shared_memory_dir=shared_memory_dir,
439 frame_segments_file=options.frame_segments_file,
440 frame_segments_name=options.frame_segments_name,
441 state_vector_on_bits=state_vector_on_bits,
442 state_vector_off_bits=state_vector_off_bits,
443 dq_vector_on_bits=dq_vector_on_bits,
444 dq_vector_off_bits=dq_vector_off_bits)
452def parse_host(host: str):
453 """Value transform for use with parse_list_to_dict that splits host into name and port tuple"""
454 name, port = host.split(
':')
455 return (name, int(port))
458def parse_int(inp: str) -> int:
459 """Value transform for use with parse_list_to_dict that coerces string input to int"""
460 if inp.startswith(
'0x'):
465def parse_list_to_dict(lst: list, value_transform: types.FunctionType =
None, sep: str =
'=', key_is_range: bool =
False, range_sep: str =
':') -> dict:
466 """A general list to dict argument parsing coercion function
470 list, a list of the form ['A=V1', 'B=V2', ...], where "=" only has to match the sep_str argument
472 Function, default None. An optional transformation function to apply on values of the dictionary
474 str, default '=', the separator string between dict keys and values in list elements
476 bool, default False. If True, the keys of the list are compound and contain range information e.g. "start:stop:remaining,list,of,items"
478 str, default ':' the separator string for range key information
481 dict of the form {'A': value_transform('V1'), ...}
484 >>> parse_list_to_dict(["H1=LSC-STRAIN", "H2=SOMETHING-ELSE"]) # doctest: +SKIP
485 {'H1': 'LSC-STRAIN', 'H2': 'SOMETHING-ELSE'}
487 >>> parse_list_to_dict(["0000:0002:H1=LSC_STRAIN_1,L1=LSC_STRAIN_2", "0002:0004:H1=LSC_STRAIN_3,L1=LSC_STRAIN_4", "0004:0006:H1=LSC_STRAIN_5,L1=LSC_STRAIN_6"], key_is_range=True) # doctest: +SKIP
488 {'0000': {'H1': 'LSC_STRAIN_1', 'L1': 'LSC_STRAIN_2'}, '0001': {'H1': 'LSC_STRAIN_1', 'L1': 'LSC_STRAIN_2'}, '0002': {'H1': 'LSC_STRAIN_3', 'L1': 'LSC_STRAIN_4'}, '0003': {'H1': 'LSC_STRAIN_3', 'L1': 'LSC_STRAIN_4'}, '0004': {'H1': 'LSC_STRAIN_5', 'L1': 'LSC_STRAIN_6'}, '0005': {'H1': 'LSC_STRAIN_5', 'L1': 'LSC_STRAIN_6'}}
495 splits = [e.split(range_sep)
for e
in lst]
496 for start, stop, val
in splits:
497 for i
in range(int(start), int(stop)):
498 key = str(i).zfill(4)
499 coerced[key] = parse_list_to_dict([l.strip()
for l
in val.split(
',')], value_transform=value_transform, sep=sep, key_is_range=
False)
501 if len(lst) == 1
and sep
not in lst[0]:
503 coerced = dict([e.split(sep)
for e
in lst])
504 if value_transform
is not None:
506 coerced[k] = value_transform(coerced[k])
511def ravel_host(host: tuple) -> str:
512 """Value transform for use with ravel_dict_to_list that ravels a host name and port into a string"""
513 return '{}:{}'.format(host[0], str(host[1]))
516def ravel_dict_to_list(dct: dict, value_transform: types.FunctionType = str, sep: str =
'=', key_is_range: bool =
False, range_sep: str =
':', join_arg: str =
None,
517 unzip: bool =
False, filter_keys: list =
None, range_elem: int =
None) -> list:
518 """Functional inverse of parse_list_to_dict.
520 TODO: This function exists to work around pipeline.py's inability to give the same option more than once by producing a string to pass as an argument that encodes the other instances of the option.
524 dict, the dict to transform into a list
526 Function, default str, the way to transform values of the dict before adding to list
528 str, default '=' separator character to join key-value pairs
530 bool, default False. If True, aggregate keys into ranges
532 str, default ':', the range separator to join range key min and max values
534 bool, default False, if True unzip the dct arg and ravel each single-valued dict separately
537 List[str] the dict converted into lists of strings
541 if range_elem
is None:
542 raise NotImplementedError
544 dct = dct[str(range_elem).zfill(4)]
547 dct = dict([(k, v)
for k, v
in dct.items()
if k
in filter_keys])
550 dicts = unzip_dict_values(dct)
551 if not isinstance(join_arg, list):
552 join_arg = len(dicts) * [join_arg]
553 return [ravel_dict_to_list(d, value_transform=value_transform, sep=sep, key_is_range=key_is_range, range_sep=range_sep, join_arg=j, unzip=
False)
for d, j
in
554 zip(dicts, join_arg)]
556 lst = [
'{}{}{}'.format(k, sep, value_transform(v))
for k, v
in sorted(dct.items(), key=
lambda x: x[0])]
559 if join_arg
is not None:
562 lst = lst[0] +
' ' +
' '.join(
'--' + join_arg +
'=' + l
for l
in lst[1:])
566def zip_dict_values(*dicts, defaults: dict =
None, key_union: bool =
True):
567 """Zip dict values by matching keys
571 Iterable[dict], a collection of dicts whose values will be grouped by key in the order given
573 dict, default None, if specified fill in missing values with these defaults
575 bool, default True, if True then use a union of keys, else use intersection.
579 >>> on_bit_list = parse_list_to_dict(["V1=7", "H1=7", "L1=7"], value_transform=int) # doctest: +SKIP
580 >>> off_bit_list = parse_list_to_dict(["V1=256", "H1=352", "L1=352"], value_transform=int) # doctest: +SKIP
581 >>> zip_dict_values(on_bit_list, off_bit_list, defaults=DEFAULT_STATE_VECTOR_ON_OFF) # doctest: +SKIP
582 {'V1': [7, 256], 'H1': [7, 352], 'H2': [7, 352], 'L1': [7, 352]}
584 >>> zip_dict_values(on_bit_list, off_bit_list,{}) # doctest: +SKIP
585 {'V1': [7, 256], 'H1': [7, 352], 'L1': [7, 352]}
587 >>> on_bit_list = parse_list_to_dict(["V1=0x7", "H1=0x7", "L1=0x7"], value_transform=lambda x: int(x, 16)) # doctest: +SKIP
588 >>> off_bit_list = parse_list_to_dict(["V1=0x256", "H1=0x352", "L1=0x352"], value_transform=lambda x: int(x, 16)) # doctest: +SKIP
589 >>> zip_dict_values(on_bit_list, off_bit_list,{}) # doctest: +SKIP
590 {'V1': [7, 598], 'H1': [7, 850], 'L1': [7, 850]}
592 keys = list(getattr(set(),
'union' if key_union
else 'intersection')(*([set(d.keys())
for d
in dicts] + ([]
if defaults
is None else [set(defaults.keys())]))))
595 ordered_value = [d[k]
for d
in dicts
if k
in d]
596 if not ordered_value:
597 ordered_value = defaults[k]
598 unified[k] = ordered_value
602def unzip_dict_values(dct: dict):
603 """Split multi-valued dict into ordered collection of single-valued dicts with common keys
604 All values should be of same length.
606 num_vals = len(list(dct.values())[0])
607 if any(len(v) != num_vals
for v
in dct.values()):
608 raise ValueError(
'All dict values must have same length.')
609 dicts = [dict()
for n
in range(num_vals)]
610 for k
in sorted(list(dct.keys())):
611 ordered_vals = list(dct[k])
612 for n
in range(num_vals):
613 dicts[n][k] = ordered_vals[n]
617def append_options(parser):
619 Append generic data source options to an OptionParser object in order
620 to have consistent an unified command lines and parsing throughout the project
621 for applications that read GW data.
623- --data-source [string]
624 Set the data source from [frames|framexmit|lvshm|nds|silence|white].
626- --block-size [int] (bytes)
627 Data block size to read in bytes. Default 16384 * 8 * 512 which is 512 seconds of double
628 precision data at 16384 Hz. This parameter is only used if --data-source is one of
629 white, silence, AdvVirgo, LIGO, AdvLIGO, nds.
631- --frame-cache [filename]
632 Set the name of the LAL cache listing the LIGO-Virgo .gwf frame files (optional).
634- --frame-type [string]
635 Set the frame type for a given instrument.
636 Can be given multiple times as --frame-type=IFO=FRAME-TYPE
638- --gps-start-time [int] (seconds)
639 Set the start time of the segment to analyze in GPS seconds.
640 Required unless --data-source is lvshm or framexmit
642- --gps-end-time [int] (seconds)
643 Set the end time of the segment to analyze in GPS seconds.
644 Required unless --data-source in lvshm,framexmit
646- --injection-file [filename]
647 Set the name of the LIGO light-weight XML file from which to load injections (optional).
649- --channel-name [string]
650 Set the name of the channels to process.
651 Can be given multiple times as --channel-name=IFO=CHANNEL-NAME
653- --nds-host [hostname]
654 Set the remote host or IP address that serves nds data.
655 This is required iff --data-source is nds
657- --nds-port [portnumber]
658 Set the port of the remote host that serves nds data, default = 31200.
659 This is required iff --data-source is nds
661- --nds-channel-type [string] type
662 FIXME please document
664- --framexmit-addr [string]
665 Set the address of the framexmit service. Can be given
666 multiple times as --framexmit-addr=IFO=xxx.xxx.xxx.xxx:port
668- --framexmit-iface [string]
669 Set the address of the framexmit interface.
671- --state-channel-name [string]
672 Set the name of the state vector channel.
673 This channel will be used to control the flow of data via the on/off bits.
674 Can be given multiple times as --state-channel-name=IFO=STATE-CHANNEL-NAME
676- --dq-channel-name [string]
677 Set the name of the data quality channel.
678 This channel will be used to control the flow of data via the on/off bits.
679 Can be given multiple times as --state-channel-name=IFO=DQ-CHANNEL-NAME
681- --shared-memory-partition [string]
682 Set the name of the shared memory partition for a given instrument.
683 Can be given multiple times as --shared-memory-partition=IFO=PARTITION-NAME
685- --shared-memory-dir [string]
686 Set the name of the shared memory directory for a given instrument.
687 Can be given multiple times as --shared-memory-dir=IFO=DIR-NAME
689- --shared-memory-assumed-duration [int]
690 Set the assumed span of files in seconds. Default = 4 seconds.
692- --shared-memory-block-size [int]
693 Set the byte size to read per buffer. Default = 4096 bytes.
695- --frame-segments-file [filename]
696 Set the name of the LIGO light-weight XML file from which to load frame segments.
697 Optional iff --data-source is frames
699- --frame-segments-name [string]
700 Set the name of the segments to extract from the segment tables.
701 Required iff --frame-segments-file is given
703- --state-vector-on-bits [hex]
704 Set the state vector on bits to process (optional).
705 The default is 0x7 for all detectors. Override with IFO=bits can be given multiple times.
706 Only currently has meaning for online (lvshm, framexmit) data
708- --state-vector-off-bits [hex]
709 Set the state vector off bits to process (optional).
710 The default is 0x160 for all detectors. Override with IFO=bits can be given multiple times.
711 Only currently has meaning for online (lvshm, framexmit) data
713- --dq-vector-on-bits [hex]
714 Set the state vector on bits to process (optional).
715 The default is 0x7 for all detectors. Override with IFO=bits can be given multiple times.
716 Only currently has meaning for online (lvshm, framexmit) data
718- --dq-vector-off-bits [hex]
719 Set the dq vector off bits to process (optional).
720 The default is 0x0 for all detectors. Override with IFO=bits can be given multiple times.
721 Only currently has meaning for online (lvshm, framexmit) data
723 **Typical usage case examples**
725 1. Reading data from frames::
727 --data-source=frames --gps-start-time=999999000 --gps-end-time=999999999 \\
728 --channel-name=H1=LDAS-STRAIN --frame-segments-file=segs.xml \\
729 --frame-segments-name=datasegments
731 2. Reading data from a fake LIGO source::
733 --data-source=LIGO --gps-start-time=999999000 --gps-end-time=999999999 \\
734 --channel-name=H1=FAIKE-STRAIN
736 3. Reading online data via framexmit::
738 --data-source=framexmit --channel-name=H1=FAIKE-STRAIN
740 4. Many other combinations possible, please add some!
742 group = optparse.OptionGroup(parser,
"Data source options",
"Use these options to set up the appropriate data source")
743 group.add_option(
"--data-source", metavar=
"source", help=
"Set the data source from [frames|framexmit|lvshm|nds|silence|white]. Required.")
744 group.add_option(
"--block-size", type=
"int", metavar=
"bytes", default=16384 * 8 * 512,
745 help=
"Data block size to read in bytes. Default 16384 * 8 * 512 (512 seconds of double precision data at 16384 Hz. This parameter is only used if --data-source is one of white, silence, AdvVirgo, LIGO, AdvLIGO, nds.")
746 group.add_option(
"--frame-cache", metavar=
"filename", help=
"Set the name of the LAL cache listing the LIGO-Virgo .gwf frame files (optional).")
747 group.add_option(
"--frame-type", metavar=
"name", action=
"append",
748 help=
"Set the frame type for a given instrument. Can be given multiple times as --frame-type=IFO=FRAME-TYPE. Used with --data-source=frames")
749 group.add_option(
"--data-find-server", metavar=
"url", help=
"Set the data find server for LIGO data discovery. Used with --data-source=frames")
750 group.add_option(
"--gps-start-time", metavar=
"seconds", help=
"Set the start time of the segment to analyze in GPS seconds. Required unless --data-source=lvshm")
751 group.add_option(
"--gps-end-time", metavar=
"seconds", help=
"Set the end time of the segment to analyze in GPS seconds. Required unless --data-source=lvshm")
752 group.add_option(
"--injection-file", metavar=
"filename", help=
"Set the name of the LIGO light-weight XML file from which to load injections (optional).")
753 group.add_option(
"--channel-name", metavar=
"name", action=
"append",
754 help=
"Set the name of the channels to process. Can be given multiple times as --channel-name=IFO=CHANNEL-NAME")
755 group.add_option(
"--idq-channel-name", metavar=
"idqname", action=
"append", help=
"iDQ channel names to process. Must also provide idq-state-channel-name. Can be given multiple times as --idq-channel-name=IFO=IDQ-CHANNEL-NAME")
756 group.add_option(
"--idq-state-channel-name", metavar=
"idqstatename", action=
"append", help=
"iDQ state channel names to process. Can be given multiple times as --idq-state-channel-name=IFO=IDQ-STATE-CHANNEL-NAME")
757 group.add_option(
"--nds-host", metavar=
"hostname", help=
"Set the remote host or IP address that serves nds data. This is required iff --data-source=nds")
758 group.add_option(
"--nds-port", metavar=
"portnumber", type=int, default=31200,
759 help=
"Set the port of the remote host that serves nds data. This is required iff --data-source=nds")
760 group.add_option(
"--nds-channel-type", metavar=
"type", default=
"online",
761 help=
"Set the port of the remote host that serves nds data. This is required only if --data-source=nds. default==online")
762 group.add_option(
"--framexmit-addr", metavar=
"name", action=
"append",
763 help=
"Set the address of the framexmit service. Can be given multiple times as --framexmit-addr=IFO=xxx.xxx.xxx.xxx:port")
764 group.add_option(
"--framexmit-iface", metavar=
"name", help=
"Set the multicast interface address of the framexmit service.")
765 group.add_option(
"--state-channel-name", metavar=
"name", action=
"append",
766 help=
"Set the name of the state vector channel. This channel will be used to control the flow of data via the on/off bits. Can be given multiple times as --channel-name=IFO=CHANNEL-NAME")
767 group.add_option(
"--dq-channel-name", metavar=
"name", action=
"append",
768 help=
"Set the name of the data quality channel. This channel will be used to control the flow of data via the on/off bits. Can be given multiple times as --channel-name=IFO=CHANNEL-NAME")
769 group.add_option(
"--shared-memory-partition", metavar=
"name", action=
"append",
770 help=
"Set the name of the shared memory partition for a given instrument. Can be given multiple times as --shared-memory-partition=IFO=PARTITION-NAME")
771 group.add_option(
"--shared-memory-dir", metavar=
"name", action=
"append",
772 help=
"Set the name of the shared memory directory for a given instrument. Can be given multiple times as --shared-memory-dir=IFO=DIR-NAME")
773 group.add_option(
"--shared-memory-assumed-duration", type=
"int", default=4, help=
"Set the assumed span of files in seconds. Default = 4.")
774 group.add_option(
"--shared-memory-block-size", type=
"int", default=4096, help=
"Set the byte size to read per buffer. Default = 4096.")
775 group.add_option(
"--frame-segments-file", metavar=
"filename",
776 help=
"Set the name of the LIGO light-weight XML file from which to load frame segments. Optional iff --data-source=frames")
777 group.add_option(
"--frame-segments-name", metavar=
"name", help=
"Set the name of the segments to extract from the segment tables. Required iff --frame-segments-file is given")
778 group.add_option(
"--state-vector-on-bits", metavar=
"bits", default=[], action=
"append",
779 help=
"Set the state vector on bits to process (optional). The default is 0x7 for all detectors. Override with IFO=bits can be given multiple times. Only currently has meaning for online (lvshm) data.")
780 group.add_option(
"--state-vector-off-bits", metavar=
"bits", default=[], action=
"append",
781 help=
"Set the state vector off bits to process (optional). The default is 0x160 for all detectors. Override with IFO=bits can be given multiple times. Only currently has meaning for online (lvshm) data.")
782 group.add_option(
"--dq-vector-on-bits", metavar=
"bits", default=[], action=
"append",
783 help=
"Set the DQ vector on bits to process (optional). The default is 0x7 for all detectors. Override with IFO=bits can be given multiple times. Only currently has meaning for online (lvshm) data.")
784 group.add_option(
"--dq-vector-off-bits", metavar=
"bits", default=[], action=
"append",
785 help=
"Set the DQ vector off bits to process (optional). The default is 0x160 for all detectors. Override with IFO=bits can be given multiple times. Only currently has meaning for online (lvshm) data.")
786 parser.add_option_group(group)
794def pipeline_seek_for_gps(pipeline, gps_start_time, gps_end_time, flags=Gst.SeekFlags.FLUSH):
796 Create a new seek event, i.e., Gst.Event.new_seek() for a given
797 gps_start_time and gps_end_time, with optional flags.
799 @param gps_start_time start time as LIGOTimeGPS, double or float
800 @param gps_end_time start time as LIGOTimeGPS, double or float
803 def seek_args_for_gps(gps_time):
805 Convenience routine to convert a GPS time to a seek type and a
809 if gps_time
is None or gps_time == -1:
810 return (Gst.SeekType.NONE, -1)
811 elif hasattr(gps_time,
'ns'):
812 return (Gst.SeekType.SET, gps_time.ns())
814 return (Gst.SeekType.SET, int(float(gps_time) * Gst.SECOND))
816 start_type, start_time = seek_args_for_gps(gps_start_time)
817 stop_type, stop_time = seek_args_for_gps(gps_end_time)
866 if pipeline.current_state != Gst.State.READY:
867 raise ValueError(
"pipeline must be in READY state")
869 for elem
in pipeline.iterate_sources():
870 elem.seek(1.0, Gst.Format(Gst.Format.TIME), flags, start_type, start_time, stop_type, stop_time)
873def mksegmentsrcgate(pipeline, src, segment_list, invert_output=False, rate=1, **kwargs):
875 Takes a segment list and produces a gate driven by it. Hook up your own input and output.
877 @param kwargs passed through to pipeparts.mkgate(), e.g., used to set the gate's name.
879 Gstreamer graph describing this function:
885 node [shape=record fontsize=10 fontname="Verdana"];
890 out [label="<return value>"];
891 in -> lal_gate -> out;
892 lal_segmentsrc -> lal_gate;
896 return pipeparts.mkgate(pipeline, src, threshold=1, control=pipeparts.mkcapsfilter(pipeline, pipeparts.mksegmentsrc(pipeline, segment_list, invert_output=invert_output),
897 caps=
"audio/x-raw, rate=%d" % rate), **kwargs)
900def mkbasicsrc(pipeline, gw_data_source_info, instrument, verbose=False):
902 All the conditionals and stupid pet tricks for reading real or
903 simulated h(t) data in one place.
905 Consult the append_options() function and the GWDataSourceInfo class
907 This src in general supports only one instrument although
908 GWDataSourceInfo contains dictionaries of multi-instrument things. By
909 specifying the instrument when calling this function you will get ony a single
910 instrument source. A code wishing to have multiple basicsrcs will need to call
911 this function for each instrument.
919 node [shape=record fontsize=10 fontname="Verdana"];
920 subgraph clusterfakesrc {
921 fake_0 [label="fakesrc: white, silence, AdvVirgo, LIGO, AdvLIGO"];
923 label="Possible path #1";
925 subgraph clusterframes {
927 frames_0 [label="lalcachesrc: frames"];
928 frames_1 [label ="framecppchanneldemux"];
929 frames_2 [label ="queue"];
930 frames_3 [label ="gate (if user provides segments)", style=filled, color=lightgrey];
931 frames_4 [label ="audiorate"];
932 frames_0 -> frames_1 -> frames_2 -> frames_3 ->frames_4;
933 label="Possible path #2";
935 subgraph clusteronline {
937 online_0 [label="lvshmsrc|framexmit"];
938 online_1 [label ="framecppchanneldemux"];
939 online_2a [label ="strain queue"];
940 online_2b [label ="statevector queue"];
941 online_3 [label ="statevector"];
942 online_4 [label ="gate"];
943 online_5 [label ="audiorate"];
944 online_6 [label ="queue"];
945 online_0 -> online_1;
946 online_1 -> online_2a;
947 online_1 -> online_2b;
948 online_2b -> online_3;
949 online_2a -> online_4;
950 online_3 -> online_4 -> online_5 -> online_6;
951 label="Possible path #3";
953 subgraph clusternds {
954 nds_0 [label="ndssrc"];
956 label="Possible path #4";
958 audioconv [label="audioconvert"];
959 progress [label="progressreport (if verbose)", style=filled, color=lightgrey];
960 sim [label="lalsimulation (if injections requested)", style=filled, color=lightgrey];
961 queue [label="queue (if injections requested)", style=filled, color=lightgrey];
964 fake_0 -> audioconv [ltail=clusterfakesrc];
965 frames_4 -> audioconv [ltail=clusterframes];
966 online_6 -> audioconv [ltail=clusteronline];
967 nds_0 -> audioconv [ltail=clusternds];
968 audioconv -> progress -> sim -> queue -> "?";
972 statevector = dqvector =
None
974 idqstatevector =
None
979 if gw_data_source_info.data_source == DataSource.White:
980 src = pipeparts.mkfakesrc(pipeline, instrument, gw_data_source_info.channel_dict[instrument], blocksize=gw_data_source_info.block_size, volume=1.0,
981 timestamp_offset=int(gw_data_source_info.seg[0]) * Gst.SECOND)
982 elif gw_data_source_info.data_source == DataSource.Silence:
983 src = pipeparts.mkfakesrc(pipeline, instrument, gw_data_source_info.channel_dict[instrument], blocksize=gw_data_source_info.block_size, wave=4,
984 timestamp_offset=int(gw_data_source_info.seg[0]) * Gst.SECOND)
985 elif gw_data_source_info.data_source == DataSource.LIGO:
986 src = pipeparts.mkfakeLIGOsrc(pipeline, instrument=instrument, channel_name=gw_data_source_info.channel_dict[instrument], blocksize=gw_data_source_info.block_size)
987 elif gw_data_source_info.data_source == DataSource.ALIGO:
988 src = pipeparts.mkfakeadvLIGOsrc(pipeline, instrument=instrument, channel_name=gw_data_source_info.channel_dict[instrument], blocksize=gw_data_source_info.block_size)
989 elif gw_data_source_info.data_source == DataSource.AVirgo:
990 src = pipeparts.mkfakeadvvirgosrc(pipeline, instrument=instrument, channel_name=gw_data_source_info.channel_dict[instrument], blocksize=gw_data_source_info.block_size)
991 elif gw_data_source_info.data_source == DataSource.Frames:
992 if instrument == Detector.V1:
996 src = pipeparts.mklalcachesrc(pipeline, location=gw_data_source_info.frame_cache, cache_src_regex=
"V")
998 src = pipeparts.mklalcachesrc(pipeline, location=gw_data_source_info.frame_cache, cache_src_regex=instrument[0], cache_dsc_regex=instrument)
999 demux = pipeparts.mkframecppchanneldemux(pipeline, src, do_file_checksum=
False, channel_list=list(map(
"%s:%s".__mod__, gw_data_source_info.channel_dict.items())))
1000 pipeparts.framecpp_channeldemux_set_units(demux, dict.fromkeys(demux.get_property(
"channel-list"),
"strain"))
1003 src = pipeparts.mkqueue(pipeline,
None, max_size_buffers=0, max_size_bytes=0, max_size_time=8 * Gst.SECOND)
1004 pipeparts.src_deferred_link(demux,
"%s:%s" % (instrument, gw_data_source_info.channel_dict[instrument]), src.get_static_pad(
"sink"))
1005 if gw_data_source_info.frame_segments[instrument]
is not None:
1010 src = pipeparts.mkgate(pipeline, src, threshold=1, control=pipeparts.mksegmentsrc(pipeline, gw_data_source_info.frame_segments[instrument]),
1011 name=
"%s_frame_segments_gate" % instrument)
1012 pipeparts.framecpp_channeldemux_check_segments.set_probe(src.get_static_pad(
"src"), gw_data_source_info.frame_segments[instrument])
1014 src = pipeparts.mkaudiorate(pipeline, src, skip_to_first=
True, silent=
False)
1015 elif gw_data_source_info.data_source
in (DataSource.FrameXMIT.value, DataSource.LVSHM.value, DataSource.DEVSHM.value):
1017 state_vector_on_bits, state_vector_off_bits = gw_data_source_info.state_vector_on_off_bits[instrument]
1018 dq_vector_on_bits, dq_vector_off_bits = gw_data_source_info.dq_vector_on_off_bits[instrument]
1020 if gw_data_source_info.data_source == DataSource.LVSHM:
1023 src = pipeparts.mklvshmsrc(pipeline, shm_name=gw_data_source_info.shm_part_dict[instrument], assumed_duration=gw_data_source_info.shm_assumed_duration,
1024 blocksize=gw_data_source_info.shm_block_size, wait_time=120)
1025 elif gw_data_source_info.data_source == DataSource.FrameXMIT:
1026 src = pipeparts.mkframexmitsrc(pipeline, multicast_iface=gw_data_source_info.framexmit_iface, multicast_group=gw_data_source_info.framexmit_addr[instrument][0],
1027 port=gw_data_source_info.framexmit_addr[instrument][1], wait_time=120)
1028 elif gw_data_source_info.data_source == DataSource.DEVSHM:
1029 src = pipeparts.mkdevshmsrc(pipeline, shm_dirname=gw_data_source_info.shared_memory_dir[instrument], wait_time=60, watch_suffix=
'.gwf')
1032 raise ValueError(gw_data_source_info.data_source)
1035 src = pipeparts.mkqueue(pipeline, src, max_size_buffers=0, max_size_bytes=0, max_size_time=Gst.SECOND * 60 * 10)
1036 src = pipeparts.mkframecppchanneldemux(pipeline, src, do_file_checksum=
False, skip_bad_files=
True)
1040 if gw_data_source_info.dq_channel_dict[instrument] == gw_data_source_info.state_channel_dict[instrument]:
1041 dqstatetee = pipeparts.mktee(pipeline,
None)
1042 statevectorelem = statevector = pipeparts.mkstatevector(pipeline, dqstatetee, required_on=state_vector_on_bits, required_off=state_vector_off_bits,
1043 name=
"%s_state_vector" % instrument)
1044 dqvectorelem = dqvector = pipeparts.mkstatevector(pipeline, dqstatetee, required_on=dq_vector_on_bits, required_off=dq_vector_off_bits,
1045 name=
"%s_dq_vector" % instrument)
1046 pipeparts.src_deferred_link(src,
"%s:%s" % (instrument, gw_data_source_info.state_channel_dict[instrument]), dqstatetee.get_static_pad(
"sink"))
1050 dqvectorelem = dqvector = pipeparts.mkstatevector(pipeline,
None, required_on=dq_vector_on_bits, required_off=dq_vector_off_bits, name=
"%s_dq_vector" % instrument)
1051 pipeparts.src_deferred_link(src,
"%s:%s" % (instrument, gw_data_source_info.dq_channel_dict[instrument]), dqvector.get_static_pad(
"sink"))
1053 statevectorelem = statevector = pipeparts.mkstatevector(pipeline,
None, required_on=state_vector_on_bits, required_off=state_vector_off_bits,
1054 name=
"%s_state_vector" % instrument)
1055 pipeparts.src_deferred_link(src,
"%s:%s" % (instrument, gw_data_source_info.state_channel_dict[instrument]), statevector.get_static_pad(
"sink"))
1057 @bottle.route("/%s/statevector_on.txt" % instrument)
1058 def state_vector_state(elem=statevectorelem):
1059 t = float(lal.UTCToGPS(time.gmtime()))
1060 on = elem.get_property(
"on-samples")
1061 return "%.9f %d" % (t, on)
1063 @bottle.route("/%s/statevector_off.txt" % instrument)
1064 def state_vector_state(elem=statevectorelem):
1065 t = float(lal.UTCToGPS(time.gmtime()))
1066 off = elem.get_property(
"off-samples")
1067 return "%.9f %d" % (t, off)
1069 @bottle.route("/%s/statevector_gap.txt" % instrument)
1070 def state_vector_state(elem=statevectorelem):
1071 t = float(lal.UTCToGPS(time.gmtime()))
1072 gap = elem.get_property(
"gap-samples")
1073 return "%.9f %d" % (t, gap)
1075 @bottle.route("/%s/dqvector_on.txt" % instrument)
1076 def dq_vector_state(elem=dqvectorelem):
1077 t = float(lal.UTCToGPS(time.gmtime()))
1078 on = elem.get_property(
"on-samples")
1079 return "%.9f %d" % (t, on)
1081 @bottle.route("/%s/dqvector_off.txt" % instrument)
1082 def dq_vector_state(elem=dqvectorelem):
1083 t = float(lal.UTCToGPS(time.gmtime()))
1084 off = elem.get_property(
"off-samples")
1085 return "%.9f %d" % (t, off)
1087 @bottle.route("/%s/dqvector_gap.txt" % instrument)
1088 def dq_vector_state(elem=dqvectorelem):
1089 t = float(lal.UTCToGPS(time.gmtime()))
1090 gap = elem.get_property(
"gap-samples")
1091 return "%.9f %d" % (t, gap)
1094 strain = pipeparts.mkqueue(pipeline,
None, max_size_buffers=1, max_size_bytes=0, max_size_time=0)
1095 pipeparts.src_deferred_link(src,
"%s:%s" % (instrument, gw_data_source_info.channel_dict[instrument]), strain.get_static_pad(
"sink"))
1096 pipeparts.framecpp_channeldemux_set_units(src, {
"%s:%s" % (instrument, gw_data_source_info.channel_dict[instrument]):
"strain"})
1099 if instrument
in gw_data_source_info.idq_channel_name:
1100 idqseries = pipeparts.mkqueue(pipeline,
None, max_size_buffers=1, max_size_bytes=0, max_size_time=0)
1101 pipeparts.src_deferred_link(src,
"%s:%s" % (instrument, gw_data_source_info.idq_channel_name[instrument]), idqseries.get_static_pad(
"sink"))
1102 if instrument
in gw_data_source_info.idq_state_channel_name:
1103 idqstatevector = pipeparts.mkqueue(pipeline,
None, max_size_buffers=1, max_size_bytes=0, max_size_time=0)
1104 pipeparts.src_deferred_link(src,
"%s:%s" % (instrument, gw_data_source_info.idq_state_channel_name[instrument]), idqstatevector.get_static_pad(
"sink"))
1107 statevector = pipeparts.mkreblock(pipeline, pipeparts.mkaudiorate(pipeline, statevector, skip_to_first=
True, silent=
False), block_duration = Gst.SECOND // 4)
1108 dqvector = pipeparts.mkreblock(pipeline, pipeparts.mkaudiorate(pipeline, dqvector, skip_to_first=
True, silent=
False), block_duration = Gst.SECOND // 4)
1109 src = pipeparts.mkreblock(pipeline, pipeparts.mkaudiorate(pipeline, strain, skip_to_first=
True, silent=
False, name=
"%s_strain_audiorate" % instrument), block_duration = Gst.SECOND // 4)
1110 if instrument
in gw_data_source_info.idq_channel_name:
1111 idqseries = pipeparts.mkreblock(pipeline, pipeparts.mkaudiorate(pipeline, idqseries, skip_to_first=
True, silent=
False), block_duration = Gst.SECOND // 4)
1112 if instrument
in gw_data_source_info.idq_state_channel_name:
1113 idqstatevector = pipeparts.mkreblock(pipeline, pipeparts.mkaudiorate(pipeline, idqstatevector, skip_to_first=
True, silent=
False), block_duration = Gst.SECOND // 4)
1115 @bottle.route("/%s/strain_dropped.txt" % instrument)
1117 def strain_add(elem=src, rate=16384):
1118 t = float(lal.UTCToGPS(time.gmtime()))
1123 add = elem.get_property(
"add")
1124 return "%.9f %d" % (t, add // rate)
1133 statevector = pipeparts.mktee(pipeline, statevector)
1134 dqvector = pipeparts.mktee(pipeline, dqvector)
1135 src = pipeparts.mkgate(pipeline, src, threshold=1, control=pipeparts.mkqueue(pipeline, statevector, max_size_buffers=0, max_size_bytes=0, max_size_time=0),
1136 default_state=
False, name=
"%s_state_vector_gate" % instrument)
1137 src = pipeparts.mkgate(pipeline, src, threshold=1, control=pipeparts.mkqueue(pipeline, dqvector, max_size_buffers=0, max_size_bytes=0, max_size_time=0),
1138 default_state=
False, name=
"%s_dq_vector_gate" % instrument)
1141 if instrument
in gw_data_source_info.idq_channel_name:
1142 idqseries = pipeparts.mkgate(pipeline, idqseries, threshold=1, control=pipeparts.mkqueue(pipeline, statevector, max_size_buffers=0, max_size_bytes=0, max_size_time=0),
1143 default_state=
False, name=
"%s_idq_state_vector_gate" % instrument)
1144 idqseries = pipeparts.mkgate(pipeline, idqseries, threshold=1, control=pipeparts.mkqueue(pipeline, dqvector, max_size_buffers=0, max_size_bytes=0, max_size_time=0),
1145 default_state=
False, name=
"%s_idq_dq_vector_gate" % instrument)
1146 if instrument
in gw_data_source_info.idq_state_channel_name:
1147 idqseries = pipeparts.mkgate(pipeline, idqseries, threshold=1, control=pipeparts.mkqueue(pipeline, idqstatevector, max_size_buffers=0, max_size_bytes=0, max_size_time=0),
1148 default_state=
False, name=
"%s_idq_idqstate_vector_gate" % instrument)
1149 elif gw_data_source_info.data_source == DataSource.NDS:
1150 src = pipeparts.mkndssrc(pipeline, gw_data_source_info.nds_host, instrument, gw_data_source_info.channel_dict[instrument], gw_data_source_info.nds_channel_type,
1151 blocksize=gw_data_source_info.block_size, port=gw_data_source_info.nds_port)
1153 raise ValueError(
"invalid data_source: %s" % gw_data_source_info.data_source)
1160 src = pipeparts.mkaudioconvert(pipeline, src)
1167 src = pipeparts.mkprogressreport(pipeline, src,
"progress_src_%s" % instrument)
1173 if gw_data_source_info.injection_filename
is not None:
1174 src = pipeparts.mkinjections(pipeline, src, gw_data_source_info.injection_filename)
1177 src = pipeparts.mkqueue(pipeline, src, max_size_bytes=0, max_size_buffers=0, max_size_time=Gst.SECOND * 64)
1183 return src, statevector, dqvector, idqseries
1186def mkhtgate(pipeline, src, control=None, threshold=8.0, attack_length=128, hold_length=128, **kwargs):
1188 A convenience function to provide thresholds on input data. This can
1189 be used to remove large spikes / glitches etc. Of course you can use it for
1190 other stuff by plugging whatever you want as input and ouput
1192 NOTE: the queues constructed by this code assume the attack and
1193 hold lengths combined are less than 1 second in duration.
1201 node [shape=record fontsize=10 fontname="Verdana"];
1207 out [label="<return>"];
1208 in -> tee -> inputqueue -> lal_gate -> out;
1216 control = src = pipeparts.mktee(pipeline, src)
1217 src = pipeparts.mkqueue(pipeline, src, max_size_time=Gst.SECOND, max_size_bytes=0, max_size_buffers=0)
1218 return pipeparts.mkgate(pipeline, src, control=control, threshold=threshold, attack_length=-attack_length, hold_length=-hold_length, invert_control=
True, **kwargs)
1226@admin.deprecated('replaced by parse_list_to_dict')
1227def channel_dict_from_channel_list(channel_list):
1229 Given a list of channels, produce a dictionary keyed by ifo of channel names:
1231 The list here typically comes from an option parser with options that
1232 specify the "append" action.
1235 >>> channel_dict_from_channel_list(["H1=LSC-STRAIN", "H2=SOMETHING-ELSE"]) # doctest: +SKIP
1236 {'H1': 'LSC-STRAIN', 'H2': 'SOMETHING-ELSE'}
1238 return parse_list_to_dict(channel_list)
1241@admin.deprecated('replaced by parse_list_to_dict with key_is_range=True')
1242def channel_dict_from_channel_list_with_node_range(channel_list):
1244 Given a list of channels with a range of mass bins, produce a dictionary
1245 keyed by ifo of channel names:
1247 The list here typically comes from an option parser with options that
1248 specify the "append" action.
1251 >>> channel_dict_from_channel_list_with_node_range(["0000:0002:H1=LSC_STRAIN_1,L1=LSC_STRAIN_2", "0002:0004:H1=LSC_STRAIN_3,L1=LSC_STRAIN_4", "0004:0006:H1=LSC_STRAIN_5,L1=LSC_STRAIN_6"]) # doctest: +SKIP
1252 {'0000': {'H1': 'LSC_STRAIN_1', 'L1': 'LSC_STRAIN_2'}, '0001': {'H1': 'LSC_STRAIN_1', 'L1': 'LSC_STRAIN_2'}, '0002': {'H1': 'LSC_STRAIN_3', 'L1': 'LSC_STRAIN_4'}, '0003': {'H1': 'LSC_STRAIN_3', 'L1': 'LSC_STRAIN_4'}, '0004': {'H1': 'LSC_STRAIN_5', 'L1': 'LSC_STRAIN_6'}, '0005': {'H1': 'LSC_STRAIN_5', 'L1': 'LSC_STRAIN_6'}}
1255 for instrument_channel_full
in channel_list:
1256 instrument_channel_split = instrument_channel_full.split(
':')
1257 for ii
in range(int(instrument_channel_split[0]), int(instrument_channel_split[1])):
1258 outdict[str(ii).zfill(4)] = dict((instrument_channel.split(
"="))
for instrument_channel
in instrument_channel_split[2].split(
','))
1262@admin.deprecated('replaced by ravel_dict_to_list with join_arg="channel-name" and filter_keys=ifos')
1263def pipeline_channel_list_from_channel_dict(channel_dict, ifos=None, opt="channel-name"):
1265 Creates a string of channel names options from a dictionary keyed by ifos.
1267 FIXME: This function exists to work around pipeline.py's inability to
1268 give the same option more than once by producing a string to pass as an argument
1269 that encodes the other instances of the option.
1271 - override --channel-name with a different option by setting opt.
1272 - restrict the ifo keys to a subset of the channel_dict by
1276 >>> pipeline_channel_list_from_channel_dict({'H2': 'SOMETHING-ELSE', 'H1': 'LSC-STRAIN'}) # doctest: +SKIP
1277 'H2=SOMETHING-ELSE --channel-name=H1=LSC-STRAIN '
1279 >>> pipeline_channel_list_from_channel_dict({'H2': 'SOMETHING-ELSE', 'H1': 'LSC-STRAIN'}, ifos=["H1"]) # doctest: +SKIP
1282 >>> pipeline_channel_list_from_channel_dict({'H2': 'SOMETHING-ELSE', 'H1': 'LSC-STRAIN'}, opt="test-string") # doctest: +SKIP
1283 'H2=SOMETHING-ELSE --test-string=H1=LSC-STRAIN '
1287 ifos = channel_dict.keys()
1288 for i, ifo
in enumerate(ifos):
1290 outstr +=
"%s=%s " % (ifo, channel_dict[ifo])
1292 outstr +=
"--%s=%s=%s " % (opt, ifo, channel_dict[ifo])
1297@admin.deprecated('replaced by ravel_dict_to_list with key_is_range=True, range_elem=node, join_arg="channel-name", filter_keys=ifos')
1298def pipeline_channel_list_from_channel_dict_with_node_range(channel_dict, node=0, ifos=None, opt="channel-name"):
1300 Creates a string of channel names options from a dictionary keyed by ifos.
1302 FIXME: This function exists to work around pipeline.py's inability to
1303 give the same option more than once by producing a string to pass as an argument
1304 that encodes the other instances of the option.
1306 - override --channel-name with a different option by setting opt.
1307 - restrict the ifo keys to a subset of the channel_dict by.
1311 >>> pipeline_channel_list_from_channel_dict_with_node_range({'0000': {'H2': 'SOMETHING-ELSE', 'H1': 'LSC-STRAIN'}}, node=0) # doctest: +SKIP
1312 'H2=SOMETHING-ELSE --channel-name=H1=LSC-STRAIN '
1314 >>> pipeline_channel_list_from_channel_dict_with_node_range({'0000': {'H2': 'SOMETHING-ELSE', 'H1': 'LSC-STRAIN'}}, node=0, ifos=["H1"]) # doctest: +SKIP
1317 >>> pipeline_channel_list_from_channel_dict_with_node_range({'0000': {'H2': 'SOMETHING-ELSE', 'H1': 'LSC-STRAIN'}}, node=0, opt="test-string") # doctest: +SKIP
1318 'H2=SOMETHING-ELSE --test-string=H1=LSC-STRAIN '
1321 node = str(node).zfill(4)
1323 ifos = channel_dict[node].keys()
1324 for i, ifo
in enumerate(ifos):
1326 outstr +=
"%s=%s " % (ifo, channel_dict[node][ifo])
1328 outstr +=
"--%s=%s=%s " % (opt, ifo, channel_dict[node][ifo])
1333@admin.deprecated('replaced by parse_list_to_dict with key_is_range=True')
1334def injection_dict_from_channel_list_with_node_range(injection_list):
1336 Given a list of injection xml files with a range of mass bins, produce a
1337 dictionary keyed by bin number:
1339 The list here typically comes from an option parser with options that
1340 specify the "append" action.
1343 >>> injection_dict_from_channel_list_with_node_range(["0000:0002:Injection_1.xml", "0002:0004:Injection_2.xml"]) # doctest: +SKIP
1344 {'0000': 'Injection_1.xml', '0001': 'Injection_1.xml', '0002': 'Injection_2.xml', '0003': 'Injection_2.xml'}
1347 for injection_name
in injection_list:
1348 injection_name_split = injection_name.split(
':')
1349 for ii
in range(int(injection_name_split[0]), int(injection_name_split[1])):
1350 outdict[str(ii).zfill(4)] = injection_name_split[2]
1354@admin.deprecated('replaced by combination of zip_dict_values and parse_list_to_dict with value_transform=parse_int')
1355def state_vector_on_off_dict_from_bit_lists(on_bit_list, off_bit_list, state_vector_on_off_dict=DEFAULT_STATE_VECTOR_ON_OFF):
1357 Produce a dictionary (keyed by detector) of on / off bit tuples from a
1358 list provided on the command line.
1360 Takes default values from module level datasource.state_vector_on_off_dict
1361 if state_vector_on_off_dict is not given
1363 Inputs must be given as base 10 or 16 integers
1366 >>> on_bit_list = ["V1=7", "H1=7", "L1=7"] # doctest: +SKIP
1367 >>> off_bit_list = ["V1=256", "H1=352", "L1=352"] # doctest: +SKIP
1368 >>> state_vector_on_off_dict_from_bit_lists(on_bit_list, off_bit_list) # doctest: +SKIP
1369 {'H1': [7, 352], 'H2': [7, 352], 'L1': [7, 352], 'V1': [7, 256]}
1371 >>> state_vector_on_off_dict_from_bit_lists(on_bit_list, off_bit_list,{}) # doctest: +SKIP
1372 {'V1': [7, 256], 'H1': [7, 352], 'L1': [7, 352]}
1374 >>> on_bit_list = ["V1=0x7", "H1=0x7", "L1=0x7"] # doctest: +SKIP
1375 >>> off_bit_list = ["V1=0x256", "H1=0x352", "L1=0x352"] # doctest: +SKIP
1376 >>> state_vector_on_off_dict_from_bit_lists(on_bit_list, off_bit_list,{}) # doctest: +SKIP
1377 {'V1': [7, 598], 'H1': [7, 850], 'L1': [7, 850]}
1379 for ifo, bits
in [line.strip().split(
"=", 1)
for line
in on_bit_list]:
1380 bits = int(bits, 16)
if bits.startswith(
"0x")
else int(bits)
1382 state_vector_on_off_dict[ifo][0] = bits
1384 state_vector_on_off_dict[ifo] = [bits, 0]
1386 for ifo, bits
in [line.strip().split(
"=", 1)
for line
in off_bit_list]:
1387 bits = int(bits, 16)
if bits.startswith(
"0x")
else int(bits)
1389 state_vector_on_off_dict[ifo][1] = bits
1391 return state_vector_on_off_dict
1394@admin.deprecated('replaced by combination of ravel_dict_to_list with unzip=True and join_arg=["state-vector-on-bits", "state-vector-off-bits"]')
1395def state_vector_on_off_list_from_bits_dict(bit_dict):
1397 Produce a tuple of useful command lines from a dictionary of on / off state
1398 vector bits keyed by detector
1400 FIXME: This function exists to work around pipeline.py's inability to
1401 give the same option more than once by producing a string to pass as an argument
1402 that encodes the other instances of the option.
1405 >>> state_vector_on_off_dict = {"H1":[0x7, 0x160], "H2":[0x7, 0x160], "L1":[0x7, 0x160], "V1":[0x67, 0x100]} # doctest: +SKIP
1406 >>> state_vector_on_off_list_from_bits_dict(state_vector_on_off_dict) # doctest: +SKIP
1407 ('H1=7 --state-vector-on-bits=H2=7 --state-vector-on-bits=L1=7 --state-vector-on-bits=V1=103 ', 'H1=352 --state-vector-off-bits=H2=352 --state-vector-off-bits=L1=352 --state-vector-off-bits=V1=256 ')
1412 for i, ifo
in enumerate(bit_dict):
1414 onstr +=
"%s=%s " % (ifo, bit_dict[ifo][0])
1415 offstr +=
"%s=%s " % (ifo, bit_dict[ifo][1])
1417 onstr +=
"--state-vector-on-bits=%s=%s " % (ifo, bit_dict[ifo][0])
1418 offstr +=
"--state-vector-off-bits=%s=%s " % (ifo, bit_dict[ifo][1])
1420 return onstr, offstr
1423@admin.deprecated('replaced by parse_list_to_dict with value_transform=parse_host.')
1424def framexmit_dict_from_framexmit_list(framexmit_list):
1426 Given a list of framexmit addresses with ports, produce a dictionary keyed by ifo:
1428 The list here typically comes from an option parser with options that
1429 specify the "append" action.
1432 >>> framexmit_dict_from_framexmit_list(["H1=224.3.2.1:7096", "L1=224.3.2.2:7097", "V1=224.3.2.3:7098"]) # doctest: +SKIP
1433 {'H1': ('224.3.2.1', 7096), 'L1': ('224.3.2.2', 7097), 'V1': ('224.3.2.3', 7098)}
1436 for instrument_addr
in framexmit_list:
1437 ifo, addr_port = instrument_addr.split(
"=")
1438 addr, port = addr_port.split(
':')
1439 out.append((ifo, (addr, int(port))))
1443@admin.deprecated('replaced by ravel_dict_to_list with value_transform=ravel_host.')
1444def framexmit_list_from_framexmit_dict(framexmit_dict, ifos=None, opt="framexmit-addr"):
1446 Creates a string of framexmit address options from a dictionary keyed by ifos.
1449 >>> framexmit_list_from_framexmit_dict({'V1': ('224.3.2.3', 7098), 'H1': ('224.3.2.1', 7096), 'L1': ('224.3.2.2', 7097)}) # doctest: +SKIP
1450 'V1=224.3.2.3:7098 --framexmit-addr=H1=224.3.2.1:7096 --framexmit-addr=L1=224.3.2.2:7097 '
1454 ifos = framexmit_dict.keys()
1455 for i, ifo
in enumerate(ifos):
1457 outstr +=
"%s=%s:%s " % (ifo, framexmit_dict[ifo][0], framexmit_dict[ifo][1])
1459 outstr +=
"--%s=%s=%s:%s " % (opt, ifo, framexmit_dict[ifo][0], framexmit_dict[ifo][1])
1464@admin.deprecated('replaced by parse_list_to_dict.')
1465def frame_type_dict_from_frame_type_list(frame_type_list):
1467 Given a list of frame types, produce a dictionary keyed by ifo:
1469 The list here typically comes from an option parser with options that
1470 specify the "append" action.
1473 >>> frame_type_dict_from_frame_type_list(['H1=H1_GWOSC_O2_16KHZ_R1', 'L1=L1_GWOSC_O2_16KHZ_R1']) # doctest: +SKIP
1474 {'H1': 'H1_GWOSC_O2_16KHZ_R1', 'L1': 'L1_GWOSC_O2_16KHZ_R1'}
1477 for frame_opt
in frame_type_list:
1478 ifo, frame_type = frame_opt.split(
"=")
1479 out[ifo] = frame_type
data_source
if no frame segments provided, set them to an empty segment list dictionary
__init__(self, Union[str, DataSource] data_source, Dict[Detector, str] channel_name, Union[int, LIGOTimeGPS] gps_start_time=None, Union[int, LIGOTimeGPS] gps_end_time=None, Dict[Detector, str] shared_memory_partition=None, Dict[Detector, str] shared_memory_dir=None, str frame_segments_name=None, Dict[Detector, str] state_vector_on_bits=None, Dict[Detector, str] state_vector_off_bits=None, str dq_vector_on_bits=None, str dq_vector_off_bits=None, Union[str, Path] frame_cache=None, Union[str, Path] injections=None, str nds_host=None, int nds_port=None, str nds_channel_type='online', int shared_memory_assumed_duration=4, int shared_memory_block_size=4096, Union[str, Path] frame_segments_file=None, int block_size=DEFAULT_BLOCK_SIZE, Dict[Detector, str] frame_type=None, Union[str or DataFindServer] data_find_server=None, str framexmit_addr=None, str framexmit_iface=None, Dict[Detector, str] state_channel_name=None, Dict[Detector, str] dq_channel_name=None, Dict[Detector, str] idq_channel_name=None, Dict[Detector, str] idq_state_channel_name=None)
dict state_vector_off_bits
from_optparse(optparse.Values options)
dict state_vector_on_bits
frame_segments
if no frame segments provided, set them to an empty segment list dictionary
_frame_cache_fileobj
create a temporary cache file
shared_memory_assumed_duration
dict idq_state_channel_name