20Parse identified and unidentified line files following the O3a convention.
22The identified lines file contains detector spectral artifacts (lines and combs)
23verified to be non-astrophysical in origin.
24Each line of the file identifies an artifact with certain fundamental frequency,
25(possibly non-identical) frequency wings,
26the number of visible harmonics (if identified as a comb),
27the scaling of the affected band with harmonics (constant or linearly scaling),
28and a systematic off-set with respect to the specified frequency.
30The unidentified lines file contains spectral artifacts that cannot yet be
31convincingly associated with non-astrophysical detector noise.
32These files only list the frequency of the most prominent peak.
34This module provides a class, `LineFileParser`, to seamlessly read those files and return
35the list of lines as a list of [left_most_line_frequency, right_most_line_frequency]
37This format is easier to use for example when applying line vetoes on CW outliers.
39Input files are fed into the class using `LineFileParser.parse_identified_lines_csv` or
40`LineFileParser.parse_unidentified_lines_csv`.
41Intervals are accesible through attributes `LineFileParser.lines_left_side` and
42`LineFileParser.lines_right_side`.
43If several files are read, their resulting intervals are concatenated
44(but not sorted, and duplicate or overlapping entries are kept as they are).
50from .
import git_version
52__author__ =
"Rodrigo Tenorio <rodrigo.tenorio@ligo.org>"
53__version__ = git_version.id
54__date__ = git_version.date
60 This
class is taylored to work using the O3 - era line files.
61 There are essentially two types of these files,
62 their main difference being the number of columns.
66 - frequency: Column containing the central frequency of the line.
67 - left_wing: Column containing the frequency limit towards
68 lower frequencies of the line
as a width (central frequency - low frequency limit) Hz.
69 - right_wing: Column containing the frequency limit towards
70 higher frequencies of the line
as a width (high frequency limit - central frequency) Hz.
71 - first_harmonic: Column
with the index of the first visible harmonic of the line.
72 - last_harmonic: Column
with the index of the last visible harmonic of the line.
73 - comb_type: Column containing line type
74 (0=single line, 1=comb,
or 2=comb whose width scales
with the harmonic number).
75 - offset: Column
with the frequency line off-set.
79 - frequency: Column containing the central frequency of the line.
82 default_genfromtxt_kwargs = {"delimiter":
",",
"skip_header": 4}
83 identified_lines_keys = {
93 unidentified_lines_keys = {
"frequency": 0}
97 Read and expand line files into frequency intervals.
98 If multiple files are read, resulting interval are concatenated.
100 Intervals can be retrieved using the attributes `lines_left_side`
and `lines_right_side`.
108 def _check_columns(self, columns, default_keys):
109 columns = columns
or default_keys
110 if not all(key
in columns
for key
in default_keys):
112 f
"`columns` dictionary {columns} does not contain "
113 f
"all of the required keys: {list(default_keys.keys())}"
118 self, lines_file, columns=None, extra_wing_Hz=0.0, genfromtxt_kwargs=None
121 Parse a csv file containing lines of known origin (Advanced LIGO format).
123 @param lines_file: Path to csv format lines file.
124 @param columns: Dictionary
with header fields
as key
125 and the corresponding (0-based) column index
as value.
126 If
None, default ordering specified
in the
class attribute will be used.
127 @param extra_wing_Hz: Extra wings to add at both sides of the resulting intervals,
in Hz.
128 @param genfromtxt_kwargs: kwargs to be passed to numpy.genfromtxt.
129 Default
is `delimiter=
",", skip_header=4`.
135 lines_file, columns, genfromtxt_kwargs
139 *expanded_lines_and_wings, extra_wing_Hz
142 self._set_lines(lines_left_side, lines_right_side)
145 self, lines_file, columns=None, extra_wing_Hz=0.0, genfromtxt_kwargs=None
148 Parse a csv file containing unidentified lines (Advanced LIGO format).
150 @param lines_file: Path to csv format lines file.
151 @param columns: Dictionary
with header fields
as key
152 and the corresponding (0-based) column index
as value.
153 If
None, default ordering specified
in the
class attribute will be used.
154 @param extra_wing_Hz: Extra wings to add at both sides of the resulting intervals,
in Hz.
155 @param genfromtxt_kwargs: kwargs to be passed to numpy.genfromtxt.
156 Default
is `delimiter=
",", skip_header=4`.
160 unidentified_lines = np.genfromtxt(
167 unidentified_lines, 0.0, 0.0, extra_wing_Hz
169 self.
_set_lines(lines_left_side, lines_right_side)
171 def _get_identified_lines_center_left_right(
172 self, lines_file, columns, genfromtxt_kwargs=None
174 lines_with_wings = np.genfromtxt(
181 def _set_lines(self, lines_left_side, lines_right_side):
183 Properly add left and right boundaries to the
class attributes.
184 That means concatenating instead of overwriting
if a list of lines
185 has been already read. This may happen e.g. when reading identified
186 and unidentified line file.
200 def _expand_harmonics(
211 Known line files contain only one of the harmonics of the lines. This method
212 expands those harmonics, explicitely adding frequencies and wings to the line
213 list
in order to apply the veto.
215 Comb type are used to properly re-scale harmonic wings. As of now (O3a),
216 0 means line, 1 means non-scaling
and 2 means scaling.
218 Offsets shift the whole left-center-right structure
as an overall adding term.
220 harmonics_per_line = (last_harmonic - first_harmonic + 1).astype(np.int32)
221 total_number_of_lines = np.sum(harmonics_per_line, dtype=np.int32)
223 expanded_central_frequency = np.zeros(total_number_of_lines)
224 expanded_left_wing = np.zeros(total_number_of_lines)
225 expanded_right_wing = np.zeros(total_number_of_lines)
228 dont_scale_wings = comb_type != 2
231 for line
in range(len(central_frequency)):
232 harmonic_index = np.arange(first_harmonic[line], last_harmonic[line] + 1)
234 np.ones(harmonics_per_line[line])
235 if dont_scale_wings[line]
239 expanded_central_frequency[
240 line_pointer : line_pointer + harmonics_per_line[line]
241 ] = (harmonic_index * central_frequency[line] + offset[line])
243 line_pointer : line_pointer + harmonics_per_line[line]
244 ] = (wing_scaling * left_wing[line])
246 line_pointer : line_pointer + harmonics_per_line[line]
247 ] = (wing_scaling * right_wing[line])
249 line_pointer += harmonics_per_line[line]
251 return expanded_central_frequency, expanded_left_wing, expanded_right_wing
253 def _add_frequency_wings(self, central_frequency, left_wing, right_wing, extra_Hz):
255 Given a line frequency and its wings, convert to a range of frequencies
256 occupied by the line. Extra bins are added according to the specified
259 lines_left_side = central_frequency - left_wing - extra_Hz
260 lines_right_side = central_frequency + right_wing + extra_Hz
261 return lines_left_side, lines_right_side
def _add_frequency_wings(self, central_frequency, left_wing, right_wing, extra_Hz)
dictionary identified_lines_keys
def _set_lines(self, lines_left_side, lines_right_side)
def __init__(self)
Read and expand line files into frequency intervals.
def parse_identified_lines_csv(self, lines_file, columns=None, extra_wing_Hz=0.0, genfromtxt_kwargs=None)
Parse a csv file containing lines of known origin (Advanced LIGO format).
dictionary default_genfromtxt_kwargs
dictionary unidentified_lines_keys
def _get_identified_lines_center_left_right(self, lines_file, columns, genfromtxt_kwargs=None)
def _expand_harmonics(self, central_frequency, left_wing, right_wing, first_harmonic, last_harmonic, comb_type, offset)
def parse_unidentified_lines_csv(self, lines_file, columns=None, extra_wing_Hz=0.0, genfromtxt_kwargs=None)
Parse a csv file containing unidentified lines (Advanced LIGO format).
def _check_columns(self, columns, default_keys)