Blame view

install/windows/voeventparse/misc.py 5.95 KB
a86c87a7   jeremy   update for windows
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
"""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