22 Code to assist in reading and writing LAL time- and frequency series data
23 encoded in LIGO Light-Weight XML format. The format recognized by the code
24 in this module is the same as generated by the array-related functions in
25 LAL's XML I/O code. The format is also very similar to the format used by
26 the DMT to store time- and frequency-series data in XML files,
30 from ligo.lw
import ligolw
31 from ligo.lw
import array
as ligolw_array
32 from ligo.lw
import param
as ligolw_param
38 Attributes = ligolw.sax.xmlreader.AttributesImpl
50 def _build_series(series, dim_names, comment, delta_name, delta_unit):
51 elem = ligolw.LIGO_LW(
Attributes({
u"Name": six.text_type(series.__class__.__name__)}))
52 if comment
is not None:
53 elem.appendChild(ligolw.Comment()).pcdata = comment
54 elem.appendChild(ligolw.Time.from_gps(series.epoch,
u"epoch"))
55 elem.appendChild(ligolw_param.Param.from_pyvalue(
u"f0", series.f0, unit=
u"s^-1"))
56 delta = getattr(series, delta_name)
57 if np.iscomplexobj(series.data.data):
58 data = np.row_stack((np.arange(len(series.data.data)) * delta, series.data.data.real, series.data.data.imag))
60 data = np.row_stack((np.arange(len(series.data.data)) * delta, series.data.data))
61 a = ligolw_array.Array.build(series.name, data, dim_names=dim_names)
62 a.Unit = str(series.sampleUnits)
63 dim0 = a.getElementsByTagName(ligolw.Dim.tagName)[0]
64 dim0.Unit = delta_unit
65 dim0.Start = series.f0
71 def _parse_series(elem, creatorfunc, delta_target_unit_string):
72 t, = elem.getElementsByTagName(ligolw.Time.tagName)
73 a, = elem.getElementsByTagName(ligolw.Array.tagName)
74 dims = a.getElementsByTagName(ligolw.Dim.tagName)
75 f0 = ligolw_param.get_param(elem,
u"f0")
78 raise ValueError(
"epoch Type must be GPS")
82 inverse_seconds_unit = lal.Unit(
"s^-1")
84 delta_target_unit = lal.Unit(delta_target_unit_string)
87 f0_unit = lal.Unit(str(f0.Unit))
90 delta_unit = lal.Unit(str(dims[0].Unit))
93 sample_unit = lal.Unit(str(a.Unit))
99 f0.pcdata * float(f0_unit / inverse_seconds_unit),
100 dims[0].Scale * float(delta_unit / delta_target_unit),
106 if np.iscomplexobj(series.data.data):
107 series.data.data = a.array[1] + 1j * a.array[2]
109 series.data.data = a.array[1]
116 assert isinstance(series, lal.REAL4FrequencySeries)
117 return _build_series(series, (
u"Frequency,Real",
u"Frequency"), comment,
'deltaF',
's^-1')
121 return _parse_series(elem, lal.CreateREAL4FrequencySeries,
"s^-1")
125 assert isinstance(series, lal.REAL8FrequencySeries)
126 return _build_series(series, (
u"Frequency,Real",
u"Frequency"), comment,
'deltaF',
's^-1')
130 return _parse_series(elem, lal.CreateREAL8FrequencySeries,
"s^-1")
134 assert isinstance(series, lal.COMPLEX8FrequencySeries)
135 return _build_series(series, (
u"Frequency,Real,Imaginary",
u"Frequency"), comment,
'deltaF',
's^-1')
139 return _parse_series(elem, lal.CreateCOMPLEX8FrequencySeries,
"s^-1")
143 assert isinstance(series, lal.COMPLEX16FrequencySeries)
144 return _build_series(series, (
u"Frequency,Real,Imaginary",
u"Frequency"), comment,
'deltaF',
's^-1')
148 return _parse_series(elem, lal.CreateCOMPLEX16FrequencySeries,
"s^-1")
152 assert isinstance(series, lal.REAL4TimeSeries)
153 return _build_series(series, (
u"Time,Real",
u"Time"), comment,
'deltaT',
's')
157 return _parse_series(elem, lal.CreateREAL4TimeSeries,
"s")
161 assert isinstance(series, lal.REAL8TimeSeries)
162 return _build_series(series, (
u"Time,Real",
u"Time"), comment,
'deltaT',
's')
166 return _parse_series(elem, lal.CreateREAL8TimeSeries,
"s")
170 assert isinstance(series, lal.COMPLEX8TimeSeries)
171 return _build_series(series, (
u"Time,Real,Imaginary",
u"Time"), comment,
'deltaT',
's')
175 return _parse_series(elem, lal.CreateCOMPLEX8TimeSeries,
"s")
179 assert isinstance(series, lal.COMPLEX16TimeSeries)
180 return _build_series(series, (
u"Time,Real,Imaginary",
u"Time"), comment,
'deltaT',
's')
184 return _parse_series(elem, lal.CreateCOMPLEX16TimeSeries,
"s")
198 Construct an XML document tree representation of a dictionary of
199 frequency series objects containing PSDs. See also read_psd_xmldoc()
200 for a function to parse the resulting XML documents.
202 If xmldoc is None (the default), then a new XML document is created and
203 the PSD dictionary added to it inside a LIGO_LW element. If xmldoc is
204 not None then the PSD dictionary is appended to the children of that
205 element inside a new LIGO_LW element. In both cases, the LIGO_LW
206 element's Name attribute is set to root_name. This will be looked for
207 by read_psd_xmldoc() when parsing the PSD document.
210 xmldoc = ligolw.Document()
211 lw = xmldoc.appendChild(ligolw.LIGO_LW(
Attributes({
u"Name": root_name})))
212 for instrument, psd
in psddict.items():
214 if instrument
is not None:
215 fs.appendChild(ligolw_param.Param.from_pyvalue(
u"instrument", instrument))
221 Parse a dictionary of PSD frequency series objects from an XML
222 document. See also make_psd_xmldoc() for the construction of XML
223 documents from a dictionary of PSDs. Interprets an empty frequency
224 series for an instrument as None.
226 The XML document tree is searched for a LIGO_LW element whose Name
227 attribute is root_name (default is "psd"). If root_name is None all
228 REAL8Frequency series objects below xmldoc are included in the return
231 if root_name
is not None:
232 xmldoc, = (elem
for elem
in xmldoc.getElementsByTagName(ligolw.LIGO_LW.tagName)
if elem.hasAttribute(
u"Name")
and elem.Name == root_name)
233 result = dict((ligolw_param.get_pyvalue(elem,
u"instrument"),
parse_REAL8FrequencySeries(elem))
for elem
in xmldoc.getElementsByTagName(ligolw.LIGO_LW.tagName)
if elem.hasAttribute(
u"Name")
and elem.Name ==
u"REAL8FrequencySeries")
235 for instrument
in result:
236 if len(result[instrument].data.data) == 0:
237 result[instrument] =
None
243 class PSDContentHandler(ligolw.LIGOLWContentHandler):
244 """A content handler suitable for reading PSD documents. Use like this:
246 >>> from ligo.lw.utils import load_filename
247 >>> xmldoc = load_filename('psd.xml', contenthandler=PSDContentHandler)
248 >>> psds = read_psd_xmldoc(xmldoc)
def read_psd_xmldoc(xmldoc, root_name=u"psd")
Parse a dictionary of PSD frequency series objects from an XML document.
def parse_REAL4TimeSeries(elem)
def build_COMPLEX8FrequencySeries(series, comment=None)
def build_COMPLEX8TimeSeries(series, comment=None)
def build_REAL4FrequencySeries(series, comment=None)
def parse_COMPLEX16FrequencySeries(elem)
def build_REAL8TimeSeries(series, comment=None)
def parse_COMPLEX16TimeSeries(elem)
def build_REAL4TimeSeries(series, comment=None)
def make_psd_xmldoc(psddict, xmldoc=None, root_name=u"psd")
Construct an XML document tree representation of a dictionary of frequency series objects containing ...
def parse_REAL8FrequencySeries(elem)
def parse_COMPLEX8TimeSeries(elem)
def parse_REAL4FrequencySeries(elem)
def build_REAL8FrequencySeries(series, comment=None)
def build_COMPLEX16TimeSeries(series, comment=None)
def parse_COMPLEX8FrequencySeries(elem)
def build_COMPLEX16FrequencySeries(series, comment=None)
def parse_REAL8TimeSeries(elem)