misc.py
5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
"""Routines for creating sub-elements of the VOEvent tree,
and a few other helper classes."""
from __future__ import absolute_import
from six import string_types
from collections import namedtuple
import datetime
from lxml import objectify, etree
class Position2D(namedtuple('Position2D', 'ra dec err units system')):
"""A namedtuple for simple representation of a 2D position as described
by the VOEvent spec.
Args:
ra (float): Right ascension.
dec (float): Declination
err (float): Error radius.
units (str): Coordinate units, cf :class:`.definitions.units`
e.g. degrees, radians.
system (str): Co-ordinate system, e.g. UTC-FK5-GEO
cf :class:`.definitions.sky_coord_system`
"""
pass # Just wrapping a namedtuple so we can assign a docstring.
_datatypes_autoconversion = {
bool: ('string', lambda b: str(b)),
int: ('int', lambda i: str(i)),
float: ('float', lambda f: str(f)),
datetime.datetime: ('string', lambda dt: dt.isoformat()),
}
def Param(name, value=None, unit=None, ucd=None, dataType=None, utype=None,
ac=True):
"""
'Parameter', used as a general purpose key-value entry in the 'What' section.
May be assembled into a :class:`Group`.
NB ``name`` is not mandated by schema, but *is* mandated in full spec.
Args:
value(string): String representing parameter value.
Or, if ``ac`` is true, then 'autoconversion' is attempted, in which case
``value`` can also be an instance of one of the following:
* :py:obj:`bool`
* :py:obj:`int`
* :py:obj:`float`
* :py:class:`datetime.datetime`
This allows you to create Params without littering your code
with string casts, or worrying if the passed value is a float or a
string, etc.
NB the value is always *stored* as a string representation,
as per VO spec.
unit(string): Units of value. See :class:`.definitions.units`
ucd(string): `unified content descriptor <http://arxiv.org/abs/1110.0525>`_.
For a list of valid UCDs, see:
http://vocabularies.referata.com/wiki/Category:IVOA_UCD.
dataType(string): Denotes type of ``value``; restricted to 3 options:
``string`` (default), ``int`` , or ``float``.
(NB *not* to be confused with standard XML Datatypes, which have many
more possible values.)
utype(string): See http://wiki.ivoa.net/twiki/bin/view/IVOA/Utypes
ac(bool): Attempt automatic conversion of passed ``value`` to string,
and set ``dataType`` accordingly (only attempted if ``dataType``
is the default, i.e. ``None``).
(NB only supports types listed in _datatypes_autoconversion dict)
"""
# We use locals() to allow concise looping over the arguments.
atts = locals()
atts.pop('ac')
temp_dict={}
temp_dict.update(atts)
for k in temp_dict.keys():
if atts[k] is None:
del atts[k]
if (ac
and value is not None
and (not isinstance(value, string_types))
and dataType is None
):
if type(value) in _datatypes_autoconversion:
datatype, func = _datatypes_autoconversion[type(value)]
atts['dataType'] = datatype
atts['value'] = func(value)
return objectify.Element('Param', attrib=atts)
def Group(params, name=None, type=None):
"""Groups together Params for adding under the 'What' section.
Args:
params(list of :func:`Param`): Parameter elements to go in this group.
name(string): Group name. NB ``None`` is valid, since the group may be
best identified by its type.
type(string): Type of group, e.g. 'complex' (for real and imaginary).
"""
atts = {}
if name:
atts['name'] = name
if type:
atts['type'] = type
g = objectify.Element('Group', attrib=atts)
for p in params:
g.append(p)
return g
def Reference(uri, meaning=None):
"""
Represents external information, typically original obs data and metadata.
Args:
uri(string): Uniform resource identifier for external data, e.g. FITS file.
meaning(string): The nature of the document referenced, e.g. what
instrument and filter was used to create the data?
"""
attrib = {'uri': uri}
if meaning is not None:
attrib['meaning'] = meaning
return objectify.Element('Reference', attrib)
def Inference(probability=None, relation=None, name=None, concept=None):
"""Represents a probable cause / relation between this event and some prior.
Args:
probability(float): Value 0.0 to 1.0.
relation(string): e.g. 'associated' or 'identified' (see Voevent spec)
name(string): e.g. name of identified progenitor.
concept(string): One of a 'formal UCD-like vocabulary of astronomical
concepts', e.g. http://ivoat.ivoa.net/stars.supernova.Ia - see
VOEvent spec.
"""
atts = {}
if probability is not None:
atts['probability'] = str(probability)
if relation is not None:
atts['relation'] = relation
inf = objectify.Element('Inference', attrib=atts)
if name is not None:
inf.Name = name
if concept is not None:
inf.Concept = concept
return inf
def Citation(ivorn, cite_type):
"""Used to cite earlier VOEvents.
Args:
ivorn(string): It is assumed this will be copied verbatim from elsewhere,
and so these should have any prefix (e.g. 'ivo://','http://')
already in place - the function will not alter the value.
cite_type (:class:`.definitions.cite_types`): String conforming to one
of the standard citation types.
"""
# This is an ugly hack around the limitations of the lxml.objectify API:
c = objectify.StringElement(cite=cite_type)
c._setText(ivorn)
c.tag = "EventIVORN"
return c